134

If I use a break statement, it will only break inner loop and I need to use some flag to break the outer loop. But if there are many nested loops, the code will not look good.

Is there any other way to break all of the loops? (Please don't use goto stmt.)

for (int i = 0; i < 1000; i++) {
   for (int j = 0; j < 1000; j++) {
       if (condition) {
            // both of the loops need to break and control will go to stmt2
       }
   }    
}

stmt2
pevik
  • 4,523
  • 3
  • 33
  • 44
user966379
  • 2,823
  • 3
  • 24
  • 30
  • 2
    you may try int i and int j before the loop starts and then on the condition make them 1001 the loop will not iterate the next . – Khurram Ijaz Mar 14 '12 at 04:25
  • C++ version: http://stackoverflow.com/questions/1257744/can-i-use-break-to-exit-multiple-nested-for-loops – Ciro Santilli OurBigBook.com Mar 19 '15 at 10:12
  • 1
    I had a professor who's pet peeve was that you couldn't send a parameter to break, to indicate how many levels out you could go. If he had his way, the answer to your question would simply be 'break(2);', where '2' is the number of loops to break out of. – Adam Wise Oct 01 '21 at 14:06

15 Answers15

272

No, don't spoil the fun with a break. This is the last remaining valid use of goto ;)

If not this then you could use flags to break out of deep nested loops.

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.

Summarized - to break out of nested loops:

  1. use goto
  2. use flags
  3. factor out loops into separate function calls

Couldn't resist including xkcd here :)

enter image description here

source

Goto's are considered harmful but as many people in the comments suggest it need not be. If used judiciously it can be a great tool. Anything used in moderation is fun.

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
  • 47
    Goto is about as clear as you'll get here, yeah. Setting the exit variable to 1000 is even more kludgy. – correnos Mar 14 '12 at 04:33
  • 5
    I would like to add that gotos are not explicitly evil, they just can be used for evil. I find that there are quite a few cases, for example this, where they are the best solution. "Don't use gotos" is a good start, but I think the next step in skill allows you "Don't use long-range gotos". – Aatch Mar 14 '12 at 04:37
  • 1
    although I like `goto`s for the WTF value, I strongly suggest going route 3 - applying it in all but the most trivial cases, it IMO gives the best results in the long run. –  Jun 07 '16 at 21:29
  • 1
    i love this comic. On a side note, `goto` is best if you know what you're doing and how to use it correctly. I use it all the time for breaking out of nested loops. Setting a flag solely for this purpose is ugly, and adds an extra compare instruction to every loop. Creating a function results in exponential amounts of add/subtracting the stack pointer. – rosghub Dec 02 '16 at 05:44
  • I agree that there are cases where `goto` is the best answer (clearest, most efficient). But as a general rule, it's best to use `goto` to break out of a statement, rather than to enter it. Among other things, this will always result in a reducible flow graph (which should not impede optimization). Try to avoid using `goto ` to enter a statement, such as a loop (which will generally result in an irreducible flow graph). – Tom Karzes Sep 17 '17 at 10:06
  • 1
    I would like to disagree with this: "Creating a function results in exponential amounts of add/subtracting the stack pointer". If there is a local (static) function which is called at only one point in the program flow, any half-decent compiler will inline it, and the resulting code is essentially the same as with goto. This possibly the easiest optimization case for any compiler. – DrV Nov 17 '17 at 11:25
  • 1
    Refactoring is usually the cleanest solution. However, if any outside-of-loop variables are changed during the inner loop, things get complicated. One possibility is to pass the variable to the inner function by reference (pointer), but this may confuse the compiler optimization and produce unnecessary extra code. Another possibility is to make such variables static at the module level, but that is not very beautiful, either. C is unfortunately missing nested functions, as they would solve this problem — unless you are willing to bind yourself to using gcc which provides an extension. – DrV Nov 17 '17 at 11:34
  • 3
    +1. And Donald E. Knuth's Structured Programming with go to Statements (http://wiki.c2.com/?StructuredProgrammingWithGoToStatements) is an interesting article to balance Dijkstra's. – kmkaplan Mar 09 '18 at 09:21
  • > Couldn't resist not including xkcd here :) There is one "not" too many there. I hate to seem like (be) a nitpicker, but SO didn't allow me to correct it because the edit was too short. – Elias Hasle Jan 21 '19 at 06:56
  • I've been told god kills a kitten whenever someone uses a `goto`. But fear not, she'll probably settle for a small one since this is kind of a valid use. – Daniel Feb 21 '19 at 10:50
56

Use:

if (condition) {
    i = j = 1000;
    break;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 65
    Works, but ugly and not general. What if someone changes the limit to 2000 (suppose the code is longer, so you don't immediately notice it)? – ugoren Mar 14 '12 at 08:17
  • 2
    @ugoren It's also so simple then. what if you used a `const int count =1000 `, in the global Initialization. or as a `#define` macro. – Laksith Oct 19 '15 at 07:37
  • 7
    As @ugoren points out, it's not a general solution. Since this is the first Google hit for this question, it would be nice if the general solution had been selected. Well people are used to checking out the #2 anyway. – BeeOnRope Nov 04 '16 at 23:30
  • 1
    I guess only need i=1000? – Peter Wu Aug 02 '19 at 02:05
55

One way is to put all the nested loops into a function and return from the inner most loop incase of a need to break out of all loops.

function() 
{    
  for(int i=0; i<1000; i++)
  {
   for(int j=0; j<1000;j++)
   {
      if (condition)
        return;
   }
  }    
}
Jay
  • 24,173
  • 25
  • 93
  • 141
50
bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
    for (int j = 0; (j < 1000) && !stop; j++)
    {
        if (condition)
            stop = true;
    }
}
Tung
  • 5,334
  • 1
  • 34
  • 41
  • Solution still increments both variables by one on _break_ which can cause trouble – TheSola10 Mar 30 '17 at 07:33
  • 10
    One can set "stop = true;" and then "break;". Then, right after the end of the inside "for" loop, do "if (stop) break;". – Jeff Grigg Aug 29 '17 at 05:49
  • 3
    I think this is the most elegant non-`goto` solution. It doesn't require knowing the limits of `i` and `j` within the condition. I like the idea of putting `if (stop) break;` after the inner loop, which could itself `break` after setting `stop`. – Willis Blackburn Oct 15 '20 at 13:55
31

You'll need a boolean variable, if you want it readable:

bool broke = false;
for(int i = 0; i < 1000; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
  if (broke)
    break;
}

If you want it less readable you can join the boolean evaluation:

bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
}

As an ultimate way you can invalidate the initial loop:

for(int i = 0; i < size; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      i = size;
      break;
    }
  }
}
Jack
  • 131,802
  • 30
  • 241
  • 343
  • The last solution is the best for performance. Do not check additional booleans if further conditional branches can be avoided. – Engineer May 08 '22 at 22:47
