How to break out of a loop from inside a switch?

C++LoopsSyntaxSwitch StatementBreak

C++ Problem Overview


I'm writing some code that looks like this:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        break; // **HERE, I want to break out of the loop itself**
    }
}

Is there any direct way to do that?

I know I can use a flag, and break from the loop by putting a conditional break just after the switch. I just want to know if C++ has some construct for this already.

C++ Solutions


Solution 1 - C++

You can use goto.

while ( ... ) {
   switch( ... ) {
     case ...:
         goto exit_loop;

   }
}
exit_loop: ;

Solution 2 - C++

An alternate solution is to use the keyword continue in combination with break, i.e.:

for (;;) {
    switch(msg->state) {
    case MSGTYPE:
        // code
        continue; // continue with loop
    case DONE:
        break;
    }
    break;
}

Use the continue statement to finish each case label where you want the loop to continue and use the break statement to finish case labels that should terminate the loop.

Of course this solution only works if there is no additional code to execute after the switch statement.

Solution 3 - C++

Premise

The following code should be considered bad form, regardless of language or desired functionality:

while( true ) {
}

Supporting Arguments

The while( true ) loop is poor form because it:

  • Breaks the implied contract of a while loop.
    • The while loop declaration should explicitly state the only exit condition.
  • Implies that it loops forever.
    • Code within the loop must be read to understand the terminating clause.
    • Loops that repeat forever prevent the user from terminating the program from within the program.
  • Is inefficient.
    • There are multiple loop termination conditions, including checking for "true".
  • Is prone to bugs.
    • Cannot easily determine where to put code that will always execute for each iteration.
  • Leads to unnecessarily complex code.
  • Automatic source code analysis.
    • To find bugs, program complexity analysis, security checks, or automatically derive any other source code behaviour without code execution, specifying the initial breaking condition(s) allows algorithms to determine useful invariants, thereby improving automatic source code analysis metrics.
  • Infinite loops.
    • If everyone always uses while(true) for loops that are not infinite, we lose the ability to concisely communicate when loops actually have no terminating condition. (Arguably, this has already happened, so the point is moot.)

Alternative to "Go To"

The following code is better form:

while( isValidState() ) {
  execute();
}

bool isValidState() {
  return msg->state != DONE;
}

Advantages

No flag. No goto. No exception. Easy to change. Easy to read. Easy to fix. Additionally the code:

  1. Isolates the knowledge of the loop's workload from the loop itself.
  2. Allows someone maintaining the code to easily extend the functionality.
  3. Allows multiple terminating conditions to be assigned in one place.
  4. Separates the terminating clause from the code to execute.
  5. Is safer for Nuclear Power plants. ;-)

The second point is important. Without knowing how the code works, if someone asked me to make the main loop let other threads (or processes) have some CPU time, two solutions come to mind:

Option #1

Readily insert the pause:

while( isValidState() ) {
  execute();
  sleep();
}
Option #2

Override execute:

void execute() {
  super->execute();
  sleep();
}

This code is simpler (thus easier to read) than a loop with an embedded switch. The isValidState method should only determine if the loop should continue. The workhorse of the method should be abstracted into the execute method, which allows subclasses to override the default behaviour (a difficult task using an embedded switch and goto).

Python Example

Contrast the following answer (to a Python question) that was posted on StackOverflow:

  1. Loop forever.
  2. Ask the user to input their choice.
  3. If the user's input is 'restart', continue looping forever.
  4. Otherwise, stop looping forever.
  5. End.
Code
while True: 
    choice = raw_input('What do you want? ')

    if choice == 'restart':
        continue
    else:
        break

print 'Break!' 

Versus:

  1. Initialize the user's choice.
  2. Loop while the user's choice is the word 'restart'.
  3. Ask the user to input their choice.
  4. End.
Code
choice = 'restart';

while choice == 'restart': 
    choice = raw_input('What do you want? ')

print 'Break!'

