如何打破嵌套循环?

时间:2012-03-14 04:23:28

标签: c nested-loops break

如果我使用break语句,它只会破坏内部循环,我需要使用一些标志来打破外部循环。但是如果有很多嵌套循环,那么代码看起来不会很好。

还有其他方法可以打破所有循环吗? (请不要使用goto stmt。)

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // both of the loops need to break and control will go to stmt2
       }
   }

}

stmt2

15 个答案:

答案 0 :(得分:151)

不,不要破坏break的乐趣。这是goto;)

的最后一次有效使用

如果不是这样,那么你可以使用标志来打破深嵌套循环。

打破嵌套循环的另一种方法是将两个循环分解为单独的函数,并在想要退出时从该函数返回。

总结 - 打破嵌套循环:

  1. 使用goto
  2. 使用标志
  3. 将循环分解为单独的函数调用
  4. 无法抗拒包含xkcd:)

    enter image description here

    source

    Goto's are considered harmful但是评论中的许多人都认为不一定是这样。如果明智地使用它可以是一个很好的工具。适度使用的任何东西都很有趣。

答案 1 :(得分:40)

怎么样:

if(condition) {
i = j = 1000;break;
}

答案 2 :(得分:34)

bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
    for (int j = 0; (j < 1000) && !stop; j++)
    {
        if (condition)
            stop = true;
    }
}

答案 3 :(得分:23)

一种方法是将所有嵌套循环放入一个函数中,并从最内层循环返回,需要打破所有循环。

function() 
{    
  for(int i=0; i<1000; i++)
  {
   for(int j=0; j<1000;j++)
   {
      if (condition)
        return;
   }
  }    
}

答案 4 :(得分:15)

我认为goto将解决问题

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
        if (condition) {
            goto end;
        }
    }
}

end:
stmt2 

答案 5 :(得分:11)

如果你想要它可读,你需要一个布尔变量:

bool broke = false;
for(int i = 0; i < 1000; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
  if (broke)
    break;
}

如果您希望它具有较低的可读性,您可以加入布尔评估:

bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
}

作为一种终极方式,您可以使初始循环无效:

for(int i = 0; i < size; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      i = size;
      break;
    }
  }
}

答案 6 :(得分:7)

使用来自LLVM团队的明智建议:

“将谓词循环转换为谓词函数”

见:

http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions

答案 7 :(得分:4)

如果你需要i和j的值,这应该有效 但性能低于其他人

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}

答案 8 :(得分:3)

警告:这个答案显示了一个真正模糊的结构。

如果您使用的是GCC,请查看this library。 与在PHP中一样,break可以接受要退出的嵌套循环的数量。 你可以这样写:

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // break two nested enclosing loops
            break(2);
       }
   }
}

答案 9 :(得分:2)

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; i++) {
       if(condition) {
            goto end;
   }
} 

end:

答案 10 :(得分:1)

我注意到问题很简单,“还有其他方法可以打破所有循环吗?”我看不到任何限定,但不是goto,特别是OP并没有要求采用 good 方式。那么,我们如何longjmp走出内循环呢? :-)

#include <stdio.h>
#include <setjmp.h>

int main(int argc, char* argv[]) {
  int counter = 0;
  jmp_buf look_ma_no_goto;
  if (!setjmp(look_ma_no_goto)) {
    for (int i = 0; i < 1000; i++) {
      for (int j = 0; j < 1000; j++) {
        if (i == 500 && j == 500) {
          longjmp(look_ma_no_goto, 1);
        }
        counter++;
      }
    }
  }
  printf("counter=%d\n", counter);
}

setjmp函数返回两次。第一次,它返回0,程序执行嵌套的for循环。然后,当ij都为500时,它将执行longjmp,这将导致setjmp再次返回值1,从而跳过循环。

longjmp不仅可以使您摆脱嵌套循环,还可以与嵌套函数一起使用!

答案 11 :(得分:0)

另一种方法是将代码从两个for循环重构为一个for循环和一个手动循环。这样,手动循环中的中断适用于外部循环。我在Gauss-Jordan Elimination中用过一次,它需要三个嵌套循环才能处理。

for (int i = 0; i < 1000; i++)
{
    int j = 0;

MANUAL_LOOP:;

    if (j < 1000)
    {
       if (condition)
       {
           break;
       }

       j++;
       goto MANUAL_LOOP;
    }
}

答案 12 :(得分:-1)

int i = 0, j= 0;

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition){
            i = j = 1001;
            break;
        }
    }
}

将打破两个循环。

答案 13 :(得分:-1)

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
       if(condition) {
          func(para1, para2...);
          return;
       }
    }
}

func(para1, para2...) {
    stmt2;
}

答案 14 :(得分:-2)

i = 0;

do
{
  for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here!
  {
     if (condition)
     {
       break;
     }
  }

  ++i;

} while ((i < 1000) && !condition);