26

I think goto will solve the problem

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; j++) {
        if (condition) {
            goto end;
        }
    }
}

end:
stmt2 

 
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
Renjith K N
  • 2,613
  • 2
  • 31
  • 53
  • @chikuba I got answer from http://www.cprogramming.com/tutorial/goto.html and your answer is not posted when i am doing the same thing thats why i dont see your post – Renjith K N Mar 14 '12 at 04:38
11

Use this wise advice from LLVM team:

"Turn Predicate Loops into Predicate Functions"

See:

http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions

R Sahu
  • 204,454
  • 14
  • 159
  • 270
ouah
  • 142,963
  • 15
  • 272
  • 331
7

Caution: This answer shows a truly obscure construction.

If you are using GCC, check out this library. Like in PHP, break can accept the number of nested loops you want to exit. You can write something like this:

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // break two nested enclosing loops
            break(2);
       }
   }
}
DaBler
  • 2,695
  • 2
  • 26
  • 46
  • 2
    And under the hood it is indeed [using `goto`](https://github.com/xbarin02/c-ext/blob/master/include/break#L35) :) – jacobq Aug 16 '19 at 11:51
  • @iX3 I can use inline assembler and jmp instruction if that helps. – DaBler Aug 19 '19 at 09:48
  • @DaBler, I didn't realize you were the author of that library. My comment was not meant as feedback but rather noting that this library uses the same method as [the accepted answer](https://stackoverflow.com/questions/9695902/how-to-break-out-of-nested-loops/47947714#answer-9695942). Hopefully your comment was meant as a joke because I think that using a language feature (even `goto`) is far preferably to inline asm (machine specific, easier to make a mistake, harder to read, ...). – jacobq Aug 19 '19 at 11:35
  • @DaBler: the definition `#define do(cond)` is somewhat confusing: you should use `def` instead of `cond` to clarify that the macro argument is a definition, not a condition. – chqrlie Jul 11 '22 at 07:35
4
for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; i++) {
       if(condition) {
            goto end;
   }
} 

