410

Is it possible to use the break function to exit several nested for loops?

If so, how would you go about doing this? Can you also control how many loops the break exits?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Faken
  • 11,352
  • 17
  • 59
  • 74
  • 11
    Instead of using break or goto to exit multiple nested loops, you can enclose that particular logic in a function and use return to exit from multiple nested loops. This will maintain the aesthetics of your code and will prevent you from using goto which is a bad programming practice. – Rishab Shinghal Aug 26 '19 at 13:49
  • 7
    why goto is bad programming practice? it's widely used in kernel. – Alexis Feb 23 '22 at 00:57
  • Goto statements reduces throughput of cpu pipelining. It makes branch prediction hard, – CodeTalker Jul 30 '22 at 18:53
  • 1
    @CodeTalker so does any other statement that possibly exit the loop, whether is it goto, break, return... In practice this is not necessarily a big issue, as the branch that exits is executed only once after many executions of the branch that does not exit: any decent branch prediction algorithm will always predict the latter after a few iterations. – PierU Apr 19 '23 at 09:15

24 Answers24

333

No, don't spoil it with a break. This is the last remaining stronghold for the use of goto.

H H
  • 263,252
  • 30
  • 330
  • 514
  • 35
    The MISRA C++ coding standard allows the use of goto to cover this exact kind of situation. – Richard Corden Aug 11 '09 at 08:13
  • 36
    Real programmers are not afraid to use goto. Done it for 25 years -- no regrets -- saved a ton of development time. – Doug Null Mar 22 '16 at 19:02
  • 4
    I agree. gotos are a must if you do not have 8K pixels across, and need to call a sequence of 30 Windows OS calls. – Michaël Roy Jun 16 '17 at 15:21
  • 9
    Or a simple "return" by putting the code in a function. – Tara Feb 08 '19 at 03:32
  • 8
    I came here looking for a way out of a `switch` statement inside a `while` loop. Logically, that's only one level of looping, but `switch` eats the `break`. This is the first `goto` I've written since I was writing in BASIC, circa 1985. (It's a very "hot" loop, even checking an extra boolean each time around costs 15-20%, so adding a `done` flag is not a good option. I just had to write this comment to cleanse my soul.) – Jim Pivarski Jan 12 '21 at 01:26
  • I think it's a myth that using goto is bad. Also for the resulting machine code it's no difference if you use while, for, break, return or goto. It will all be translated into jumps... – zomega May 17 '22 at 09:15
  • Just keep in mind that a goto kills all optimizations by waiting for the CPU's cycles to flush what's still in its pipe by forcing the compiler to add nop ASM opcodes before the goto. In short: it is a performance killer. – Jacques Jan 29 '23 at 01:54
  • @Jacques - but can a compiler implement an if/else without a JMP ? – H H Jan 29 '23 at 10:15
  • It's best never to assume what the compiler is going to do. It is true that a compiler can identify innumerable different patterns with a view to optimizing the code, but it is not for us to draw conclusions from them. First of all one compiler will behave differently from another but, in addition, the behavior of a compiler will change over time. – Jacques Jan 30 '23 at 10:11
294

AFAIK, C++ doesn't support naming loops, like Java and other languages do. You can use a goto, or create a flag value that you use. At the end of each loop check the flag value. If it is set to true, then you can break out of that iteration.

Cullen Walsh
  • 4,318
  • 1
  • 17
  • 12
  • 383
    Don't be afraid to use a `goto` if that is the best option. – jkeys Aug 10 '09 at 23:50
  • 28
    I'm a new C++ programmer (and one without any formal programming training) thus after reading about people's rants on goto. I'm hesitant on using it in fear my program might just suddenly explode and kill me. Other than that, when i used to write programs on my ti-83 (in boring math class of course), the functions the basic editor provided required the use of goto's. – Faken Aug 11 '09 at 02:18
  • 2
    I seem to remember reading that many compilers give up on optimizing loops when a goto is present... – Steven Sudit Aug 11 '09 at 02:41
  • 35
    @Faken: Two types of programmers use `goto`: Bad programmers, and pragmatic programmers. The former are self explanatory. The latter, which you would fit into if you choose to use them well, use a so called "evil" concept when it is the lesser of (two) evils. Read this for a better understanding of some C++ concepts that you might need to use from time to time (macros, goto's, preprocessor, arrays): http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15 – jkeys Aug 11 '09 at 04:26
  • 48
    @Faken: There's nothing wrong with using goto. It's _misusing_ a goto that is troublesome. – Everyone Aug 11 '09 at 04:51
  • 34
    @Hooked: That's right, except that using `goto` rarely ever is the best option. Why not put the loops into their own function (`inline`, if you're concerned about speed) and `return` from this? – sbi Aug 11 '09 at 09:08
  • 7
    @sbi, sometime our functions have very big stack frame, and passing about 9-10+ vars will definetly make our code unreadable. Take a break and use goto, in this case it makes your program sexier and more readable. Some algorithms have sooo much control paths that makes goto more preferred way, especially state mashines in game loop - performance critical code where even a simple stack frame losses most or your performance! – Петър Петров Aug 28 '13 at 16:58
  • 3
    @ПетърПетров inlined functions don't have a stack frame – Tim Seguine Nov 04 '13 at 11:42
  • 5
    inline is a compiler hint keyword, no guarantee it will inline the function. In any case, you write the code as though they were not inline which means passing variables.... I'm with @Петър Петров on that. – hookenz Mar 24 '14 at 04:14
  • 1
    Unfortunately, I ended up seeing with my eyes how a stack frame was initialized on calling a inline function. Compiler have its final decision on that. The only really inlined thing is a macro. In fact, compiler will not even see it :) And DO NOT BOTHER throwing! It's like calling "goto" 10000 times in a row. – Петър Петров Apr 09 '14 at 13:05
  • 1
    If the function manipulates 9-10+ variables within a loop, the performance penalty of that creation of the stack frame is absolutely negligible. – Marian Spanik Nov 23 '15 at 21:16
  • 3
    Creating - and unwinding - a Stack Frame is more expensive than checking flag then performing a jump. `if...goto` very often gets compiled to to `je` or `jne` local jumps pair, while the `call` / `ret` function semantic often does far jumps and cache misses. So, don't be afraid to use `goto` it is is the smaller evil of twos. And, _never_ truse `inline` if you want speed. – Петър Петров Jan 25 '17 at 17:09
