如何使用break语句停止内部和外部循环

5

我有一个非常简单的代码,在内部循环中使用了break

for (int it=0; it<5; it++) {
    for (int it2=0; it2<5; it2++) {
        if (it2==2) 
            break; //break here not it2, but it loop
        NSLog(@"it=%d it2=%d", it, it2);
    }
}

我收到一个输出:
it=0 it2=0, it=0 it2=1, 
it=1 it2=0, it=1 it2=1, 
it=2 it2=0, it=2 it2=1,
it=3 it2=0, it=3 it2=1,
it=4 it2=0, it=4 it2=1

我知道在一些编程语言中,有可能确定 break 语句应该影响哪个循环。是否可以调用 break 来停止外部循环(带有变量 itfor 循环)?


在 C 或 C++ 中,no. break 仅用于当前循环。 - A Lan
2
在 C 语言中,你不能使用直接的指令来实现这个(除了 goto 标签),但是你可以从第一个循环中跳出并设置一个标志来终止第二个循环。 - n0p
针对你的问题,你有两个选择:goto或函数。更有趣的问题是:你实际的问题是什么(你提供的示例看起来很牵强),你正在尝试用哪种语言解决它? - Björn Pollex
我在Objective-C中遇到了这样的问题,但每次出现时,我都能找到好的解决方案来避免使用两个for循环。 - Szu
6个回答

12
如果你真的想这么做,那就大胆使用 goto
for (int it=0; it<5; it++) {
    for (int it2=0; it2<5; it2++) {
        if (it2==2) 
            goto end_outer_loop;
        NSLog(@"it=%d it2=%d", it, it2);
    }
}

end_outer_loop:

// more stuff here.

这是一个合法的 goto(大多数向下方向的goto都是合法的)。事实上,break是一种特殊类型的“经过批准”的goto,并且因为C语言很简单,你必须在复杂情况下使用明确的goto。

然而正如这里许多人指出的那样,最好能够使用 return。你不应该 仅仅为了避免goto而扭曲你的程序,但在大多数情况下,它表明你的函数变得过于复杂,因此应该将其拆分。


1
帮帮忙!我正在经历一个令人讨厌的回溯到上世纪70年代的时光。 - ravenspoint
10
将功能分解为小函数是很好的。但你不应该仅仅为了避免使用goto语句而这样做。这取决于循环是否与计算密切相关。这就是为什么其他编程语言会有特殊的语言功能来处理这个问题(例如循环标签,整数参数用于终止等)。 - Adrian Ratnapala
2
当人们要求我提供“goto”合法用途时,这是唯一一个我能引用的实际常见应用示例。我不知道为什么人们如此反感“goto”,但完全接受“switch”,因为由于其作用域而具有相同的后果。 - tenfour
2
@tenfour 确实如此。就好像每个人都停止思考一样,只是因为有一天被告知“goto是邪恶的!” - lethal-guitar
2
我认为这是仅有几个情况之一,应该使用goto。使用函数感觉就像是为了不使用goto而强制采用不同的设计。 - Veritas
显示剩余7条评论

6
您可以使用一个名为 bool flag 的变量来实现这个目的,类似于这样:
bool flag = false;
for (int it=0; it<5; it++) {
    for (int it2=0; it2<5; it2++) {
        if (it2==2) { flag=true; break; }
        NSLog(@"it=%d it2=%d", it, it2);
    }
    if(flag) {break;}
}

只有在其他方法无法使用时才应使用此方法。 return 方法可以提高代码可读性,这只是一个变通方法。

goto 方法也是有效的,但通常建议不要使用 goto,因为它会中断控制流,并且如果代码足够大,则可能导致数小时的调试!


3
在我看来,这种写法不如使用goto清晰易读。 - lethal-guitar
我有同样的想法,但 if 语句是不必要的。你可以在 for 语句中添加条件。 - Szu
@Szu 我同意你的提议! - CinCout
1
这些标志变量只是轻微地令人讨厌,因为它们仅在本地使用;但它们是“让我们添加状态变量疾病”的迹象。而且,被黑客式添加的状态变量是我所知道的导致错误和难以理解代码的最糟糕的原因。 - Adrian Ratnapala
1
@gargankit,你从哪里得到了“goto”如此强大的想法?你不能在当前函数之外使用“goto”... - tenfour

