10

我正在准备一些代码:

for(int a = 1; a <= 100; a++)    //loop a (main loop)
{
    for(int b = 1000; b <= 2000; b++)    //loop b
    {
       if(b == 1555)
          break;
    }

    for(int c = 2001; c <= 3000; c++)    //loop c
    {
       .
       .
       .
    }
}

int a我想通过在 b 循环(循环变量)中使用break;语句来打破主循环(循环变量int b)。

我该怎么做?

4

11 回答 11

34

使用goto.

for(int a = 1; a <= 100; a++)    //loop a (main loop)
{
    for(int b = 1000; b <= 2000; b++)    //loop b
    {
       if(b == 1555)
          goto loopDone;
    }

    for(int c = 2001; c <= 3000; c++)    //loop c
    {
       .
       .
       .
    }
}
loopDone:
于 2010-08-09T17:13:30.937 回答
23

要么做以下四件事之一:使用goto、使用throw、使用标志或重构。

许多人会不同意使用goto,但有时它是一个干净的解决方案。(大多数时候,它不是,但它的存在是有原因的。)但是,我发现使用goto权证是一种重构。

第二种解决方案是抛出一些特殊异常,然后在主循环之外捕获它。这是对异常系统的滥用,基本上更糟goto;使用 agoto而不是这个。

第三种解决方案是使用某种标志。这基本上是“更安全” ,但有些人可能会认为它有点难看。(尤其是多级。尽管在这种情况下,您担心的是您的代码有多丑。)goto

我推荐的解决方案是重构。无论你在做什么,都太过分了。您应该将内部循环移动到一个函数中,然后调用该函数。返回主循环只是从该函数返回。(换句话说,“我的工作完成了。”)

于 2010-08-09T17:19:14.517 回答
21

我建议将您的代码重构为一个函数。然后你可以return从那个函数而不是使用break

void myFunc() 
{
    for(int a = 1; a <= 100; a++)    //loop a (main loop)
    {
        for(int b = 1000; b <= 2000; b++)    //loop b
        {
           if(b == 1555) // Logic is just an example,
              return;    // since it will always return
        }

        .
        .
        .
    }
}

这——或者甚至更复杂的代码重构——应该适合一个干净、优雅的解决方案。或者,如果您只想快速修复,您可以使用条件变量:

for(int a = 1; a <= 100; a++)    //loop a (main loop)
{
    bool cond = false;

    for(int b = 1000; b <= 2000; b++)    //loop b
    {
       if(b == 1555){
          cond = true;
          break;
       }
    }

    if (cond) break;

    .
    .
    .
}

其他人建议使用goto. 虽然这是另一个快速解决方案,但我强烈建议您不要这样做,特别是如果您在严格的环境中工作,代码将经过同行评审并在未来几年内使用。

我看来,这种goto方法比函数/返回重构更难维护,尤其是稍后当其他人对代码进行更改时。另外,您必须向goto团队中偶然发现代码的任何其他人证明这一点。

于 2010-08-09T17:14:06.583 回答
4
for(int a = 1; a <= 100; a++)    //loop a (main loop)
{
    for(int b = 1000; b <= 2000; b++)    //loop b
    {
       if(b == 1555)
          goto end;
    }

    for(int c = 2001; c <= 3000; c++)    //loop c
    {
       .
       .
       .
    }
}
end:
于 2010-08-09T17:13:44.853 回答
4

一次退出两个这样的循环的唯一方法是 agoto或 athrow或 a returnthrow并且return可能不合适(特别是throw,如果条件不是异常的)。或者,您可以设置某种条件 ( bool breakout;),如果它为真,则继续中断。

于 2010-08-09T17:13:46.857 回答
4

如果合适,您可以创建一个内容为 a 循环的函数,并使用 return。

public void bigLoop()
{
    for(int a = 1; a <= 100; a++)
    {
        for(int b = 1000; b <= 2000; b++)
        {
            if(b == 1555)
                return;
        }

        for(int c = 2001; c <= 3000; c++)
        {
            .
            .
            .
        }
    }
}//bigLoop
于 2010-08-09T17:18:38.513 回答
4

\(◕◡◕)/

[]() {
    for(int a = 1; a <= 100; a++)    //loop a (main loop)
    {
        for(int b = 1000; b <= 2000; b++)    //loop b
        {
           if(b == 1555)
              return;
        }

        for(int c = 2001; c <= 3000; c++)    //loop c
        {
           .
           .
           .
        }
    }
}();
于 2010-08-09T18:38:35.213 回答
3
  1. 使用goto

    for(int a = 1; a <= 100; a++)    //loop a (main loop)
    {
        for(int b = 1000; b <= 2000; b++)    //loop b
        {
           if(b == 1555)
              goto done;
        }
        for(int c = 2001; c <= 3000; c++)    //loop c
        {
           .
           .
           .
        }
    }
    done:
    
  2. 设置每个循环测试的哨兵值:

    bool sentinel = true ;
    for(int a = 1; a <= 100 && sentinel ; a++)    //loop a (main loop)
    {
        for(int b = 1000; b <= 2000 && sentinel; b++)    //loop b
        {
           if(b == 1555)
              sentinel = false;
        }
        for(int c = 2001; c <= 3000 && sentinel; c++)    //loop c
        {
           .
           .
           .
        }
    }
    
于 2010-08-09T17:16:55.023 回答
2

一种简单的策略是将循环放在一个单独的函数中并在选定的点执行返回:

void func()
{
    for(int a = 1; a <= 100; a++)    //loop a (main loop)
    {
        for(int b = 1000; b <= 2000; b++)    //loop b
        {
           if(b == 1555)
              return;
        }

        for(int c = 2001; c <= 3000; c++)    //loop c
        {
           .
           .
           .
        }
    }
}

任何类型的结果也可以通过返回值或函数的引用参数返回。

于 2010-08-09T17:18:53.240 回答
2

理想的方法是重构您的代码,以便您不再需要如此复杂的嵌套循环结构。根据您的其余代码的样子,您的bandc循环可能是成为单个函数的候选者,如果不是整个a循环的话。

既然它看起来像循环bc迭代相邻的范围,为什么不将它们组合起来并减少循环嵌套呢?

for (int a = 1; a <= 100; a++)    //loop a (main loop)
{
    int count = 1000;
    while (count <= 3000) // combined loops 'b' and 'c'
    {
        if (count <= 2000)
        {
            // Old loop 'b' code
            if (b == 1555)
                goto fullbreak;
        }
        else
        {
            // Old loop 'c' code
            ...
        }
        count++;
    }
}
fullbreak:

您也可以使用条件变量代替goto. 如果您想跳出旧b循环但仍处理旧c循环,只需count = 2001在旧b循环代码中设置即可。

理想情况下,您至少可以将其重新考虑为更像

for (int a = 1; a <= 100; a++)    //loop a (main loop)
{
    if (process_inner_loop(pass, required, args))
        break;
}

如果你想跳出封闭循环,函数会process_inner_loop包装你原来的两个循环并返回非零。现在,goto您可以简单地使用return 1;.

于 2010-08-09T17:39:52.523 回答
1

使用这种模式

for(int a = 1; a <= 100; a++)
{
    int breakMain = 0;
    for(int b = 1000; b <= 2000; b++)
    {
       if(b == 1555)
       {
           breakMain = 1;
           break;
       }
    }

    if(breakMain)
         break;

    for(int c = 2001; c <= 3000; c++)
    {
       .
       .
       .
    }
}
于 2010-08-09T17:13:53.887 回答