Strange switch's behaviour in c - c

I want the code below to print ok when user enters 1 or 3, or to print why otherwise.
Why, when user enters 3, the program prints why?
#include <stdio.h>
#include <conio.h>
int main(void){
int i;
clrscr();
scanf("%d", &i);
switch(i){
case (1||3):
printf("ok\n");
break;
default:
printf("why\n");
}
getch();
return 0;
}

case(1||3):
Will not work. If you want to say "1 or 3", write:
case 1 :
case 3 :
printf("ok");
break;
If you don't have break between cases, they flow from one into the next. Try it in the debugger.

Expression
1||3
has constant value 1. Operator || is the logical OR operator that according to the C Standard
3 The || operator shall yield 1 if either of its operands compare
unequal to 0; otherwise, it yields 0. The result has type int.
So if you enter 1 then code under the case label will be executed. Otherwise the code under the default label is executed.
In fact your switch statement looks like
switch(i)
{
case 1:
printf("ok");
break;
default:
printf("why");
}
Expression 1 || 3 will be calculated at compilation time and the compiler will generate code that will correspond to the label
case 1:
All case label expressions are evaluated at compilation time and instead of the expressions the compiler uses their results.
To achive the result you want you should either add one more case label or substitute the switch statement for a if-else statement. For example
switch(i)
{
case 1:
case 3:
printf("ok");
break;
default:
printf("why");
}
or
if( i == 1 || i == 3 )
{
printf("ok");
}
else
{
printf("why");
}

You want to learn the following paradigm for flow control:
switch(i)
{
case (1):
case (3):
printf("ok");
break;
default:
printf("why");
}
Where either 1 or 3 will fall through until the break.
1||3 => true... which is typically 0x1

Yet another solution:
printf( (i==1||i==3)?"ok":"why" );

Related

switch case isn't true than also its executing case which is inside the failed one

#include<stdio.h>
int main()
{
switch(2)
{
case 1:
if(1)
{
case 2:
printf("hello\n");
};
}
return 0;
}
OUTPUT = hello
as I'm passing 2 in switch
case 1 is not true then also it enters it and executes code inside case 2.
How come it enters case 1?
Thanks.
After switch(2), it will jump immediately to the case 2 label. The fact that it is within an if block contained within case 1 is irrelevant. case 2: effectively functions no differently from a goto label, so it will jump to it wherever it is. It is not true that case 1 is somehow being entered.
To clarify, properly indented it looks thus:
#include<stdio.h>
int main() {
switch(2) {
case 1:
if(1) {
case 2:
printf("hello\n");
}
;
}
return 0;
}
how come it enters case 1 ?
It doesn't enter the case 1. In fact if(1) has no use here. The above code is equivalent to
#include<stdio.h>
int main()
{
switch(2)
{
case 1:
case 2: printf("hello\n");
}
return 0;
}
To see the irrelevant use of if you can replace if(1) with if(0) and you will find that result will be the same.

switch case in c, default before case

I was trying this :
#include<stdio.h>
int main() {
int i = 2;
switch(i) {
default:{
printf("Hi\n");}
case 1:
printf("Hi1\n");
case 2:
printf("Hi2\n");
}
}
output is "Hi2" as expected, however if i = 3,
#include<stdio.h>
int main() {
int i = 3;
switch(i) {
default:{
printf("Hi\n");}
case 1:
printf("Hi1\n");
case 2:
printf("Hi2\n");
}
}
Output is
"Hi"
"Hi1"
"Hi2"
How does program enter other cases which do not match? I know putting break in default would solve this.
Why this behavior? Is there anything mentioned in C specification for this?
In C (and many other languages) the cases are simply labels that get 'jumped' to. Once execution starts in a selected case, it flows just like normal. If you want execution to 'stop' at the end of a case 'block' you have to use the break statement (or some other flow control statement):
switch(i) {
default:{
printf("Hi\n");}
break;
case 1:
printf("Hi1\n");
break;
case 2:
printf("Hi2\n");
break;
}
}
For whatever it's worth, in my opinion this is was an unfortunate decision made by the language designers since falling through to the next case after execution one or more statements in a case are executed is very, very rarely desired. However, that's the way the language works.
C# addresses this by making it so falling out of a case is illegal - some sort of explicit flow control (a break or a goto) is required at the end of a sequence of of statements in a case (unless it's the last case in the switch).
This is because the code steps through each instruction unless explicitly stated not to.
In a switch() { }, you must be explicit.
Think about the instructions backed by this C. It would be a jump table. Without break, there would be no jump beneath each branch to go after the switch case.
Complementing #alex, try this.
#include<stdio.h>
int main() {
int i = 2;
switch(i) {
default:{
printf("Hi\n");}
case 2:
printf("Hi2\n");
case 1:
printf("Hi1\n");
}
}