1
在 C/C++ 中,你真的没有类似的东西。已经有一些答案了,比如使用 goto 或其他方法。个人而言,我不喜欢 goto,认为它会导致一些松散的代码(仅代表我个人意见)。
对我来说,这里有两个好选择。
  1. 编写循环条件,使其在两者中都包含退出条件。这是我个人会选择的方式,因为我不喜欢在循环中使用 break 或其他东西,除非我绝对必须这样做。我只是认为这样可以使产品更加清洁,并且这是我所学到的。

  2. 如果你决定保留 break,那么不要用单行的 if() 控制它,将其分成两部分并创建一个“中断标志”,如果满足中断条件,则设置该标志。从那里开始,在外部循环中要么放置另一个条件以在该标志被设置时退出,要么在外部循环中(但不在内部循环中)放置另一个 if() 来在该标志被设置时退出。

希望这可以帮助你。

0
你应该将循环包装在一个函数中,然后使用 return 语句从该函数返回。

4
这是一个典型的因语言因素而强行设计的案例。应该反过来思考。 - SomeWittyUsername
1
我同意,在某些情况下这可能是解决问题的方法。如果不知道原始问题,很难给出明确的答案。我认为,对于几乎所有用例,将迭代包装到实现算法的函数中比使用“goto”得到更清晰的解决方案。 - Björn Pollex
一个好的启发是问自己是否能为该函数想出一个好的名称。这与询问该循环是否执行某些独特且可识别的操作相同。如果存在这样的名称,则可以使您的代码自我注释。如果不存在这样的名称,则内联文本将更易于阅读,因为它可以节省读者穿透额外间接层的时间。 - Adrian Ratnapala

0
在编程中使用goto语句会使程序的逻辑变得复杂和混乱。在现代编程中,goto语句被认为是一种有害的结构和不良的编程实践。
您可以将其用作函数,当条件发生时函数退出。
int loop(int it,int it2)
{
  for (int it=0; it<5; it++) {
    for (int it2=0; it2<5; it2++) {
        if (it2==2) return 0; //function returns here
        NSLog(@"it=%d it2=%d", it, it2);
    }
  }
  return 1;
}

3
使用 goto 跳出循环是被认为完全合适的一种情况。而且不会增加太多复杂度,因为标签和跳转之间非常接近。 - lethal-guitar
我同意goto语句是有用的,但从专业程序员的角度来看,使用goto语句被认为是一个不好的习惯。因为在复杂的程序中使用它可能会导致其他人阅读代码时产生歧义。在简单的程序中使用它还可以接受。但出于他的知识,我让他知道使用goto是一个不好的习惯。 - Sorcrer
1
除了这种情况,这被视为一个坏习惯。即使是MISRA C++也允许这样做。我不认为将循环包装在函数中会更好,因为它只会降低可读性,并且由于返回值也会打破控制流,所以并没有任何优势。 - Veritas
1
@hariprasad 作为一名专业程序员,你是否使用异常或switch语句?当在复杂的程序中错误使用时,所有这些都可能会给其他人阅读代码带来歧义。这总是取决于特性的使用方式,在这种特定的用例中,goto肯定不会被视为坏习惯。 - lethal-guitar

-1

很遗憾,c++没有那种类型的中断。一种被认为是可恶的选择是使用goto。

有两个可接受的解决方案:

  1. 将此代码放入单独的函数中,并使用return

  2. 使用布尔标志

    bool stopFlag = false; for (int it=0; it<5 && !stopFlag; it++) { for (int it2=0; it2<5; it2++) { if (whatever) { stopFlag=true; break; } }


这是为数不多的情况之一,其中使用goto被认为是更好的解决方案。 - Veritas
维瑞塔斯,我持不同意见,因为在这种情况下有两个干净的选择。但这只是一个品味问题。 - Ophir Gvirtzer
当然有替代方案,但goto是更清晰的选择。Return实际上是一个伪装的goto,它还会破坏控制流,因此除了为程序员提供额外的工作之外,它并没有提供任何优势。 - Veritas
谁给我点踩因为我的口味与他不同,我对他表示强烈的不满。 - Ophir Gvirtzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接