【问题标题】:Is there a way to break a superordinate loop in C?有没有办法打破C中的上级循环?
【发布时间】:2011-11-07 14:04:29
【问题描述】:

假设你有两个这样的嵌套 for 循环:

int i, j;    // Iterators

for(i=0; i<100; ++i) {
     /* do some stuff */
     ...
     for(j=0; j<99; ++j) {
         /* do more stuff */
         ...
         if( someFunction(j,i) == 2 ) {
             /* break out of both loops */
         }
     }
}

有没有办法(类似于break; 命令在一个循环中)在现场结束两个循环?

【问题讨论】:

  • goto 很方便。
  • @robjb 我怀疑它是。这是goto 非常好的情况之一。对goto的无条件仇恨是错误的。
  • 你可以将其重构为一个函数并调用return
  • 绝对不是。这是C。只要goto 完全 跳出两个循环(最好是 它们之后),它是可以接受的。在循环内跳转有点争议,而且很难做到正确:) @robjb
  • @robjb 这不是玩笑; goto 是这样做的唯一方法,没有非教条式的理由不使用它。

标签: c loops


【解决方案1】:

您可以将goto 用作:

int i, j;    // Iterators

for(i=0; i<100; ++i) {
     /* do some stuff */
     ...
     for(j=0; j<99; ++j) {
         /* do more stuff */
         ...
         if( someFunction(j,i) == 2 ) {
             goto done;
         }
     }
}
done:

或使用另一个变量来控制循环迭代:

int i, j;    // Iterators
int done = 0;
for(i=0; i<100 && !done; ++i) {
     /* do some stuff */
     ...
     for(j=0; j<99 && !done; ++j) {
         /* do more stuff */
         ...
         if( someFunction(j,i) == 2 ) {
             done = 1;
         }
     }
}

【讨论】:

  • +1 两种想法,虽然人们不喜欢goto,但它比在每一轮中添加检查要快。(如您的第二个选项)
  • !done 标志在每个循环中都经过验证,这似乎不是最优的
  • +1 表示第二个想法。这就是我会做的。 goto 更快,但也很危险。如果您在编写时不注意,可能会发生奇怪的事情。标志的验证只能在外循环中完成,在done = 1;后面加一个break,这样可以降低计算成本(虽然对于现在的计算机来说很小)
  • @Victor 我不同意。第一个变体更容易阅读,第二个变体更容易出错。在这个例子中,它可能没有太大区别。但是考虑两个或三个跨越 50-100 行的循环。您不必检查 !done 是否包含在所有循环中,只需将标签放在正确的位置即可。
【解决方案2】:

我们的好朋友goto 可以为您处理!

int i, j;    // Iterators

for(i=0; i<100; ++i) {
     /* do some stuff */
     ...
     for(j=0; j<99; ++j) {
         /* do more stuff */
         ...
         if( someFunction(j,i) == 2 ) {
             /* break out of both loops */
             goto ExitLoopEarly;
         }
     }
}
goto ExitLoopNormal;

ExitLoopEarly:
....

ExitLoopNormal:
...

【讨论】:

    【解决方案3】:

    这可能是一个解决方案

    function void loop()
    {
                  int i, j;    // Iterators
    
                for(i=0; i<100; ++i) {
                     /* do some stuff */
                     ...
                     for(j=0; j<99; ++j) {
                         /* do more stuff */
                         ...
                         if( someFunction(j,i) == 2 ) {
                             return;
                         }
                     }
                }
    }
    

    【讨论】:

    • 这只会满足某些情况,你可以忽略它在循环中可能使用的任何值。
    • 什么意思?我真的无法理解你
    • 假设他在一个函数中有三个这样的双循环,并且在这些循环中他修改了函数的一些局部变量,他需要传递(通过引用)在循环到函数。 goto 或一些标志似乎更合理。
    • 是的,但这是非常具体的情况,如果您在循环中使用多个变量,则很有可能可以重构它,所以即使在一般情况下我也不能想一个会阻止你使用这个实现的极端情况
    • 让我说得更笼统——调用一个函数来避免 goto(并在中间用 return 中断)对我来说似乎不是进步。就是这样。
    【解决方案4】:

    您可以在一个函数中插入两个循环并使用return

    void foo(){
    int i, j;    // Iterators
    
    for(i=0; i<100; ++i) {
         /* do some stuff */
         ...
         for(j=0; j<99; ++j) {
             /* do more stuff */
             ...
             if( someFunction(j,i) == 2 ) {
                 return;
             }
         }
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-10
      • 2013-04-11
      • 2011-06-04
      • 2011-02-08
      • 2023-03-27
      • 2016-11-19
      • 2011-04-30
      相关资源
      最近更新 更多