Reputation: 26583
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.
Upvotes: 170
Views: 189283
Reputation: 400
Well its the crazy unruly homegrown cpp programmer with another one. The classy programmers have cringed against using terminating conditions inside loop body but I highly disagree. I qualify my belief with the fact that I used loops much more than the regular programmer, since I do text parsing manually and not with regex. Plus other kinds of situtations where I needed loops. So I understand the need for terminating conditions inside loops. Infact, even if I only have one condition, I may prefer a while(true) loop; in order to do all my code inside the loop body. eg:
while(true)
{
if(condition)
{
// do something
return;
}
// .... long body
}
This format allows persons to see what action is taken on loop termination immediately.
Anyhow, I will explain the BREAK_OUT_OF keyword. It allows you to break out of outer loops or switch statements, from within an inner loop or switch statement. This keyword is set to come in the next version of cpp, cpp 2026. But dont worry, for now you can emulate it in your primitive cpp compilers. Here are the steps.
Step 1: Download the BREAK_OUT_OF keyword package with the following command:
#define BREAK_OUT_OF(ID) goto STATEMENT##ID
#define S_ID(ID)
#define DEF_S_ID(ID) STATEMENT##ID:
Dont be fooled by the goto statement in the commands. Its not a regular goto statement that we all hate. Its a jmp statement in disguise.
Step 2: Now that you downloaded the compatibility package; when you need to break out of an outer statement from within an inner statement; you first give it an ID. You do this using S_ID keyword.
while(true) S_ID(first_loop)
Step 3: Place DEF_S_ID keyword immediately after statement body. Note that in the up coming cpp 26, This will automatically be done for us.
while(true) S_ID(first_loop)
{
}DEF_S_ID(first_loop)
Last Step: break out of outer loop from within inner loop using BREAK_OUT_OF keyword
while(true) S_ID(first_loop)
{
switch(10) S_ID(1)
{
case 10: BREAK_OUT_OF(first_loop);
case 0: BREAK_OUT_OF(1);
}DEF_S_ID(1)
}DEF_S_ID(first_loop)
Upvotes: 0
Reputation: 65891
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.
Upvotes: 84
Reputation: 327
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.
Upvotes: 1
Reputation: 31191
The following code should be considered bad form, regardless of language or desired functionality:
while( true ) {
}
The while( true )
loop is poor form because it:
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.)The following code is better form:
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
No flag. No goto
. No exception. Easy to change. Easy to read. Easy to fix. Additionally the code:
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:
Readily insert the pause:
while( isValidState() ) {
execute();
sleep();
}
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
).
Contrast the following answer (to a Python question) that was posted on StackOverflow:
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
Versus:
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
Here, while True
results in misleading and overly complex code.
Upvotes: 55
Reputation: 96
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);
Upvotes: 5
Reputation: 356
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;
}
Upvotes: 1
Reputation: 11
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;
Upvotes: 1
Reputation: 96281
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**
}
}
Upvotes: 2
Reputation: 264591
You could potentially use goto, but I would prefer to set a flag that stops the loop. Then break out of the switch.
Upvotes: 2
Reputation: 527123
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.
Upvotes: 17
Reputation: 1
while(true)
{
switch(x)
{
case 1:
{
break;
}
break;
case 2:
//some code here
break;
default:
//some code here
}
}
Upvotes: -3
Reputation: 3168
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**
}
}
Upvotes: 0
Reputation: 30428
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!
Upvotes: 1
Reputation: 39218
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();
Upvotes: 0
Reputation: 1
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
Upvotes: 0
Reputation: 4842
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
Upvotes: -2
Reputation: 99635
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 ...
}
Upvotes: 8
Reputation: 6625
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.
Upvotes: 29
Reputation: 34365
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())
;
Upvotes: 12
Reputation: 170509
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
.
Upvotes: 5
Reputation: 422122
You can use goto
.
while ( ... ) {
switch( ... ) {
case ...:
goto exit_loop;
}
}
exit_loop: ;
Upvotes: 236