127

Just to add an explicit answer using 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
        }
      }
    }();
  }

Of course this pattern has a certain limitations and obviously C++11 only but I think it's quite useful.

Predelnik
  • 5,066
  • 2
  • 24
  • 36
  • 11
    This might confuse the reader into thinking the return causes the function the lambda is in to return, and not the lambda itself. – Xunie Aug 25 '16 at 01:55
  • 8
    @Xunie: If your loop is so complicated, that you forget that you are in a lambda, it is time to put them in a different function, but for simple cases, this should work quite well. – MikeMB Dec 01 '16 at 17:54
  • You can capture the lambda in a RIIA template that gives it a name and calls it in dtor(aka scope gaurd). This would not add any performance gain but can improve readabilty and reduce the risk of missing the function call parenthesis. – Red.Wave Jun 15 '18 at 06:42
  • this solution is not working when you also want a real return inside the loop... I mean: at one condition you just want to break out of 2 loops. at another condition you want to return out of the function. BTW: I really like this way of thinking! +1! – Thomas Aug 13 '20 at 09:51
  • 2
    I tested this on godbolt and it appears to compile to identical code to using a goto! Another advantage of this solution over goto is that labels only work if they label a statement. For example, you can't write `my_label: }` – Eyal Feb 08 '21 at 19:48
  • How this is called? First time to see it in code. – Alexis Feb 23 '22 at 00:59
  • lambdas are not debugger friendly. – SuperSaiyan99000 Mar 23 '23 at 02:57
62

Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.