Skipping switch cases via false loop is a valid operation?

Would this be legal code or breaking any rules?
switch (expr)
{
do
{
case 6:
/*...*/
if (/*...*/)
break;
case 7:
/*...*/
} while (0);
case 9:
/*...*/
break;
default:
break;
}
Would this be a legal way of executing case 6 followed by case 7 but only if some conditions are met?
Or would this lead into undefined behavior and lets nasal dragons come out of the switch?
p.s. my Question is refering to c99.
EDIT:
What i want to do is the following:
assume, case 9, has to be executed in everycase. If expr is 6, i have to execute 6, under some conditions 7 and after that 9 or if expr is 7 its 7->9
so i just want to skip 7 if some conditions are met, but i cant change the order of 6,7,9.
EDIT2:
I'm not looking for an alternative soloution, I'm just interested in the behavior of this snippet.
If a switch statement has an associated case or default label within the scope of an
identifier with a variably modified type, the entire switch statement shall be within the
scope of that identifier.
from ISO/IEC 9899:TC3 6.8.4.2->3
Lets me feel unsure about its behavior.
But I'm not sure that would aim code like mine snippet too.
Whilst I believe the above code is valid, I would make it more explicit:
case 6:
...
/* fall through */
case 7:
if (expr != 6 || condition_to_run_7)
{
do whatever 7 does;
}
if (should_not_do_9)
case 9:
...
break;
}
Alternatively, which is the cleaner solution: move what the 6, 7 and 9 cases does into individual functions, and call the relevant functions (more than once, if needed) in the switch-statement, and have proper "break" after each case...
Maybe I'm one of those lousy programmers. I'm not sure about the standards, but I've been doing things like that when it's needed. That said, if I wanted to do what you have stated in your question, I'd do something like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int iCnt, iTmp;
for(iCnt = 1; argc > iCnt; iCnt ++)
{
iTmp = (int) strtol(argv[iCnt], NULL, 10);
switch(iTmp)
{
case 6:
printf("Case 6\n");
/* change this condition to whatever suits you */
if (argc - 1 == iCnt)
{
case 7:
printf("Case 7\n");
}
case 9:
printf("Case 9\n");
default:
printf("Default case\n");
}
printf("\n");
}
return 0;
}
i.e. an if statement is more intrinsic here IMO.
Valid yes; doing what you want? I doubt it.
Assuming the breaks you have put in are the only ones, then assuming the compiler doesn't get into a complete state (not implausible frankly, especially if you have optimisations turned up), then the following will happen
case 9:: runs its block and continues
default: runs its block and continues
case 7 : runs its block repeatedly forever
case 6 : run's its block, maybe 7, repeats forever
To do what you want, remove the do..while, and put the if block at the end of the 6 around the 7, possibly putting a guard to check whether you are in the 6 or 7 case.
switch (expr)
{
case 6:
/*...*/
break;
case 7:
if ( expr==7 || !/*...*/)
{
/*...*/
}
case 9:
/*...*/
break;
default:
break;
}
However, it's not how I'd do it. This is probably one where wrapping it into child functions would make sense:
void handle6() { /*...*/ }
void handle7() { /*...*/ }
void handle9() { /*...*/ }
switch (expr)
{
case 6:
handle6();
if( /*...*/ ) handle7();
handle9();
break;
case 7:
handle7();
case 9:
handle9();
break;
default:
/*...*/
}
is another way which is probably clearer.
and for completeness...
switch( expr )
{
case 6:
/*...*/
if( /*...*/ ) goto case_9;
case 7:
/*...*/
case 9:
case_9:
/*...*/
break;
default:
break;
}

