我可以使用break来退出多个嵌套for循环吗?

时间:2009-08-10 23:15:11

标签: c++ for-loop break nested-loops

是否可以使用break函数退出多个嵌套的for循环?如果是这样,你会怎么做呢?你还可以控制休息退出的循环次数吗?

20 个答案:

答案 0 :(得分:249)

不,不要用break破坏它。这是使用goto的最后一个据点。

答案 1 :(得分:211)

AFAIK,C ++不支持命名循环,就像Java和其他语言一样。您可以使用goto,或创建您使用的标志值。在每个循环结束时检查标志值。如果设置为true,那么您可以跳出该迭代。

答案 2 :(得分:52)

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

当然,这提出了另一个论点,即你是否应该从最后的任何地方的函数中明确return

答案 3 :(得分:46)

只是使用lambdas添加一个明确的答案:

  for (int i = 0; i < n1; ++i) {
    [&] {
      for (int j = 0; j < n2; ++j) {
        for (int k = 0; k < n3; ++k) {
          return; // yay we're breaking out of 2 loops here
        }
      }
    }();
  }

当然这种模式有一定的局限性,显然只有C ++ 11,但我认为它非常有用。

答案 4 :(得分:32)

中断将仅退出包含它的最内层循环。

您可以使用转到来突破任意数量的循环。

当然转到通常是Considered Harmful

  

使用break函数[...]是否合适?

使用break和goto会使得更难以推断程序的正确性。请参阅此处以获取对此的讨论:Dijkstra was not insane

答案 5 :(得分:19)

虽然这件衣服已经出现了,但我认为一个好方法是做到以下几点:

for(unsigned int z = 0; z < z_max; z++)
{
    bool gotoMainLoop = false;
    for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
    {
        for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
        {
                          //do your stuff
                          if(condition)
                            gotoMainLoop = true;
        }
    }

}

答案 6 :(得分:14)

这个怎么样?

for(unsigned int i=0; i < 50; i++)
{
    for(unsigned int j=0; j < 50; j++)
    {
        for(unsigned int k=0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                j=50;
                k=50;
            }
        }
    }
}

答案 7 :(得分:12)

使用goto的代码示例和打破嵌套循环的标签:

for (;;)
  for (;;)
    goto theEnd;
theEnd:

答案 8 :(得分:9)

打破几个嵌套循环的一个好方法是将代码重构为函数:

void foo()
{
    for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < 50; j++)
        {
            for(unsigned int k=0; k < 50; k++)
            {
                // If condition is true
                return;
            }
        }
    }
}

答案 9 :(得分:5)

goto对破坏嵌套循环非常有用

for (i = 0; i < 1000; i++) {
    for (j = 0; j < 1000; j++) {
        for (k = 0; k < 1000; k++) {
             for (l = 0; l < 1000; l++){
                ....
                if (condition)
                    goto break_me_here;
                ....
            }
        }
    }
}

break_me_here:
// Statements to be executed after code breaks at if condition

答案 10 :(得分:3)

我知道这是一个老话题,但是我觉得这确实需要说,没有其他地方要说。对于这里的每个人,请使用 goto。。我刚刚使用过。

几乎所有内容都一样,goto不是“或”或“不好”的100%。至少有两种用法,我要说的是,如果您将goto用于它们-而不用于其他任何用途-您不仅应该100%可以,而且与没有它相比,您的程序将更具可读性,因为它使您的意图更加清晰(有多种方法可以避免这种情况,但是我发现它们都比较笨拙):

  1. 突破嵌套循环,并且
  2. 错误处理(即,在函数末尾跳转到清理例程,以便返回失败代码并释放内存。)

与其仅仅教条地接受诸如“ so-so is'evil'”之类的规则,不如理解为什么主张情感,并遵循“ why”而不是情书。不知道这也会给我带来很多麻烦,以至于我要说,断断续续地称呼事物“邪恶”比事物本身有害得多。最糟糕的是,您只会得到错误的代码-然后您知道只要听到警惕就不会使用它,但是如果您为满足教条主义而竭尽全力,那会更糟。 >

为什么之所以将“ goto”称为“邪恶”是因为您永远不要使用它来代替普通的ifs,fors和whiles 。那为什么呢?尝试一下,一直尝试使用“ goto”代替普通的控制逻辑语句,然后尝试再次使用控制逻辑编写相同的代码,并告诉我哪个看起来更好,更容易理解,哪个看起来更糟。 。妳去(奖金:现在尝试在仅goto的代码中添加新功能。)这就是为什么它是“邪恶的”,并且围绕“邪恶”具有适当的范围限定。使用它来缩短C的“ break”命令的缺点不是是有问题的用法,只要您从代码中清楚地知道goto应该完成什么(例如使用“ nestedBreak”之类的标签)。打破嵌套循环是很自然的。

(或者更简单地说:使用goto打破循环。我想说这是更可取的。请勿使用goto来 create 循环。那是“邪恶”。)

