Can you use an OR in a switch? - c++

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;
}

Related

C++ Switch Cases

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.

Why does C++ require breaks in switch statements? [duplicate]

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.

In a switch case statement, it says "duplicate case value" comes up as an error. Anyone know why?

I am working on a rock paper scissors program, but this time the computer chooses rock half the time, scissors a third of the time, and paper only one sixth of the time. The way I did this was I enumerated six possible computer choice values:
enum choicec {rock1, rock2, rock3, scissors1, scissors2, paper};
choicec computer;
But then, after the computer makes its choice, I have to convert these enumerated values to either rock, paper, or scissors. I did this using a switch-case statement:
switch(computer) {
case rock1 || rock2 || rock3:
c = 1;
break;
case scissors1 || scissors2: //ERROR!
c = 3;
break;
case paper:
c = 2;
break;
}
one is rock, two is paper, and three is scissors. However, on the line where I have error written in as a comment, it gives me this error: [Error] duplicate case value.
I'm not sure why.
Any ideas?
I am not sure what you doing, but switch statement should look like this
switch(computer)
{
case rock1:
case rock2:
case rock3:
c = 1;
break;
case scissors1:
case scissors2:
c = 3;
break;
case paper:
c = 2;
break;
}
You can't use || in case branches. Sorry :(
When you use || it does a logical or on them, that says "is rock1 or rock2 or rock3 not a zero?". And the answer is yes, at least one of those is not zero. So rock1 || rock2 || rock3 is true, which is 1. And scissors1 || scissors is also true, which is 1. So you have two case branches for the 1 case.
You should simply use case fallthrough to select multiple conditions:
switch(computer) {
case rock1: case rock2: case rock3:
c = 1;
break;
case scissors1: case scissors2:
c = 3;
break;
case paper:
c = 2;
break;
default:
std::cerr << "INVALID COMPUTER MOVE";
}
Also, I always have a default in my case switches. Sometimes mistakes happen, and we definitely want to know if it doesn't hit any of the case branches. I'm also pretty paranoid about missing else statements, but about half the time it's ok if there's no else.
That switch statement does not do what you think.
Each case defines one value that the value of computer is matched against. Combining several values with logical disjunction to give the value associated with a single case label does not make the corresponding block be entered when the value of computer is equal to any of those values, but rather when it is equal to the result of their logical OR combination. Not very meaningful, indeed.
This is how you could rewrite your switch statement in order to make more sense:
switch(computer) {
case rock1: // Is it rock1?
case rock2: // Or perhaps rock2?
case rock3: // Or maybe rock3?
c = 1; // Well, if it's one of the above, do this...
break;
case scissors1: // OK, it wasn't. So is it scissors1?
case scissors2: // Or scissors2?
c = 3; // If it's one of the above, do this...
break;
case paper: // So is it paper?
c = 2;
break;
default: // Always better to be explicit about this
break;
}
Change it to:
switch(computer) {
case rock1:
case rock2:
case rock3:
c = 1;
break;
case scissors1:
case scissors2:
c = 3;
break;
case paper:
c = 2;
break;
}
rock1 || rock2 || rock3 and scissors1 || scissors2 are both expressions which evaluate to "true", hence the conflict.
The expression used in the switch statement must be integral type ( int, char and enum). In the Switch statement, all the matching case execute until a break statement is reached and Two case labels cannot have the same value.
But in the above case with logical or condition.
At first
case: rock1 || rock2 || rock3:
This will evaluate to 1 and second case scissors1 || scissors2: will also evaluate to 1. This is cause error as said Two case labels cannot have the same value.
This is the reason compiler complains and giving an error:
Compiler Error: duplicate case value
To solve this convert to
switch(computer) {
case rock1:
case rock2:
case rock3:
c = 1;
break;
case scissors1:
case scissors2: //Now will not give any error here...
c = 3;
break;
case paper:
c = 2;
break;
}

Changing switch variable inside a case

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.

Is It Possible To Do The Following In A Switch Statement - C++?

I am a programming student in my second OOP class, and I have a simple question that I have not been able to find the answer to on the internet, if it's out there, I apologize.
My question is this:
Is it possible have Boolean conditions in switch statements?
Example:
switch(userInputtedInt)
{
case >= someNum && <= someOtherNum
break;
// Is this possible?
}
No this is not possible in C++. Switch statements only support integers and characters (they will be replaced by their ASCII values) for matches. If you need a complex boolean condition then you should use an if / else block
As others have said you can't implement this directly as you are trying to do because C++ syntax doesn't allow it. But you can do this:
switch( userInputtedInt )
{
// case 0-3 inclusve
case 0 :
case 1 :
case 2 :
case 3 :
// do something for cases 0, 1, 2 & 3
break;
case 4 :
case 5 :
// do something for cases 4 & 5
break;
}
No, this is usually the purview of the if statement:
if ((userInputtedInt >= someNum) && (userInputtedInt <= someOtherNum)) { ... }
Of course, you can incorporate that into a switch statement:
switch (x) {
case 1:
// handle 1
break;
default:
if ((x >= 2) && (x <= 20)) { ... }
}
It's not possible directly -- a C or C++ switch statement requires that each case is a constant, not a Boolean expression. If you have evenly distributed ranges, you can often get the same effect using integer division though. e.g. if you have inputs from 1 to 100, and want to work with 90-100 as one group, 80-89 as another group, and so on, you can divide your input by 10, and each result will represent a range.
Or you can perhaps do this
switch((userInputtedInt >= someNum) && (userInputtedInt <= someOtherNum))
{
case true:
//do something
break;
case false:
//something else
break;
}
But that's just down-right terrible programming that could be handled with if-else statements.
This isn't possible. The closest you can some, if the values are reasonably close together is
switch(userInputtedInt)
{
case someNum:
case someNum+1:
// ...
case someOtherNum:
break;
}
C++ does not support that.
However, if you are not concerned with writing portable, standard code some compilers support this extended syntax:
switch(userInputtedInt)
{
case someNum...someOtherNum:
break;
}
Those values must be constant.
If you fancy the preprocessor you could write some kind of macro that auto-expands to the number of case statement required. However that would require a lengthly file with pretty much all case statements (ex: #define CASE0 case 0: #define CASE1 case 1: ...)
You shouldn't go there but it's fun to do...for fun! ;)
The standard does not allow for this:
6.4.2 The switch statement [stmt.switch]
[...] Any statement within the switch statement can be labeled with one or more case labels as follows:
case constant-expression :
where the constant-expression shall be an integral constant expression (5.19).
Some C++ compilers still support range notations today, 8 years after this question was originally asked. It surprised me.
I learned Pascal in 2012, Pascal do have range notations.
So it encouraged me to try the similar syntax in C++, then it worked unexpectedly fabulously.
The compiler on my laptop is g++ (GCC) 6.4.0 (from Cygwin project) std=c++17
There is a working example, which I wrote in hurry. repl.it
In addition, the source code is attached as follow:
#include <iostream>
using namespace std;
#define ok(x) cout << "It works in range(" << x << ")" << endl
#define awry cout << "It does\'t work." << endl
int main() {
/*bool a, b, c, d, e, f, g;
switch(true) {
case (a): break; These does not work any more...
case (b and c): break;
}*/
char ch1 = 'b';
switch(ch1) {
case 'a' ... 'f': ok("a..f"); break;
case 'g' ... 'z': ok("g..z"); break;
default: awry;
}
int int1 = 10;
switch(int1) {
case 1 ... 10: ok("1..10"); break;
case 11 ... 20: ok("11..20"); break;
default: awry;
}
return 0;
}