I was doing a quiz online based on the C++ switch statement. I came across a question and I have a fair understanding of how switch statements work but this one question made absolutely no sense to me. Can someone please explain?
Why is the answer D and not C?
Is Case 2: the default case or what?
This quiz can be found at: http://www.cprogramming.com/tutorial/quiz/quiz5.html
Here's how this code behaves.
x is equal to zero
so cout<<"Zero"; is executed.
Since there's no break; after it,
the second case is executed: cout<<"Hello World";
And since cout<<"something"; doesn't add a newline after printing, they're printed as a single word.
since there is no break; statements in each case, the code will fall-through from case 0: to case 2:.
In C++ a case will "fall-through" if there is no break statement:
int temperature = 20;
switch(temperature)
{
case 20:
cout << "it's nice and warm";
case 25:
cout << "it's a bit hot";
break;
case 30:
cout << "It's way too hot!";
break;
}
This will print out:
it's nice and warm AND it's a bit hot because there is no break statement.
Since, x=0. It matches the 2nd case i.e. (case 0: cout << "Zero"; ). But there is no break statement to break out of the switch statement, it executes next cases too. If you have other cases its gonna execute and stop only when it find break statement or reaches the end of the switch case.
Related
Can you use an OR operator in a switch case? I was trying to remove case sensitivity from a user input check (so there may be a better way to do this altogether, I'm a beginner after all), and this of course resulted in doubling my switch case (not including the default case). Would it be better to use an if/else at this point, or is there a way to check for different conditions in a case?
My code, if it helps:
case 'Y':
case 'y':
cout << "Good, we will check later to ensure your opinion is unchanged." << endl;
break;
case 'N':
case 'n':
cout << "Open your window tonight, unlock the door, take sleep medication, and ignore any noises in your room." << endl;
break;
default:
cout << "Not an answer... think you can play games with me? I'll give you worse than the lemon haters, you'll be better off killing yourself before I take matters into my own hands." << endl;
If you do not plan to distinguish whether letters are lowercase or uppercase, then the best solution would be to "convert" your switch variable to lower/uppercase. By that you will get rid of unnecessary cases and save some time in future while implementing new ones.
Depending on your decision, you may choose std::tolower or std::toupper:
switch (std::tolower(x)) {
case 'y':
std::cout << "answer1" << std::endl;
break;
case 'n':
std::cout << "answer2" << std::endl;
break;
default:
std::cout << "answer3" << std::endl;
break;
}
Answering your question about usage of OR statement - it will not work well with char. All characters are defined with some integers (values from ASCII table), which means that e.g. y has the value 121, while Y has 89.
Let's take a look at expression case 'y' || 'Y': the value returned from 'y' || 'Y' would actually be 1. How is that possible? OR statement returns 1 if at least one of arguments is not 0 and 0 otherwise. This is how the value is calculated:
case 'y' || 'Y' => case 121 || 89 => case 1
Sadly, neither y nor Y is defined as 1 in ASCII, so switch will use default case with that input.
you can use it but it will not work, why? let me explain
when pass variable to switch() c++ will compare its value and type with each case, when you use "or" is a logical operator that means the result of the comparison will be a boolean value, check this example:
int main()
{
char input = 'R';
switch(input){
case 'R' || 'r' : // the 'or' opreator will return true wich is not equal to R
cout<<"wow!!!";
break;
default:
cout<<"meh";
}
return 0;
}
solution: you can use if/else statement
if(input=='Y' || input =='y'){
cout<<"Good, we will check later to ensure your opinion is unchanged." << endl;
}else if(input=='N' || input =='n'){
cout<<"Open your window tonight, unlock the door, take sleep medication, and ignore any noises in your room." << endl;
}else{
cout << "Not an answer... think you can play games with me? I'll give you worse than the lemon haters, you'll be better off killing yourself before I take matters into my own hands." << endl;
}
**or you can use tolower() to force the input to be lower case **
You can't use OR in a switch case, since it checks equality of the input and the case, so when using || evaluates to either true or false, which likely won't be equal to the input (for example, you check if a number, like 5, is equal to false). #Mohammed Khaled Gave a good explanation. What you can do is simply make an if/else chain (where you can use ||), or copy and paste the code from the switch cases.
int a = some_value;
switch(a) {
case 5:
do_something_1;
case 6:
do_something_1;
case 7:
do_something_2;
}
According to this book I am readingļ¼
Q What happens if I omit a break in a switch-case statement?
A The break statement enables program execution to exit the switch construct.
Without it, execution continues evaluating the following case statements.
Suppose if I have codes looking like
switch (option}{
case 1:
do A;
case 2:
do B;
default:
do C;
break;
}
Does this mean if I choose case 1, the A and C are done. If I choose case 2, B and C are done. If i choose neither, then only C is done.
if so, what happens if we omit the break after do C.
I assume these are bad programming practice, but I am curious what would happen to get a deeper understanding how it all works. Thanks
You execute everything starting from the selected case up until you see a break or the switch statement ends. So it might be that only C is executed, or B and then C, or A and B and C, but never A and C
If you don't include break in any of case then all the case below will be executed and until it sees break.
And if you don't include break in default then it will cause no effect as there are not any case below this 'Default' case.
And not using break generally considered as a bad practice but some time it may also come handy because of its fall-through nature.For example:
case optionA:
//optionA needs to do its own thing, and also B's thing.
//Fall-through to optionB afterwards.
//Its behaviour is a superset of B's.
case optionB:
// optionB needs to do its own thing
// Its behaviour is a subset of A's.
break;
case optionC:
// optionC is quite independent so it does its own thing.
break;
The break acts like a goto command. Or, as a better example, it is like when using return in a void function. Since it is at the end, it makes no difference whether it is there or not. Although, I do like to include it.
switch (option}{
case 1:
do A;
case 2:
do B;
case 2:
do C;
break;
default:
do C;
}
if your option is 1 it executes everything til it finds the break keyword...
that mean break end the excution of the switch --> case
Output :A then B then C
so it is recommended to put break after each case
like :
switch (option}{
case 1:
do A;
break;
case 2:
do B;
break;
do C;
break;
default:
do D;
}
if your option is 1 the Output will be : just A ...
note: default doesn't need a break;
I've seen in many comments and answers that it's a bad practice to omit break lines. I personally find it very useful in some cases.
Let's just take a very simple example. It's probably not the best one, just take it as an illustration:
- on bad login, you need to log the failed attempt.
- for the third bad attempt, you want to log and do some further stuff (alert admin, block account, ...).
Since the action is the same for first and second try, no need to break between these two and rewrite the same commands a second time.
Now the third time, you want to do other things AND also log. Just do the other things first, then let it run (no break) through the log action of the first and second attempts:
switch (badCount) {
case 3: //only for 3
alertAdmin();
blockAccount();
case 2: //for 2 AND 3
case 1: //for 1 AND 2 and 3
errorLog();
badCount++;
}
Imho, if it was soooo bad practice to have common code for different cases, the C structure would simply NOT allow it.
The key is execution control is transferred to the statement for the matching case.
E.g.
1. switch(x) {
2. case 1:
3. do_step1;
4. case 2:
5. do_step2;
6. default:
7. do_default;
8. }
Treat lines 2, 4, 6, as "Labels" for the goto calls. On x = 1, the control will be transferred to line 3 & execution of line 3, 5 & 7 will occur.
Try yourself - Run the code using ideone available here.
#include <stdio.h>
void doA(int *i){
printf("doA i = %d\n", *i);
*i = 3;
}
void doB(int *i){
printf("doB i = %d\n", *i);
*i = 4;
}
void doC(int *i){
printf("doC i = %d\n", *i);
*i = 5;
}
int main(void) {
int i = 1;
switch(i){
case 1:
doA(&i);
case 2:
doB(&i);
default:
doC(&i);
break;
}
return 0;
}
Output:
doA i = 1
doB i = 3
doC i = 4
Note:
It will execute all the options from the selected case until it sees a break or the switch statement ends. So it might be that only C is executed, or B and then C, or A and B and C, but never A and C
If you change the value of the variable analysed in switch inside the handle function (e.g doA), it does not affect the flow as describe above
Without break statements, each time a match occurs in the switch, the statements for that case and SUBSEQUENT CASES execute until a break statement or the end of the switch is encountered.
This question already has answers here:
Switch statement fall-through...should it be allowed? [closed]
(12 answers)
Closed 7 years ago.
When writing switch statements in C++, it seems necessary to include a break after every case. Otherwise, the code will continue to run into the next case.
For example:
int x = 1;
switch (x)
{
case 0:
std::cout << "x is 0." << std::endl;
case 1:
std::cout << "x is 1." << std::endl;
case 2:
std::cout << "x is 2." << std::endl;
default:
std::cout << "x is neither 0, 1 nor 2." << std::endl;
}
Will return:
>> x is 1.
>> x is 2.
However:
int x = 1;
switch (x)
{
case 0:
std::cout << "x is 0." << std::endl;
break;
case 1:
std::cout << "x is 1." << std::endl;
break;
case 2:
std::cout << "x is 2." << std::endl;
break;
default:
std::cout << "x is neither 0, 1 nor 2." << std::endl;
break;
}
Will return:
>> x is 1.
My question is: If it is necessary to include the break for every case, then why does C++ require it to be explicitly written at all? Why not just break the switch statement after every case by default in C++? Are there any examples when this behaviour may not in fact be desired?
This is for the favour of "falling throught" cases:
switch (x)
{
case 0:
case 1:
std::cout << "x is 0 or 1." << std::endl;
break;
}
In this example, the case statement is executed if x is either 0 or 1.
It is because the switch val will be translated to a jump in assembly to specific address where case (some value): is, then the CPU will continue executing code as normal, so fetch next address and go on, fetch next and go on, the case blocks are in consecutive addresses in memory so the execution will fall through.
break; will tell the CPU to jump again, this time beyond the switch-case block not executing any more casees.
The fall through might be beneficiary, and in some newer languages You must explicitly say You want it, in C and C++ the fall through is implicit.
example from my machine:
int i=1;
switch (i) {
case 1:
i=5;
break;
default:
i=6;
}
return 0;
will become
0x100000eeb: movl $0x1, -0x8(%rbp) ;int i=1;
0x100000ef2: xorl %eax, %eax
0x100000ef4: movb %al, %cl
0x100000ef6: testb %cl, %cl ;switch(i)
0x100000ef8: jne 0x100000f0f ;i is not 1 go to default:
0x100000efe: jmp 0x100000f03 ;i is 1 go to case 1:
0x100000f03: movl $0x5, -0x8(%rbp) ;case 1: i=5;
0x100000f0a: jmp 0x100000f16 ;break;
0x100000f0f: movl $0x6, -0x8(%rbp) ;default: i=6;
0x100000f16: movl $0x0, %eax ;first instruction after switch-case
if there were no jump after i=5; then the cpu would execute the default: as well.
Because the behaviour was inherited from C, which uses explicit break instead. Switch fallthrough was much more useful then and that's why it was chosen as the "default" behaviour.
There was just a lot more programmer time and a lot less machine time so designing for maximum potential efficiency instead of readability made a lot more sense. And compilers had a lot less power to optimize (in many respects). You can look at things like Duff's Device for examples of how this behaviour was used.
There might be a situation when you may require or want to get the same result for the two or may be more cases then you dont need a break. Something like this:
switch (x)
{
case 1:
case 2:
case 3:
some task
break;
deafult:
do some other task
break;
}
The above code is eventually the same as:
switch (x) {
case 0: // The case 1 code is shared here
case 1:
// code
goto case 2;
case 2:
//some code here
goto default;
default:
//some other code
break;
}
From the K&R
Falling through from one case to another is not robust, being prone to
disintegration when the program is modified. With the exception of
multiple labels for a single computation, fall-throughs should be used
sparingly, and commented.
As a matter of good form, put a break after the last case (the default
here) even though it's logically unnecessary. Some day when another
case gets added at the end, this bit of defensive programming will
save you.
As puppy has mentioned the bahaviour was inherent from the C language, so a quote from the book Expert C Programming
We analyzed the Sun C compiler sources
to see how often the default fall
through was used. The Sun ANSI C
compiler front end has 244 switch
statements, each of which has an
average of seven cases. Fall through
occurs in just 3% of all these cases.
In other words, the normal switch
behavior is wrong 97% of the time.
It's not just in a compiler - on the
contrary, where fall through was used
in this analysis it was often for
situations that occur more frequently
in a compiler than in other software,
for instance, when compiling operators
that can have either one or two
operands:
switch (operator->num_of_operands) {
case 2: process_operand( operator->operand_2);
/* FALLTHRU */
case 1: process_operand( operator->operand_1);
break;
}
Case fall through is so widely
recognized as a defect that there's
even a special comment convention,
shown above, that tells lint "this is
really one of those 3% of cases where
fall through was desired."
A very common example:
switch (month) {
case 2:
if(isLeapYear)
days = 29;
else
days = 28;
break;
case 4:
case 6:
case 9: // do the same thing
case 11:
days = 30;
break;
default:
days = 31;
}
From the above example - you get a much cleaner code, and also, you have more flexibility than you would have if the switch required to break out implicitly after every case.
First of all the output of the first program looks like
x is 1.
x is 2.
x is neither 0, 1 nor 2.
C++ allows to pass the control through all case labels that has no break statement. For example
char c;
std::cin >> c;
switch ( c )
{
case 'y':
case 'Y':
std::cout << "Y was pressed" << std::endl;
break;
case 'n':
case 'N':
std::cout << "N was pressed" << std::endl;
break;
default:
std::cout << "Neither Y nor N was pressed" << std::endl;
break;
}
Some other languages as for example C# do not allow to do this. Nevertheless they require a break statement in any case.:)
Yes, it is necessary to include a break or a return after every switch case.
An example where it is usefull, that not every case has an automatical break, is when you get key-events and certain keys should do the same thing:
switch (current_key)
{
case KEY_W:
case KEY_UP:
case KEY_SPACE:
player->jump();
break;
case KEY_S:
case KEY_DOWN:
case KEY_SHIFT:
player->cover();
break;
default:
//Do something
break;
}
and you may write a function for you code like this:
const char* make_x_to_string(int x)
{
switch (x)
{
case 0:
return "x is zero";
case 1:
return "x is one";
default:
return "x is neither zero or one";
}
}
and then simply call
cout << make_x_to_string(0) << endl;
You don't need break there, because return exits the function.
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.
In the following code:
int i = 0;
switch(i)
{
case 0:
cout << "In 0" << endl;
i = 1;
break;
case 1:
cout << "In 1" << endl;
break;
}
What will happen? Will it invoke undefined behavior?
No undefined behavior. But the value of i is only tested when the code reaches switch (i). So case 1: will be skipped (by the break; statement).
The switch keyword does not mean "run code whenever the value of i is 0 / 1". It means, check what i is RIGHT NOW and run code based on that. It doesn't care what happens to i in the future.
In fact, it's sometimes useful to do:
for( step = 0; !cancelled; ++step ) {
switch (step)
{
case 0:
//start processing;
break;
case 1:
// more processing;
break;
case 19:
// all done
return;
}
}
And changing the control variable inside a case block is extremely common when building a finite state machine (although not required, because you could set next_state inside the case, and do the assignment state = next_state afterward).
You break out of this switch statement after you set it to 1 which is defined behavior so it will never enter case 1.
There's no issue here. The expression in the switch condition is evaluated when it is reached. It doesn't have to be a variable and if it is the variable can be subsequently modified without any effect on the behaviour of the switch statement.
Your output would be :
"In 0"
even if you assign the value i = 1 it wont be reflected because switch does not operate in iteration, it is one time selection as break would make it go out of the switch statement.