When can I leave out "break" in switch loop? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I just solved 1st exercise on learncpp, chaper 7.8. I tested their version of switch loop and it works, but I wonder it's without break, shouldn't in this case such code cause undesired behavior? When can I leave out break?
Here is my version(which also works correctly):
switch (op)
{
case '+': {
return add;
break;}
case '-': {
return subtract;
break;}
case '*': {
return multiply;
break;}
case '/': {
return divide;
break;}
default: ;
}

Without break, the flow of execution will simply continue to the next case - unless you jump in some other way of course (like returning, in your case). This is known as fall-through.
Whether this is a bug or not depends on the program. It can be useful if (for example) you want multiple cases to have the same action:
switch (op)
{
case '+':
return add;
break; // these breaks do nothing - we have already returned!
case '-':
return subtract;
break;
case 'x': // fall through to '*'
case '*':
return multiply;
break;
case '/':
return divide;
break;
}

Note that C++ does not insist on your using break, but often switch cases depend on them, to obviate the useful follow through feature.
You can remove a break with no effect on your program if program control never reaches it: None of the break statements after the return statements are reachable, so you can safely remove them.
You also don't need an empty default label either.

Since you are new to C++, consider that:
Anytime your code reaches a return statement, your current function/method will end and return the specified valued without executing any more line of codes. So your break statements are never going to be reached.
When a break is reached, the current switch, while or for will end. And the flow will continue outside of its scope {...}.
If you do not use break in a switch case then the flow just continues (even to the next case).

It may be useful to you to understand what a switch is doing under the covers.
essentially this:
enum command {
add, subtract, multiply, divide, error
};
command foo(char op)
{
switch (op)
{
case '+': {
return add;
break;}
case '-': {
return subtract;
break;}
case '*': {
return multiply;
break;}
case '/': {
return divide;
break;}
default:
break;
}
return error;
}
Is logically the same as this:
command foo_that_will_give_people_seizures(char op)
{
if (op == '+') goto plus_;
if (op == '-') goto minus_;
if (op == '*') goto mpy_;
if (op == '/') goto div_;
goto break_;
plus_:
return add;
goto break_; // notice how this statement cannot be reached.
minus_:
return subtract;
mpy_:
return multiply;
div_:
return divide;
break_:
;
return error;
}
and the statement break; appearing in any of the cases in the first function is equivalent to goto break_ in the second.
ps. you won't win any friends writing code like this. People like to pretend that goto is a bad thing in c++ ;-)

You should be aware that break should be left out on default: (if the default is the last case) where the code flow basically reaches the end and doesn't need to get break.
The very purpose of break is to prevent code to continue to next case(s) when the actual case is true. return however, returns the given statement in the case and breaks the switch. If you are considering to return inside switch cases, then instead of using break, you may use return foobar; It will break by returning whatever you wish to return.

Related

Does the while(true) loop end if the operator is a '+' or '-'

double term()
{
double left = primary();
Token t = get_token();
while (true)
{
switch (t.kind)
{
case '*':
left *= primary();
t = get_token();
break;
case '/':
left /= primary();
t = get_token();
break;
case '%':
left %= primary();
t = get_token();
break;
default:
return left;
}
}
}
This is from Bjarne Strousup programming principles and practice using c++ book, page 201.
I want to ask will the while(true) loop inside term() be terminated if the operator is '+' or '-'?
if not, under what condition will the while(true) loop be terminated?
Yes, it will terminate the loop.
In the switch there are only cases for '*', '/', '%'. Hence, if you pass operator (t.kind) '+' or '-' or precisely any other character it will go to the default case. which return the current value of left(according to your program). Since the return statement ends the execution flow of the function, it will also terminate the loop.
The break statement is used in switch to end processing of a particular labeled statement (or case) within the switch statement. It branches to the end of the switch statement.
So you can't break out of the while loop using the break statements inside your switch-case block.
If you really want to break out of while loop from within your switch-case block you can use goto statements.
This is a good read VS switch-case

While loop in case statement (C++)