Of course, this brings up the other argument of whether you should ever explicitly return from a function anywhere other than at the end.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 7
    That's a C problem. With RIAA early return is not a problem as all the problems associated with early return are correctly handled. – Martin York Aug 11 '09 at 00:12
  • 4
    I understand that proper application of RIAA can solve the resource cleanup problem in C++, but I have seen the philosophical argument against early return continue in other environments and languages. One system I worked on where the coding standard prohibited early return had functions littered with boolean variables (with names like `continue_processing`) that controlled the execution of blocks of code further down in the function. – Greg Hewgill Aug 11 '09 at 00:23
  • 27
    What is RIAA? Is that anything like RAII? =D – jkeys Aug 11 '09 at 00:39
  • 2
    Depends how many for loops he's got and how deep the nest goes... do you want the blue pill or the red pill? – hookenz Mar 24 '14 at 04:16
38

break will exit only the innermost loop containing it.

You can use goto to break out of any number of loops.

Of course goto is often Considered Harmful.

is it proper to use the break function[...]?

Using break and goto can make it more difficult to reason about the correctness of a program. See here for a discussion on this: Dijkstra was not insane.

Mitja
  • 1,969
  • 30
  • 35
Karl Voigtland
  • 7,637
  • 34
  • 29
  • 20
    A good answer in that it explains that "goto is harmful" meme is strongly tied to the more generalized "control flow interruption is harmful" statement. It is meaningless to say "goto is harmful", and then turn around and recommend using `break` or `return`. – Pavel Minaev Aug 11 '09 at 00:46
  • 7
    @Pavel: `break` and `return` have the advantage over `goto` that you don't need to hunt for a label in order to find where they go. Yes, underneath they are some kind of `goto`, but a very restricted one. They are a lot easier to decipher by a programmer's pattern-matching brain than the unrestricted `goto`. So IMO they are preferable. – sbi Aug 11 '09 at 09:13
  • 2
    @sbi: True, but break is still not part of structured programming. It is just better tolerated than a `goto`. – jkeys Aug 11 '09 at 15:53
  • 3
    @KarlVoigtland the Dijkstra link is outdated; this appears to be working: http://blog.plover.com/2009/07/ – Aaron Brager Feb 21 '13 at 21:59
  • 7
    There is absolutely nothing wrong with using goto in this situation. A well placed goto is leaps and bounds better and more readable than many of the contorted solutions otherwise proposed. – James Sep 19 '13 at 13:07
  • I'd argue that C++'s "goto after_loop;" is so straightforward it's easier to understand than Java's "break before_loop;". I don't find it particularly elegant to quit a loop by referring to a label that's declared before the actual loop. I know the label is supposed to give the loop a name, but I never managed to like it. What if you put other statements between the label and the loop? Is that a syntax error to try to break? Same for continue statements. – Johan Boulé Feb 10 '21 at 19:14
36

How about this?

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;
            }
        }
    }
}
jebeaudet
  • 1,533
  • 16
  • 15
  • 2
    interesting approach but I definitely like the way ered @inf.ig.sh handles it. for (unsigned int y = 0; y < y_max && !gotoMainLoop; y++). – Andrew Jun 21 '12 at 20:06
23

Although this answear was already presented, i think a good approach is to do the following:

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;
        }
    }

}
scigor
  • 1,603
  • 5
  • 24
  • 38
22

A code example using goto and a label to break out of a nested loop:

for (;;)
  for (;;)
    goto theEnd;
theEnd:
Helio Santos
  • 6,606
  • 3
  • 25
  • 31
13