Here, while True results in misleading and overly complex code.

Solution 4 - C++

A neatish way to do this would be to put this into a function:

int yourfunc() {

    while(true) {

        switch(msg->state) {
        case MSGTYPE: // ... 
            break;
        // ... more stuff ...
        case DONE:
            return; 
        }

    }
}

Optionally (but 'bad practices'): as already suggested you could use a goto, or throw an exception inside the switch.

Solution 5 - C++

AFAIK there is no "double break" or similar construct in C++. The closest would be a goto - which, while it has a bad connotation to its name, exists in the language for a reason - as long as it's used carefully and sparingly, it's a viable option.

Solution 6 - C++

You could put your switch into a separate function like this:

bool myswitchfunction()
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        return false; // **HERE, I want to break out of the loop itself**
    }
    return true;
}

while(myswitchfunction())
    ;

Solution 7 - C++

Even if you don't like goto, do not use an exception to exit a loop. The following sample shows how ugly it could be:

try {
  while ( ... ) {
    switch( ... ) {
      case ...:
        throw 777; // I'm afraid of goto
     }
  }
}
catch ( int )
{
}

I would use goto as in this answer. In this case goto will make code more clear then any other option. I hope that this question will be helpful.

But I think that using goto is the only option here because of the string while(true). You should consider refactoring of your loop. I'd suppose the following solution:

bool end_loop = false;
while ( !end_loop ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        end_loop = true; break;
    }
}

Or even the following:

while ( msg->state != DONE ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
}

Solution 8 - C++

There's no C++ construct for breaking out of the loop in this case.

Either use a flag to interrupt the loop or (if appropriate) extract your code into a function and use return.

Solution 9 - C++

No, C++ does not have a construct for this, given that the keyword "break" is already reserved for exiting the switch block. Alternatively a do..while() with an exit flag could suffice.

do { 
    switch(option){
        case 1: ..; break;
        ...
        case n: .. ;break;
        default: flag = false; break;
    }
} while(flag);

Solution 10 - C++

You could potentially use goto, but I would prefer to set a flag that stops the loop. Then break out of the switch.

Solution 11 - C++

Why not just fix the condition in your while loop, causing the problem to disappear?

while(msg->state != DONE)
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        // We can't get here, but for completeness we list it.
        break; // **HERE, I want to break out of the loop itself**
    }
}

Solution 12 - C++

It amazes me how simple this is considering the depth of explanations... Here's all you need...

bool imLoopin = true;

while(imLoopin) {

    switch(msg->state) {

        case MSGTYPE: // ... 
            break;

        // ... more stuff ...

        case DONE:
            imLoopin = false;
            break;

    }

}

LOL!! Really! That's all you need! One extra variable!

Solution 13 - C++

I think;

while(msg->state != mExit) 
{
    switch(msg->state) 
    {
      case MSGTYPE: // ...
         break;
      case DONE:
      //  .. 
      //  ..
      msg->state =mExit;
      break;
    }
}
if (msg->state ==mExit)
     msg->state =DONE;

Solution 14 - C++

I got same problem and solved using a flag.

bool flag = false;
while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        flag = true; // **HERE, I want to break out of the loop itself**
    }
    if(flag) break;
}

Solution 15 - C++

Because the switch uses the break to break out from the switch (not from the while(1)), it needs the goto-statement:

while(1) {
    switch (*p) {
      case ' ':
        p++;
        break;
      case '\n':
        p++; *s=p; return(i);
      case '\0':
        *s=p; return(i);
      default:
        token[i]=p;
        i++;
        p++;
        goto ex1;
    };
  };
  ex1:

I can't add multiple case to same line like:

case ' ','\t':

it would be

case ' ': case '\t':

That's why maybe the break used here...

It looks the most frequent cases should be placed at the top of the list to make the program run faster. It may not have parallel execution for searching the different cases.