Is anyone can help me resolve I think trivial issue for someone who knows C langue quite well.
I have some piece of code however label_start_menu: doesn't work for me.
What I want to achieve is back to default: Now if e.g. 3 == 3 while loop is working infinite and is not possible to return to default:
switch (counter1) {
case 1:
menu_clock();
delay(2000);
while(true){
Serial.println("loop1");
Serial.println("loop1");
Serial.println("loop1");
if(3 == 3)
{
break;
goto label_start_menu;
}
}
break;
case 2:
menu_media();
delay(2000);
break;
default:
label_start_menu:
menu_start();
break;
}
}
Thanks,
ojdas
if(3 == 3)
{
break;
goto label_start_menu;
}
goto will never get executed because the break statement will break out of your loop right there.
My advice would be to get rid of the goto, and to just call menu_start() in the if statement, and then break, instead of using a goto.
I'm not sure what you're trying to do with your while loop, exactly, but you've got your break; statement in front of your goto label_start_menu; statement, so it will never be reached.
More complete answer: there's absolutely no need for the goto in the first place. You're already calling another function. Rewrite the whole thing like this:
switch (counter1)
{
case 1:
menu_clock();
delay(2000);
Serial.println("loop1");
Serial.println("loop1");
Serial.println("loop1");
menu_start();
break;
case 2:
menu_media();
delay(2000);
break;
default:
menu_start();
break;
}
the break should be the last thing..
also, why put it in a loop? that is an infinite loop.. just call it and then break breaking will get you out of the switch and will not continue so make sure you do everything before you break, so put your goto label_start_menu; before the break and remove the if statement and the other break under it.
if you want to loop it then there are other loop methods you can use.. google is great with that!
Im going to repost #40two's answer, because it exactly hits the nail about usage of goto (besides the other flaws coming in the same way (no reasonable loop break conditions)).
#40two: XKCD is a real good source for insight, as lomg you're able to read it!

Why is "defau4t" legal in a switch statement? [duplicate]

This question already has answers here:
Default case in a switch condition
(3 answers)
Closed 8 years ago.
I came up with this program in some other site and thought of trying it, here's the program:
#include <stdio.h>
int main()
{
int a=10;
switch(a)
{
case '1': printf("one");
break;
case '2': printf("two");
break;
defau4t: printf("none");
}
return 0;
}
Suprisingly enough, this compiles without errors or warnings. How is this possible? Isn't there an error on keyword "default"?
Could anyone explain this behaviour?
The token is not considered to be a keyword at all. This is a goto jump mark named "defau4t" pointing at otherwise dead code (after the break; of case '2':)...
Try this for laughs (and an endless loop):
switch(a)
{
case '1': printf("one");
break;
case '2': printf("two");
break;
defau4t: printf("none");
default: goto defau4t;
}
One flaw with the switch statement is that you can wildly jump in and out of them using goto. At any point inside the switch (or outside it for that matter), you can place a label, that you can jump to with goto. Of course, that is very bad practice as it leads to spaghetti code.
So defau4t: is merely a label, and labels can be placed pretty much anywhere inside function bodies.
Apart from that typo of default.
i think you need to also update
case '1': printf("one");
break;
case '2': printf("two");
break;
to
case 1: printf("one");
break;
case 2: printf("two");
break;

Switch Statement continue

Is the following possible in C++?
switch (value) {
case 0:
// code statements
break;
case 1:
case 2:
// code statements for case 1 and case 2
/**insert statement other than break here
that makes the switch statement continue
evaluating case statements rather than
exit the switch**/
case 2:
// code statements specific for case 2
break;
}
I want to know if there is a way to make the switch statement continue evaluating the rest of the cases even after it has hit a matching case. (such as a continue statement in other languages)
How about a simple if?
switch (value)
{
case 0:
// ...
break;
case 1:
case 2:
// common code
if (value == 2)
{
// code specific to "2"
}
break;
case 3:
// ...
}
Once the case label is decided, there is no way to have the switch continue to search for other matching labels. You can continue to process the code for the following label(s) but this doesn't distinguish between the different reasons why a case label was reached. So, no, there is no way to coninue the selection. In fact, duplicate case labels are prohibited in C++.
Yep, just don't put in a break. It will naturally fall down to the other switch statements.

