【问题标题】:How does continue work?继续如何工作?
【发布时间】:2014-09-19 17:39:13
【问题描述】:

我试图了解“继续”的工作原理。我理解关键字的概念,但是当我运行不同的程序时,它的工作方式不同:-/ 让我给你举几个例子:

如果我运行这个程序:

int j = 0;
int i = 0;
LABEL1: for (; i < 3; i++) {
  if (true)
    continue;
}

i 的值将是 3。到目前为止一切顺利。 让我们添加一个外循环:

int j = 0;
int i = 0;
LABEL2: for (; j < 3; j++) {
  LABEL1: for (; i < 3; i++) {
    if (true)
      continue LABEL2;
  }
}

i 的值将是... 0 !! 我不明白如果 continue 与进入外循环的标签一起使用,为什么 i 不递增。有人可以解释为什么吗? 你有一些像 break 那样棘手的事情吗?还是用 do {} while ?

非常感谢您提供的任何帮助。

【问题讨论】:

  • i 永远不会增加 bc 你继续外循环
  • 继续使用标签将转到标签指示的位置。这里 continue 跳转到 LABEL2,所以 i++ 没有被执行。
  • 谢谢大家!我明白了。你帮了我很多!我刚刚发现了一些可以帮助其他人理解 continue 如何与循环一起工作的东西: continue 导致控制流跳转到循环条件(for while、do while 循环)或更新(for for 循环)。这会导致控制流跳转到下一次迭代。嘿,是否可以将其标记为已解决?
  • @user3884432 为了“将其标记为已解决”,只需从下面接受您最喜欢的答案。有很多好的。如果你不喜欢他们,写下你自己的答案并接受。
  • 实际上,continue 将您分支到循环的末尾,就在关闭 } 之前。这会导致循环条件被重新评估,就像您的程序流“落入”到循环底部一样。在continue label; 的情况下,控制转移到label: 标识的循环底部。

标签: java for-loop while-loop break continue


【解决方案1】:
continue LABEL2; 

导致只有外循环增加。如果你有

LABEL2 : for(;j <3;j++){
    LABEL1 : for(;i < 3; i++){
             if (true)
                 continue LABEL1;
             }
     }

i 会增加。