One nice way to break out of several nested loops is to refactor your code into a function:

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;
            }
        }
    }
}
Deqing
  • 14,098
  • 15
  • 84
  • 131
  • 4
    ...which is not a option if we have to pass 10-20 variables for stack framing this function. – Петър Петров Aug 28 '13 at 17:04
  • 1
    @ПетърПетров then go for a lambda which is also better as you can define it exactly where you need it. – DarioP Nov 07 '13 at 13:28
  • 1
    +1 for lambdas but overhaul in game engine core where even one stack frame is still a bottleneck. Sorry to tell, but lambdas are not so lightweight at least in MSVC 2010. – Петър Петров Apr 09 '14 at 13:12
  • @ПетърПетров Then change the pair of functions into a class, and the stack variables into private members. – Arthur Tacca Nov 10 '17 at 13:25
  • 1
    This only overcomplicates the already complex code :) Sometimes, goto is the only solution. Or if you write complex automata with "goto state X" documentation, then goto is actually making the code read as written in the document. Also, C# and go both have goto with a purpose: no language is turing-complete without a goto, and gotos are often the best used tools for writing intermediate translator or assembly-like code. – Петър Петров Dec 01 '17 at 14:35
  • @ПетърПетров If you have to pass 20 stack variables I'd argue there are bigger problems than the choice of `return` vs. `goto`. – c z Jun 01 '21 at 11:34
12

I know this is an old thread but I feel this really needs saying and don't have anywhere else to say it. For everybody here, use goto. I just used it.

Like almost everything, goto is not 100% either/xor "bad" or "good". There are at least two uses where I'd say that if you use a goto for them - and don't use it for anything else - you should not only be 100% okay, but your program will be even more readable than without it, as it makes your intention that much clearer (there are ways to avoid it, but I've found all of them to be much clunkier):

  1. Breaking out of nested loops, and
  2. Error handling (i.e. to jump to a cleanup routine at the end of a function in order to return a failure code and deallocate memory.).

Instead of just dogmatically accepting rules like "so-so is 'evil'", understand why that sentiment is claimed, and follow the "why", not the letter of the sentiment. Not knowing this got me in a lot of trouble, too, to the point I'd say calling things dogmatically "evil" can be more harmful than the thing itself. At worst, you just get bad code - and then you know you weren't using it right so long as you heard to be wary, but if you are wracking yourself trying to satisfy the dogmatism, I'd say that's worse.

Why "goto" is called "evil" is because you should never use it to replace ordinary ifs, fors, and whiles. And why that? Try it, try using "goto" instead of ordinary control logic statements, all the time, then try writing the same code again with the control logic, and tell me which one looks nicer and more understandable, and which one looks more like a mess. There you go. (Bonus: try and add a new feature now to the goto-only code.) That's why it's "evil", with suitable scope qualification around the "evil". Using it to short-circuit the shortcomings of C's "break" command is not a problematic usage, so long as you make it clear from the code what your goto is supposed to accomplish (e.g. using a label like "nestedBreak" or something). Breaking out of a nested loop is very natural.

(Or to put it more simply: Use goto to break out of the loop. I'd say that's even preferable. Don't use goto to create the loop. That's "evil".)

And how do you know if you're being dogmatic? If following an "xyz is evil" rule leads your code to be less understandable because you're contorting yourself trying to get around it (such as by adding extra conditionals on each loop, or some flag variable, or some other trick like that), then you're quite likely being dogmatic.

There's no substitute for learning good thinking habits, moreso than good coding habits. The former are prior to the latter and the latter will often follow once the former are adopted. The problem is, however, that far too often I find, the latter are not explicated enough. Too many simply say "this is bad" and "this needs more thought" without saying what to think, what to think about, and why. And that's a big shame.

(FWIW, in C++, the need to break out of nested loops still exists, but the need for error codes does not: in that case, always use exceptions to handle error codes, never return them unless it's going to be so frequent that the exception throw and catch will be causing a performance problem, e.g. in a tight loop in a high demand server code, perhaps [some may say that 'exceptions' should be 'used rarely' but that's another part of ill-thought-out dogmatism: no, at least in my experience after bucking that dogma I find they make things much clearer - just don't abuse them to do something other than error handling, like using them as control flow; effectively the same as with "goto". If you use them all and only for error handling, that's what they're there for.].)

The_Sympathizer
  • 1,191
  • 9
  • 17
8

I'm not sure if it's worth it, but you can emulate Java's named loops with a few simple macros:

#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

Example usage:

#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);
        }
    }
}