又怎么知道自己是教条的?如果遵循“ xyz是邪恶的”规则,则代码会使您的代码变得 less 容易理解,因为您正试图绕过它(例如,通过在每个循环中添加额外的条件或某些标记变量),或类似的其他技巧),那么您很有可能会教条主义。

除了良好的编码习惯以外,没有什么可以替代学习良好的思考习惯。前者在后者之前,而后者通常会在前者被采用后跟随。但问题是,我发现的次数太多了,后者不够复杂。太多的人只是简单地说“这很不好”和“这需要更多的思考”,而没有说要想什么,想什么关于为什么 。太可惜了。

(FWIW,在C ++中,仍然需要打破嵌套循环,但是对错误代码的需求却不存在:在这种情况下,请始终使用异常来处理错误代码,除非如此,否则绝不返回它们异常抛出和捕获经常会导致性能问题,例如在高需求服务器代码中的紧密循环中,也许[有人可能说“例外”应该“很少使用”,但这是思想欠缺的另一部分。摆脱教条主义:不,至少在我反驳这种教条之后,根据我的经验,我发现它们使事情变得更加清晰-只是不要滥用它们来进行错误处理以外的其他操作,例如将它们用作控制流;实际上与“ goto”相同。如果将它们全部使用并且仅用于错误处理,那就是它们的用途。]。

答案 11 :(得分:2)

我确实认为goto在这种情况下有效:

要模拟break / continue,您需要:

for ( ;  ;  ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            goto theEnd;
        }
    }
}
theEnd:

继续

for ( ;  ; ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            i++;
            goto multiCont;
        }
    }
    multiCont:
}

答案 12 :(得分:2)

  

break语句终止执行它出现的最近的封闭doforswitchwhile语句。控制传递给终止语句后面的语句。

来自msdn

答案 13 :(得分:1)

我不确定是否值得,但是您可以使用一些简单的宏来模拟Java的命名循环:

#define LOOP_NAME(name) \
    if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
    { \
        [[maybe_unused]] CAT(_namedloop_break_,name): break; \
        [[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
    } \
    else

#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)

#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y

用法示例:

#include <iostream>

int main()
{
    // Prints:
    // 0 0
    // 0 1
    // 0 2
    // 1 0
    // 1 1

    for (int i = 0; i < 3; i++) LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << i << ' ' << j << '\n';
            if (i == 1 && j == 1)
                BREAK(foo);
        }
    }
}

另一个例子:

#include <iostream>

int main()
{
    // Prints: 
    // 0
    // 1
    // 0
    // 1
    // 0
    // 1

    int count = 3;
    do LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << ' ' << j << '\n';
            if (j == 1)
                CONTINUE(foo);
        }
    }
    while(count-- > 1);
}

答案 14 :(得分:0)

其他语言(例如PHP)接受一个break参数(即break 2;)来指定你想要突破的嵌套循环级别的数量,但C ++却没有。您必须使用在循环之前设置为false的布尔值,如果要中断,在循环中设置为true,加上嵌套循环后的条件中断,检查布尔值是否设置为true如果是的话会打破。

答案 15 :(得分:0)

我知道这是老帖子。但我会建议一点逻辑和简单的答案。

for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < conditionj; j++)
        {
            for(unsigned int k=0; k< conditionk ; k++)
            {
                // If condition is true

                j= conditionj;
               break;
            }
        }
    }

答案 16 :(得分:0)

仅用一个bool变量中断任意数量的循环,如下所示:

bool check = true;

for (unsigned int i = 0; i < 50; i++)
{
    for (unsigned int j = 0; j < 50; j++)
    {
        for (unsigned int k = 0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                check = false;
                break;
            }
        }
        if (!check)
        {
            break;
        }
    }
    if (!check)
    {
        break;
    }
}

在这段代码中,我们break;所有循环。

答案 17 :(得分:-1)

  while (i<n) {
    bool shouldBreakOuter = false;
    for (int j=i + 1; j<n; ++j) {
      if (someCondition) {
          shouldBreakOuter = true;
      }
    }

    if (shouldBreakOuter == true)
      break;

  }

答案 18 :(得分:-2)

你可以使用try ... catch。

try {
    for(int i=0; i<10; ++i) {
        for(int j=0; j<10; ++j) {
            if(i*j == 42)
                throw 0; // this is something like "break 2"
        }
    }
}
catch(int e) {} // just do nothing
// just continue with other code

如果你必须同时打破几个循环,那么它通常是一个例外。

答案 19 :(得分:-3)

断开for循环对我来说有点奇怪,因为for循环的语义通常表明它将执行指定的次数。但是,在所有情况下都不错;如果你正在寻找一个集合中的东西,并想在你找到它之后破解它,那么它很有用。但是,在C ++中不可能打破嵌套循环;通过使用标记的中断,它是其他语言。你可以使用标签和goto,但这可能会让你在晚上胃灼热..?看起来似乎是最好的选择。