is it possible to do an OR in a case statement?

I want to do something like:
case someenumvalue || someotherenumvalue:
// do some stuff
break;
Is this legal in C?
The variable that I am doing a switch on is an enumerated list data struct.
You can rely on the fact that case statements will fall-through without a break:
case SOME_ENUM_VALUE: // fall-through
case SOME_OTHER_ENUM_VALUE:
doSomeStuff();
break;
You can also use this in a more complicated case, where both values require shared work, but one (or more) of them additionally requires specific work:
case SOME_ENUM_VALUE:
doSpecificStuff();
// fall-through to shared code
case SOME_OTHER_ENUM_VALUE:
doStuffForBothValues();
break;
Yes, you can simply skip the break in the first case to achieve the fall-through effect:
switch (expr) {
case someenumvalue: // no "break" here means fall-through semantic
case someotherenumvalue:
// do some stuff
break;
default:
// do some other stuff
break;
}
Many programmers get into the trap of fall-through inadvertently by forgetting to insert the break. This caused me some headaches in the past, especially in situations when I did not have access to a debugger.
you need:
case someenumvalue:
case someotherenumvalue :
do some stuff
break;
You can use fallthrough to get that effect:
case someenumvalue:
case someotherenumvalue :
do some stuff
break;
A case statement like a goto -- your program will execute everything after it (including other case statements) until you get to the end of the switch block or a break.
As others have specificied, yes you can logically OR things together by using a fall through:
case someenumvalue: //case somenumvalue
case someotherenumvalue : //or case someothernumvalue
do some stuff
break;
But to directly answer your question, yes you can do a logical, or bit-wise or on them as well (it's just a case for the result of the operation), just be careful that you're getting what you'd expect:
enum
{
somenumvalue1 = 0,
somenumvalue2 = 1,
somenumvalue3 = 2
};
int main()
{
int val = somenumvalue2; //this is 1
switch(val) {
case somenumvalue1: //the case for 0
printf("1 %d\n", mval);
break;
case somenumvalue2 || somenumvalue3: //the case for (1||2) == (1), NOT the
printf("2 %d\n", mval); //case for "1" or "2"
break;
case somenumvalue3: //the case for 2
printf("3 %d\n", mval);
break;
}
return 0;
}
If you choose to do the second implementation keep in mind that since you're ||'ing things, you'll either get a 1 or 0, and that's it, as the case.

Debugging a switch statement in a C-based programming puzzle

I came across this puzzle here. I can't figure out why NONE is not printed. Any ideas?
#include<stdio.h>
int main()
{
int a=10;
switch(a)
{
case '1':
printf("ONE\n");
break;
case '2':
printf("TWO\n");
break;
defa1ut:
printf("NONE\n");
}
return 0;
}
defa1ut: is a syntactically valid label, e.g. for a goto but not the default of the switch statement.
If you compile with gcc with enough warnings it will point this out:
ajw#rapunzel:/tmp > gcc -Wall -Wextra test.c
test.c: In function ‘main’: test.c:13:15: warning: label ‘defa1ut’
defined but not used
It's a good argument for building with warnings cranked up high and aiming for 0 warnings in every build.
If defa1ut is a typo for default and the string "NONE" is printed:
This is because '1' and 1 is different.
'1' means the ASCII value of the character '1' whose value in decimal is 49. and 1 is an integer.
The first case will be true if the value of a is 49 or '1' , but as a=10 so it is neither equal to '1' nor equals to '2' and thus default is executed (if it existed, and defa1ut is not a typo).
If defa1ut is not a typo for default and simply nothing is printed:
In this case you have no default instead which look like it is defa1ut which will act as a normal label, so simply nothing will be printed.
default is spelled wrong. and so that case is never reached.
http://codepad.org/gQPA6p4s
#include<stdio.h>
int main()
{
int a=10;
switch(a)
{
case '1':
printf("ONE\n");
break;
case '2':
printf("TWO\n");
break;
defalut:
printf("NONE\n");
mickey_mouse:
printf("No Mickey\n");
default :
printf("CORRECT DEFAULT\n");
}
return 0;
}
Since defa1ut is not keyword, it should be addressed with a case statement.
Why do you think it should be printed?
defa1ut is different from default

Resources