Another example:

#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);
}
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • 1
    This is the most brilliant thing I've seen in this thread – radrow Jul 14 '22 at 13:04
  • Although, it seems to let the outer loop to finish its current routine. It also doesn't directly "jump over" multiple levels of nested loops. – radrow Jul 14 '22 at 13:06
  • @radrow Can you show an example of the wrong behavior? Seems to [work correctly](https://gcc.godbolt.org/z/jhTY8v6Pa) for me. – HolyBlackCat Jul 14 '22 at 13:33
  • Nevermind, I tested it and it works perfectly indeed. However, an explanation on how it works would be useful :) – radrow Jul 15 '22 at 09:51
  • 1
    @radrow There's not much to see here, once you expand the macros and look at the result. The loop body becomes `if (false) {...} else {/*original loop body*/}`, where the first branch that's never taken contains a few goto labels, that `BREAK` and `CONTINUE` jump to. – HolyBlackCat Jul 15 '22 at 10:09
  • Totally worth it! Very nice. Thanks. – Dumbled0re Jul 25 '22 at 15:36
  • Question: Does the if statement really need to declare a variable? My experiments suggest it could be simplified to `if (0) { ....` – Dumbled0re Jul 25 '22 at 18:27
  • 1
    @Dumbled0re The variable is needed to stop you from using break/continue outside of this loop. The compiler refuses to `goto` into a scope if it requires creating a new variable, allowing you to break/continue only inside this if-else block. – HolyBlackCat Jul 25 '22 at 18:29
  • @Dumbled0re FYI, the best place to try out formatting is [this](https://meta.stackexchange.com/questions/3122/formatting-sandbox). – HolyBlackCat Jul 25 '22 at 19:08
  • 1
    have an upvote – mwallner Jul 27 '23 at 07:21
7

goto can be very helpful for breaking nested loops

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
4

I do think a goto is valid in this circumstance:

To simulate a break/continue, you'd want:

Break

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

Continue

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

The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.

from msdn.

Rob
  • 2,148
  • 13
  • 17
1

Break any number of loops by just one bool variable see below :

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;
    }
}

In this code we break; all the loops.

Vikas Bansal
  • 2,184
  • 2
  • 15
  • 18
1

My suggestion is use a check variable to break a desired loop. The result code may not be so pleasant.
You can use preprocessors in order to make desired breaking under the hood. This approach can hides ugly codes and extra complexity.
For example, I created my custom break mechanism as follow:

Wanted code:

for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 100; k++) {
            //do something
            if (desiredCondition) {
                breakToLevel = 0;
            }
            if (breakToLevel < 3) {
                break;
            }
        }
        if (breakToLevel < 2) {
            break;
        }
    }
    if (breakToLevel < 1) {
        break;
    }
}

Defined macros:

#define BREAK_TO(L) breakToLevel = (L); 
#define CHECK_BREAK(L) if (breakToLevel < (L)) break; 

and result:

for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 100; k++) {
            //do something
            if (desiredCondition) {
                BREAK_TO(0)
            }
            CHECK_BREAK(3)
        }
        CHECK_BREAK(2)
    }
    CHECK_BREAK(1)
}
S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59
0

Other languages such as PHP accept a parameter for break (i.e. break 2;) to specify the amount of nested loop levels you want to break out of, C++ however doesn't. You will have to work it out by using a boolean that you set to false prior to the loop, set to true in the loop if you want to break, plus a conditional break after the nested loop, checking if the boolean was set to true and break if yes.

Patrick Glandien
  • 7,791
  • 5
  • 41
  • 47
0

I know this is old post . But I would suggest a bit logical and simpler answer.

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;
            }
        }
    }
  • 3
    That's not very scalable solution as `j = conditionj` won't work if you have a complex predicate instead of `j < conditionj`. – Sergey Sep 14 '16 at 16:01
0
 bool found = false;
    
    for(int i=0; i < m; ++i){
        for(int j=0; j < n; ++j)
            if(grid[i][j] == '*'){
                q.push(make_pair(i,j));
                found = true;
                break;
            }
        if(found)
            break;
    }