Does case-switch work like this?

I came across a case-switch piece of code today and was a bit surprised to see how it worked. The code was:
switch (blah)
{
case a:
break;
case b:
break;
case c:
case d:
case e:
{
/* code here */
}
break;
default :
return;
}
To my surprise in the scenario where the variable was c, the path went inside the "code here" segment. I agree there is no break at the end of the c part of the case switch, but I would have imagined it to go through default instead. When you land at a case blah: line, doesn't it check if your current value matches the particular case and only then let you in the specific segment? Otherwise what's the point of having a case?
This is called case fall-through, and is a desirable behavior. It allows you to share code between cases.
An example of how to use case fall-through behavior:
switch(blah)
{
case a:
function1();
case b:
function2();
case c:
function3();
break;
default:
break;
}
If you enter the switch when blah == a, then you will execute function1(), function2(), and function3().
If you don't want to have this behavior, you can opt out of it by including break statements.
switch(blah)
{
case a:
function1();
break;
case b:
function2();
break;
case c:
function3();
break;
default:
break;
}
The way a switch statement works is that it will (more or less) execute a goto to jump to your case label, and keep running from that point. When the execution hits a break, it leaves the switch block.
That is the correct behavior, and it is referred to as "falling through". This lets you have multiple cases handled by the same code. In advanced situations, you may want to perform some code in one case, then fall through to another case.
Contrived example:
switch(command)
{
case CMD_SAVEAS:
{
this->PromptForFilename();
} // DO NOT BREAK, we still want to save
case CMD_SAVE:
{
this->Save();
} break;
case CMD_CLOSE:
{
this->Close();
} break;
default:
break;
}
This is called a fall-through.
It is exactly doing what you are seeing: several cases is going to execute same piece of code.
It is also convenient in doing extra processing for certain case, and some shared logic:
// psuedo code:
void stopServer() {
switch (serverStatus)
case STARTING:
{
extraCleanUpForStartingServer();
// fall-thru
}
case STARTED:
{
deallocateResources();
serverStatus = STOPPED;
break;
}
case STOPPING:
case STOPPED:
default:
// ignored
break;
}
This is a typical use of fall-through in switch-case. In case of STARTING and STARTED, we need to do deallocateResources and change the status to STOPPED, but STARTING need some extra cleanup. By the above way, you can clearly present the 'common logic' plus extra logic in STARTING.
STOPPED, STOPPING and default are similar, all of them fall thru to default logic (which is ignoring).
It is not always a good way to code like this but if it is well used it can present the logic better.
Luckily for us, C++ doesn't depend on your imagination :-)
Think of the switch labels as "goto" labels, and the switch(blah) simply "goes to" the corresponding label, and then the code just flows from there.
Actually the switch statement works the way you observed. It is designed so that you can combine several cases together until a break is encountered and it acts something like a sieve.
Here is a real-world example from one of my projects:
struct keystore_entry *new_keystore(p_rsd_t rsd, enum keystore_entry_type type, const void *value, size_t size) {
struct keystore_entry *e;
e = rsd_malloc(rsd, sizeof(struct keystore_entry));
if ( !e )
return NULL;
e->type = type;
switch (e->type) {
case KE_DOUBLE:
memcpy(&e->dblval, value, sizeof(double));
break;
case KE_INTEGER:
memcpy(&e->intval, value, sizeof(int));
break;
/* NOTICE HERE */
case KE_STRING:
if ( size == 0 ) {
/* calculate the size if it's zero */
size = strlen((const char *)value);
}
case KE_VOIDPTR:
e->ptr = rsd_malloc(rsd, size);
e->size = size;
memcpy(e->ptr, value, size);
break;
/* TO HERE */
default:
return NULL;
}
return e;
}
The code for KE_STRING and KE_VOIDPTR cases is identical except for the calculation of size in case of string.