如何在 Objective-C 中突破两个嵌套的 for 循环?

我有两个这样嵌套的 for 循环:

for(...) {
for(...) {


}
}

我知道有一个 break语句。但是我很困惑,它是同时打破了两个循环,还是只打破了它被称为循环的那个循环?一旦我发现迭代更多次是没有意义的,我就需要打破这两个规则。

63063 次浏览

Break 从一个循环中断开,但是您可以向外部循环添加一个检查,当内部循环中断时,外部循环中断。

bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
for ( ... ) {
if (...) {
dobreak = true;
break;
}
}
}

如果从一组嵌套循环中执行中断,则只有执行中断的最内层循环被终止。(就像标准 C 一样)

Break 语句只会打破作用域中的循环,即父循环。如果你想打破第二个循环,你可以使用一个布尔变量,这是在两个循环的范围

bool isTerminated = false;


for (...)
{
if (!isTerminated)
{
for(...)
{
...


isTerminated = true;
break;
}
}
else
{
break;
}
}

Break 语句从最内层的循环中断开。将需要一个额外的测试和中断语句来打破外部循环。

也许最简单的方法是使用“标志”变量

for(i=0; i<10 && (done==false); i++)
for(j=0;j< 10; j++){
..
..
if(...){done=true; break;}
}

在中断前更改顶部循环的计数器

for(i=0; i<10 ; i++)
for(j=0;j< 10; j++){
..
..
i = 10;
break;
}

break语句只能让您跳出最内层的循环。如果你不想增加代码、内存和专用状态变量的性能开销,我建议将代码重构为一个函数或方法,并使用 return来摆脱所有循环:

void do_lots_of_work(void)
{
int i, j;


for(i=0; i<10 ; i++)
{
for(j=0;j< 10; j++)
{
..
..
if(disaster_struck())
return; /* Gets us out of the loops, and the function too. */
}
}
}

如果使用 goto 可以简化代码,那么它就是合适的。

for (;;)
{
for (;;)
{
break; /* breaks inner loop */
}
for (;;)
{
goto outer; /* breaks outer loop */
}
}
outer:;

其他人提到了如何设置标志或使用 goto,但我建议重构代码,以便将内部循环转换为单独的方法。然后,该方法可以返回一些标志,以指示外部循环应该为 break。如果您恰当地命名方法,这将更具可读性。

for (int i = 0; i < 10; i++) {
if (timeToStop(i)) break;
}


-(bool) timeToStop: (int) i {
for (int j = 0; j < 10; j++) {
if (somethingBadHappens) return true;
}


return false;
}

伪代码,没有经过测试,但是你明白我的意思。

除了前面提到的标志变量或 goto,你可以 一个 Objective-C 异常:

@try {
for() {
for() {
@throw ...
}
}
}
@catch{
...
}

另一种解决方案是将函数中的第二个循环分解出来:

int i;


for(i=0; i<10 ; i++){
if !innerLoop(i) {
break;
}
}


bool innerLoop(int i)
int j;
for(j=0;j< 10; j++){
doSomthing(i,j);
if(endcondtion){
return false;
}
}
}

和上一个一模一样,通常是这样的:

for(i=0;i<a;i++){
for(j=0;j<a;j++){
if(Something_goes_wrong){
i=a;
break;
}
}
}

为了方便起见,不如将这个 true/false 检查改为一个方法,并使用 return语句:

- (bool) checkTrueFalse: parameters{


for ( ...) {
for ( ... ) {


if (...) {
return true;
}


}
}
return false;
}