0

you can use "goto" to leave nested loops below is my original code including "goto"

int main()
{
    string str;
    while (cin >> str)
    {
        if (str == "0")
            break;
        int sum = 0;
        for (auto ch : str)
        {
            if (ch <= 'z' && ch >= 'a')
                sum += (ch - 'a' + 1);
            else if (ch >= 'A' && ch <= 'Z')
                sum += (ch - 'A' + 1);
            else
            {
                cout << "Fail" << endl;
                goto fail;
            }
        }

        cout << sum << endl;
        fail:
    }
    return 0;
}

however, I could avoid "goto" by adding a function "calculate"

void calculate(const string &str)
{
    int sum = 0;
    for (auto ch : str)
    {
        if (ch <= 'z' && ch >= 'a')
            sum += (ch - 'a' + 1);
        else if (ch >= 'A' && ch <= 'Z')
            sum += (ch - 'A' + 1);
        else
        {
            cout << "Fail" << endl;
            return;
        }
    }

    cout << sum << endl;
}

int main()
{
    string str;
    while (cin >> str)
    {
        if (str == "0")
            break;
        calculate(str);
    }
    return 0;
}
Jimmy wu
  • 23
  • 4
0

The most graceful way is to use exception.

Exception means encountering an abnormal situation, which can not only be a too bad situation but also be a too good situation.

For example you are looking for an element in a 3d array with 3 nested for-loops. The normal situation is "The current is NOT the one I'm looking for". The abnormal situation is "The current IS the one".

Remember the difference between error and exception. An exception doesn't have to be an error, it can be a good news.

Zim
  • 1,528
  • 1
  • 10
  • 6
-1
  while (i<n) {
    bool shouldBreakOuter = false;
    for (int j=i + 1; j<n; ++j) {
      if (someCondition) {
          shouldBreakOuter = true;
      }
    }

    if (shouldBreakOuter == true)
      break;

  }
Ennabah
  • 2,303
  • 2
  • 20
  • 39
-2

You can use 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

If you have to break out of several loops at once, it is often an exception anyways.

lawilog
  • 173
  • 6
  • 1
    I would like to know the reason why this answer get this much down-votes. – hkBattousai Jun 18 '15 at 13:10
  • 7
    @hkBattousai The solution has down votes because it's using an exception to control the execution flow. As the name suggests, exceptions should only be used on exceptional cases. – Helio Santos Jun 18 '15 at 21:07
  • 4
    @HelioSantos Isn't this an exceptional situation for which the language is not supplying proper solution? – hkBattousai Jun 21 '15 at 11:14
  • It would be valid if 1. my program is compiled with exceptions support (never in my case) and 2. it really WAS an exception 3. You are willing to put up with the horrific overhead. – Mr. Developerdude Jan 04 '17 at 12:01
  • 3
    The performance impact of the throw is huge for something that is not an unrecoverable error 99% of the time. – Michaël Roy Jun 16 '17 at 05:24
  • 2
    @hkbattousai The language does provide solutions, such as using a a test condition, or using a `goto`. – Michaël Roy Jun 17 '17 at 21:17
  • 1
    Also, if another exception was thrown from that code block, you would catch it, thinking it is the control flow one and it would get propagated/handled properly. – John Smith Apr 26 '18 at 20:06
-5

Breaking out of a for-loop is a little strange to me, since the semantics of a for-loop typically indicate that it will execute a specified number of times. However, it's not bad in all cases; if you're searching for something in a collection and want to break after you find it, it's useful. Breaking out of nested loops, however, isn't possible in C++; it is in other languages through the use of a labeled break. You can use a label and a goto, but that might give you heartburn at night..? Seems like the best option though.

Nick Lewis
  • 4,150
  • 1
  • 21
  • 22
  • 12
    It's not strange at all. If you're iterating over a collection to look for something (and don't have a faster way of searching), there's no point finishing the loop. (as one example) – Joe Aug 11 '09 at 00:44