It is possible that the standard c then has missing some methods about this switching: https://blog.hackajob.co/better-c-switch-statements-for-a-range-of-values/ => allows you to use the <, >, <=, and >= operators in a switch expression

I was thinking that it should be (if c-language syntax changed) like:

switch (c) {
  case >= 5:
     ... op1
  endcase;
  case == 1:
  case == 3:
     ... op2
  endcase;
  default:
    ...
};

where op2 is executed when c is equal to 1 or 3 and when c is larger than or equal to 5 op1 is executed. Because comparison for equal or larger/smaller than would occur easily in similar manner.

  while(1) {
    switch (c) {
      case >= 2:
         ... op1
      case <= 5:
         ... op2
      break;
      default:
        ...
    };
  };

this case op1 is executed for c larger than 2 and op2 executed for 2<=c<=5 and break exits it from while-loop.

Solution 16 - C++

The simplest way to do it is to put a simple IF before you do the SWITCH , and that IF test your condition for exiting the loop .......... as simple as it can be

Solution 17 - C++

The break keyword in C++ only terminates the most-nested enclosing iteration or switch statement. Thus, you couldn't break out of the while (true) loop directly within the switch statement; however you could use the following code, which I think is an excellent pattern for this type of problem:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

If you needed to do something when msg->state equals DONE (such as run a cleanup routine), then place that code immediately after the for loop; i.e. if you currently have:

while (true) {
    switch (msg->state) {
    case MSGTYPE:
        //... 
        break;

    //...

    case DONE:
        do_cleanup();
        break;
    }

    if (msg->state == DONE)
        break;

    msg = next_message();
}

Then use instead:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

assert(msg->state == DONE);
do_cleanup();

Solution 18 - C++

while(MyCondition) {
switch(msg->state) {
case MSGTYPE: // ... 
    break;
// ... more stuff ...
case DONE:
   MyCondition=false; // just add this code and you will be out of loop.
    break; // **HERE, you want to break out of the loop itself**
}
}

Solution 19 - C++

If I remember C++ syntax well, you can add a label to break statements, just like for goto. So what you want would be easily written:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ...
        break;
    // ... more stuff ...
    case DONE:
        break outofloop; // **HERE, I want to break out of the loop itself**
    }
}

outofloop:
// rest of your code here

Solution 20 - C++

  while(true)
  {
    switch(x)
    {
     case 1:
     {
      break;
     }
    break;
   case 2:
    //some code here
   break;
  default:
  //some code here
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjrharshathView Question on Stackoverflow
Solution 1 - C++mmxView Answer on Stackoverflow
Solution 2 - C++sakraView Answer on Stackoverflow
Solution 3 - C++Dave JarvisView Answer on Stackoverflow
Solution 4 - C++AlterlifeView Answer on Stackoverflow
Solution 5 - C++AmberView Answer on Stackoverflow
Solution 6 - C++Adam PierceView Answer on Stackoverflow
Solution 7 - C++Kirill V. LyadvinskyView Answer on Stackoverflow
Solution 8 - C++sharptoothView Answer on Stackoverflow
Solution 9 - C++Prashanth SriramView Answer on Stackoverflow
Solution 10 - C++Martin YorkView Answer on Stackoverflow
Solution 11 - C++Mark BView Answer on Stackoverflow
Solution 12 - C++Mark A. DonohoeView Answer on Stackoverflow
Solution 13 - C++ercanView Answer on Stackoverflow
Solution 14 - C++Ram SutharView Answer on Stackoverflow
Solution 15 - C++user1070696View Answer on Stackoverflow
Solution 16 - C++SpiriAdView Answer on Stackoverflow
Solution 17 - C++Daniel TrebbienView Answer on Stackoverflow
Solution 18 - C++Wajeed-MSFTView Answer on Stackoverflow
Solution 19 - C++Andrei Vajna IIView Answer on Stackoverflow
Solution 20 - C++ChevaughnView Answer on Stackoverflow