从最嵌套的循环继续最外层循环

时间:2014-07-07 20:24:58

标签: loops sap nested-loops abap

有没有办法从ABAP中最嵌套的循环中继续最外层循环?

Java中的示例。这种语言中有一个使用标签的构造(大多数人还不知道它),它允许我从嵌套的循环中继续最外层的循环。

public class NestedLoopContinue {
    public static void main(String[] args) {    
        label1: for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 2; j++) {
                if (i == 3) {
                    continue label1;
                }
            }
            System.out.println(i + 1);
        }
    }
}

此输出

1
2
3
5

现在,我怎么能以聪明的方式在ABAP中做到这一点?一种解决方案是使用TRY. ENDTRY.块,但它更像是一个黑客攻击。还有其他想法吗?

DATA: l_outer_counter TYPE i.
DO 5 TIMES.
  l_outer_counter = sy-index.
  TRY.
    DO 2 TIMES.
      IF l_outer_counter = 4.
        RAISE EXCEPTION TYPE cx_abap_random.
      ENDIF.
    ENDDO.
    WRITE / l_outer_counter.
    CATCH cx_abap_random.
      CONTINUE.
  ENDTRY.
ENDDO.

或许有一种方法可以判断DO. ENDO.是否以EXIT语句结束(当然没有引入自己的变量,如SYST全局变量)?

DATA: l_outer_counter TYPE i.
DO 5 TIMES.
  l_outer_counter = sy-index.
  DO 2 TIMES.
    IF l_outer_counter = 4.
      EXIT.
    ENDIF.
  ENDDO.
  IF sy-last_loop_ended_with_exit = abap_true. "???
    CONTINUE.
  ENDIF.
  WRITE / l_outer_counter.
ENDDO.

3 个答案:

答案 0 :(得分:10)

我不知道特定于ABAP的解决方案,但我之前使用过通用编程解决方案来解决这个问题。只需使用布尔值并在内循环的末尾检查是否继续。

在Java中:

public class NestedLoopContinue
{
    public static void main(String[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            boolean earlyBreak = false;
            for (int j = 0; j < 2; j++)
            {
                if (i == 3)
                {
                    earlyBreak = true;
                    break;
                }
            }
            if (earlyBreak)
            {
               continue;
            }
            System.out.println(i + 1);
        }
    }
}

在ABAP:

DATA: l_outer_counter type i,
      early_break type FLAG.

DO 5 TIMES.
  l_outer_counter = sy-index.

  DO 2 TIMES.
      IF l_outer_counter = 4.
       early_break = ABAP_TRUE.
       EXIT.
      ENDIF.
  ENDDO.

  IF early_break = ABAP_TRUE.
      CLEAR early_break.
      CONTINUE.
  ENDIF.

  WRITE / l_outer_counter.

ENDDO.

我已经读过Java首先存在基于标签的中断的原因是因为GOTO语句没有明确地这样做,并且基于标签的break所涵盖的案例是为数不多的“好”之一使用团队想要维护的GOTO

但总的来说,这是一个非常尴尬的结构。是否没有可能的方法来重构您的代码(可能交换循环的内部),以便首先消除对此的需求?

答案 1 :(得分:4)

当使用嵌套循环时,我经常找到提高可读性的最佳方法,并避免使用更多不寻常的方法(例如打破标签,这不仅因为它具有类似goto的性质而引起争议,而且还会降低可读性因为很多人不熟悉它们是将内循环提取到一个单独的函数中。我不知道在ABAP中是如何完成的,但重构的Java等价物将是:

public class NestedLoopContinue {

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            NestedLoopContinue.innerLoop(i)
        }
    }

    static void innerLoop(int i) {
        for (int j = 0; j < 2; j++) {
            if (i == 3) {
                return;
            }
        }
        System.out.println(i + 1);
    }
}

我认为在这个例子中,这实际上变得不那么可读,因为在两个方法中遵循逻辑更难。但是,如果这是一个真实世界的例子(其中方法和变量具有一些实际意义和适当的名称),那么将内部循环提取到单独的方法中的结果将比使用标签更具可读性。

答案 2 :(得分:-1)

根据robjohncox答案,ABAP代码可能如下所示。

CLASS lcl_nested_loop_continue DEFINITION FINAL.
  PUBLIC SECTION.
    CLASS-METHODS:
      main.
  PRIVATE SECTION.
    CLASS-METHODS:
      inner_loop
        IMPORTING
          i_index TYPE i.
ENDCLASS.

CLASS lcl_nested_loop_continue IMPLEMENTATION.
  METHOD main.
    DO 5 TIMES.
      lcl_nested_loop_continue=>inner_loop( sy-index ).
    ENDDO.
  ENDMETHOD.

  METHOD inner_loop.
    DO 2 TIMES.
      IF i_index = 4.
        RETURN.
      ENDIF.
    ENDDO.
    WRITE / i_index.
  ENDMETHOD.
ENDCLASS.