【讨论】:

    【解决方案2】:

    i 将在内循环结束时增加。但是continue LABEL2跳出内循环,到外循环结束,所以i没有增加;而是只增加j,直到不再满足外部循环条件。

    也许当我们用while 循环重写代码时会更清楚:

    int j=0;
    int i = 0;
    while (j<3) {
        while(i<3) {
           if (true)
               goto END_OF_LOOP2;
    
           END_OF_LOOP1: i++;
        }
        END_OF_LOOP2: j++;
    }
    

    【讨论】:

      【解决方案3】:

      for的基本语句结构如下:

      BasicFor 语句: for ( [ForInit] ; [Expression] ; [ForUpdate] ) 语句

      现在,来自JLS §14.14.1.3. Abrupt Completion of for Statement:

      如果 Statement 的执行由于 continue 没有标签而突然完成,则依次执行以下两个步骤:

      1. 首先,如果存在ForUpdate部分,则表达式从左到右依次计算;它们的值(如果有)将被丢弃。如果 ForUpdate 部分不存在,则不执行任何操作。

      2. 其次,执行另一个for迭代步骤。

      如果 Statement 的执行由于带有标签 L 的 continue 而突然完成,那么有一个选择:

      • 如果for语句有标签L,则依次执行以下两步:

        1. 首先,如果存在 ForUpdate 部分,则表达式按从左到右的顺序进行计算;它们的值(如果有)将被丢弃。如果 ForUpdate 不存在,则不执行任何操作。

        2. 其次,执行另一个for迭代步骤。

      • 如果for 语句没有标签L,则for 语句会因为使用标签L 继续而突然完成。

      (强调我的)

      ForUpdate,就您而言,是i++。综上所述:

      • 您的第一个 sn-p 属于第一种情况,因此 i 递增。

      • 您的第二个 sn-p 属于第二种情况,因此 i 不会递增,因为 for 语句突然完成。

      请注意,如果您在第二个 sn-p 中有 continue LABEL1,i 将像在您的第一个 sn-p 中一样递增(根据 JLS)。

      作为未来的提示,对于有关语言规则/语义的明确答案,您应该始终查阅语言规范。对于 Java,那就是 JLS。

      【讨论】:

      • 人们可能还注意到 14.14.1.2 指定 [Expression] 的评估是迭代步骤的一部分。否则,对规范的幼稚阅读可能表明 sn-p 都不应该终止。
      【解决方案4】:

      这真的很正常。执行流程是这样的:

      1. j=0
      2. i=0
      3. 进入 LABEL 2 循环,
      4. 进入了 LABEL 1 循环,
      5. 继续标签 2
      6. j++
      7. 进入了 LABEL 1 循环,
      8. 继续标签 2
      9. j++
      10. 进入了 LABEL 1 循环,
      11. 继续标签 2 ...直到 j==3

      【讨论】:

      • 这将有助于展示第一个 sn-p 中的不同之处。
      • 这不值得赞成。它没有解释 continue 的作用。显示执行流程不是答案
      • @VinceEmigh 这很有用,而且在评论中格式化得很好。如果您认为它不适合作为答案,可能会成为一个很好的元主题。
      • 对于顶级答案,流程图将大大提高该答案的可读性。事实上,它相当拥挤。
      • 其实我想说明的是,这里的问题不是 continue 是如何工作的,而是 for 如何工作的。
      【解决方案5】:

      如果你在调试模式下运行它,你会看到会发生什么。简而言之,每当您进入内循环以递增i 时,您将改为将continue 改为LABEL2,而不是递增i 并进入内循环的下一次迭代。

      因此,您将在外循环 3 次,并且您将永远不会在内循环中点击 i++。

      如果更简单,可以将内部 for 循环想象为 while 循环:

      int i = 0, j = 0;
      LABEL2: for (; j < 3; j++) {
        LABEL1: while (i < 3) {
          if (true) {
            continue LABEL2;
          }
      
          i++;
        }
      }
      

      【讨论】:

        【解决方案6】:

        Continue 只是顾名思义,它立即继续执行下一个循环,而不执行循环中的其余代码。

        所以如果你有这样的循环:

        int j=0;
        int i = 0;
            LABEL1 : for(;i < 3; i++){
                if (true) {
                    continue;
                }
                someOtherMethod();
            }
        

        someOtherMethod 部分永远不会执行,因为您总是会点击 continue。

        您的计数器从不增加的原因与标签有关,您可以使用标签标记循环(在您的情况下为 LABEL1 和 LABEL2 并使用该标签继续您的内部循环的外部循环之一.

        因此,对于您的代码,LABEL1 的循环永远不会有机会增加其计数器,因此i 仍然是0,因为您的 continue 语句会立即继续到外循环的下一次迭代。

        【讨论】:

          【解决方案7】:

          如果这是代码, 例如:

              int main (){
                // Local variable declaration:
          
              int a = 10;
          
             // do loop execution
            do
            {
               if( a == 15)
               {
                  // skip the iteration.
                  a = a + 1;
                  continue;
                }
                cout << "value of a: " << a << endl;
                     a = a + 1;
                   }while( a < 20 );
                   return 0;
               }
          

          那么结果会是

          value of a: 10
          value of a: 11
          value of a: 12
          value of a: 13
          value of a: 14
          value of a: 16
          value of a: 17
          value of a: 18
          value of a: 19
          

          注意事项: “a 的值:15”不在输出中。 编程语言中的 continue 会跳过循环中的特定行,如果使用了“break”,那么 break 会在“14”之后离开该行(在这种情况下)。
          为了您的理解,请看以下流程图:

          【讨论】:

            【解决方案8】:

            i 在下次检查条件时递增。

            如果您 continue 或 break 循环,则不会再次检查条件,并且永远不会增加 i 的值。

            为

            LABEL1 : for(;i < 3; i++){
                           if (true)
                               continue;
                         }
            

            当您继续时,您将再次检查 i 的值是否小于 3,然后再检查条件编译器在内部增加 i 的值。

            这里

            LABEL2 : for(;j <3;j++){
                    LABEL1 : for(;i < 3; i++){
                             if (true)
                                 continue LABEL2;
                             }
                     }
            

            当您执行continue 时,Label1 的条件永远不会再次检查,并且会直接转到带有Label2 的语句,因此它永远不会增加。

            休息也是如此

            LABEL1 : for(;i < 3; i++){
                           if (true)
                               break;
                         }
            

            如果您执行上述代码,i 的值将是0 而不是1。

            【讨论】:

              【解决方案9】:

              不带标签的continue 语句将从条件重新执行最里面的while 或do 或循环,并从更新表达式重新执行最里面的for 循环。它通常用于提前终止循环的处理,从而避免深度嵌套的 if 语句。在下面的例子中 continue 将得到下一行,而不在循环中处理下面的语句。

              while (getNext(line)) {
                if (line.isEmpty() || line.isComment())
                  continue;
                // More code here
              }
              

              带有标签的 continue 将以相同的方式执行相应标签的循环。这可以用来逃避深度嵌套的循环,或者只是为了清楚起见。如果你真的很反常,你也可以用它来模拟有限形式的goto。在以下示例中,continue 将重新执行 for (;;) 循环。

              aLoopName: for (;;) {
                // ...
                while (someCondition)
                // ...
                  if (otherCondition)
                    continue aLoopName;
              

              有时continue 也用作占位符,以使空循环体更清晰。

              for (count = 0; foo.moreData(); count++)   continue;
              

              没有label 的相同语句也存在于C 和C++ 中。在 Perl 中,它被命名为 next。

              source

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-02-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-07-28
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多