sundowatch
sundowatch

Reputation: 3103

C++: break the main loop

I am preparing some code:

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
    {
       .
       .
       .
    }
}

I want to break the main loop (loop variable int a) by using a break; statement in the b loop (loop variable int b).

How can I do it?

Upvotes: 10

Views: 7660

Answers (11)

Justin Ethier
Justin Ethier

Reputation: 134157

I recommend refactoring your code into a function. Then you can just return from that function instead of using 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
        }

        .
        .
        .
    }
}

This - or perhaps even a more involved refactoring of your code - should lend itself to a clean, elegant solution. Alternatively, if you just want a quick fix you could use a condition variable:

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;

    .
    .
    .
}

Others have suggested using goto. While that is another quick fix, I strongly recommend against it, especially if you are working in a rigorous environment where the code will be peer reviewed and used for years down the road.

In my opinion the goto approach is a bit harder to maintain than a function/return refactoring, especially later on when someone else makes changes to the code. Plus you will have to justify the goto to anyone else on the team that happens to stumble onto the code.

Upvotes: 21

Gunslinger47
Gunslinger47

Reputation: 7061

\ (◕ ◡ ◕) /

[]() {
    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
        {
           .
           .
           .
        }
    }
}();

Upvotes: 4

David Thornley
David Thornley

Reputation: 57036

The only way to head out of two such loops at a time is a goto or a throw or a return, and throw and return may not be appropriate (particularly throw, if the condition isn't exceptional). Alternately, you could set some sort of condition (bool breakout;), and keep breaking if it's true.

Upvotes: 4

bta
bta

Reputation: 45057

The ideal way would be to re-factor your code so that you no longer need such a complicated nested-loop structure. Depending on what the rest of your code looks like, your b and c loops may be candidates for becoming individual functions, if not the entire a loop.

Since it looks like loops b and c iterate over adjacent ranges, why not combine them and reduce your loop nesting a bit?

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:

You can also use a condition variable instead of the goto. If you want to break out of the old b loop but still process the old c loop, simply set count = 2001 inside the old b loop code.

Ideally, you would at least be able to re-factor this to something more like

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

where the function process_inner_loop wraps up your original two loops and returns non-zero if you want to break out of the enclosing loop. Now, instead of using goto or condition variables, you can simply return 1;.

Upvotes: 2

GManNickG
GManNickG

Reputation: 503865

Either do one of four things: use goto, use throw, use a flag, or refactor.

Many will disagree with using goto, but sometimes it's a clean solution. (Most times, it isn't, but it exists for a reason.) However, I find the use of goto warrants a refactor.

The second solution is to throw some special exception and then catch it just outside the main loop. This is an abuse of the exception system and basically a worse goto; use a goto instead of this.

The third solution would be to use a flag of some sort. This is basically a "safer" goto, but some might argue it's a bit uglier. (Especially with multiple-levels. Though in such a case your concern is how ugly your code is.)

The solution I would recommend is refactor. Whatever you're doing, it's too much. You should move the inner loops into a function, and call that function. Returning to the main loop is simply a return from that function. (In other words "My work is done.")

Upvotes: 23

One simple strategy is to put the loop in a separate function and do a return at the selected point:

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
        {
           .
           .
           .
        }
    }
}

Any kind of result may also be returned with a return value, or with a reference parameter for the function.

Upvotes: 2

WillfulWizard
WillfulWizard

Reputation: 5409

If it is appropriate, you could make a function who's contents are the a loop, and use 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

Upvotes: 4

tpdi
tpdi

Reputation: 35141

  1. Use a 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. set a sentinel value tested by each loop:

    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
        {
           .
           .
           .
        }
    }
    

Upvotes: 3

Bang Dao
Bang Dao

Reputation: 5102

Use this kind of pattern

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++)
    {
       .
       .
       .
    }
}

Upvotes: 1

adamk
adamk

Reputation: 46804

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:

Upvotes: 4

Carl Norum
Carl Norum

Reputation: 224944

Use a 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:

Upvotes: 34

Related Questions