end:
chikuba
  • 4,229
  • 6
  • 43
  • 75
3

If you need the values of i and j, this should work but with less performance than others

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}
  • Note that if the condition is dependent on `j` then the value of the condition needs to be stored in some way for this to still work. – SuperBiasedMan Jun 03 '15 at 16:02
  • 1
    You are right but after **break**, the value of **j** doesn't change and so is the value of the condition. – Ali Eren Çelik Jun 04 '15 at 07:48
  • 2
    This is a broken solution and not valid in general. Either j isn't defined outside its loop or `for (int i = 0; i < 1000; i++) { for (int j = 0; j < 1000; j++) { if (workComplete[i][j]) break; /* do work */ workComplete[i][j] = true; } if (workComplete[i][j]) break; ... }` is going to **always** break out of the outer loop after the first iteration of the inner loop. – Chai T. Rex Jan 01 '20 at 02:49
1

A different approach is to refactor the code from two for loops into a for loop and one manual loop. That way the break in the manual loop applies to the outer loop. I used this once in a Gauss-Jordan Elimination which required three nested loops to process.

for (int i = 0; i < 1000; i++)
{
    int j = 0;

MANUAL_LOOP:;

    if (j < 1000)
    {
       if (condition)
       {
           break;
       }

       j++;
       goto MANUAL_LOOP;
    }
}
EvilTeach
  • 28,120
  • 21
  • 85
  • 141
1

I note that the question is simply, "Is there any other way to break all of the loops?" I don't see any qualification but that it not be goto, in particular the OP didn't ask for a good way. So, how about we longjmp out of the inner loop? :-)

#include <stdio.h>
#include <setjmp.h>

int main(int argc, char* argv[]) {
  int counter = 0;
  jmp_buf look_ma_no_goto;
  if (!setjmp(look_ma_no_goto)) {
    for (int i = 0; i < 1000; i++) {
      for (int j = 0; j < 1000; j++) {
        if (i == 500 && j == 500) {
          longjmp(look_ma_no_goto, 1);
        }
        counter++;
      }
    }
  }
  printf("counter=%d\n", counter);
}

The setjmp function returns twice. The first time, it returns 0 and the program executes the nested for loops. Then when the both i and j are 500, it executes longjmp, which causes setjmp to return again with the value 1, skipping over the loop.

Not only will longjmp get you out of nested loops, it works with nested functions too!

Willis Blackburn
  • 8,068
  • 19
  • 36
  • Just when you think you know C... – Danijel Jun 20 '22 at 08:31
  • `longjmp()` is **much worse** than `goto` for this purpose. Your example has undefined behavior because the value of `counter` after returning a second time from `setjmp()` could be `500500` as expected or `0` if `counter` happens to reside in a register saved and restored by `setjmp()`. To avoid this pitfall, you could qualify `counter` as `volatile`... DV for advocating a dreadful solution with only an implied caveat. – chqrlie Jul 11 '22 at 07:19
-3
for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
       if(condition) {
          func(para1, para2...);
          return;
       }
    }
}

func(para1, para2...) {
    stmt2;
}
berlloon
  • 41
  • 6
  • So basically you're saying that it should (1) make a bunch of extra function calls and then (2) spin for the rest of the time when `condition` becomes false. Oh, and the second loop will run forever because it increments `i` instead of `j`, whoops... – jacobq Aug 16 '19 at 11:54
-3
int i = 0, j= 0;

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition){
            i = j = 1001;
            break;
        }
    }
}

Will break both the loops.

Andy Hayden
  • 359,921
  • 101
  • 625
  • 535
Khurram Ijaz
  • 1,844
  • 5
  • 24
  • 43
-4
i = 0;

do
{
  for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here!
  {
     if (condition)
     {
       break;
     }
  }

  ++i;

} while ((i < 1000) && !condition);
guga
  • 714
  • 1
  • 5
  • 15