converting an if statement to a switch statement - if-statement

How can I convert the following if=statement to a switch-statement WITHOUT needing to create a case for every number between that interval (41-49)? Is it possible?
if (num < 50 && num > 40)
{
printf("correct!");
}

You have to enumerate every case for a switch. The compiler converts this to a jump table, so you can't use ranges. You can, however, have multiple cases use the same block of code, which may be closer to what you want.
switch(num) {
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
printf("correct!");
break;
default:
break;
}

What about this?
switch ((num-41)/9) {
case 0:
printf("correct!");
break;
}

bool criteria1 = (num < 50 && num > 40);
switch criteria1: ...
It may result in multilevel decision networks.. scary?

In C or C++ (since you are using printf, I'll assume that's what it is), cases need to be enumerated for each choice.
The only difference between switch/case and if is the possibility that the compiler can turn it into a computed goto instead of checking ranges. If switch/case supported ranges, that would defeat the purpose of opening the possibility of this optimizaton.

Related

C++ nested switches duplicate value error

so this is the code that im trying to get to work but it displays "duplicate case value" whenever it reaches for B
im a first year college student so i might have used a wrong format or i might be overlooking something i really dont seem to figure out the problem so i turn to you guys for help
char dep;
int exp;
cout<<"please enter your department, A, B OR C: ";
cin>>dep;
cout<<"please enter your years of experience ";
cin>>exp;
switch(dep)
{
case 'A' || 'a' :{
switch (exp) {
case 5:
cout<<"you will recieve a 5% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 5% raise";
break;
}
}
break;
case 'B' || 'b' :{
switch (exp) {
case 5:
cout<<"you will recieve a 2% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 2% raise";
break;
}
}
break;
Though it compiles (or would without the B version), and spells what you wanted if roughly translated to English, case 'A' || 'a' does not do what you think it does.
The expression after case is treated as an exact match for the selection statement — it's compared exactly to dep. You can't throw in a more complex expression and expect it to be "unrolled" into multiple comparisons. Think of switch/case as a simple lookup table, rather than an intelligent branching feature (that's what if is for!).
Perhaps confusingly, the expression 'A' || 'a' is valid in its own right, but (like any expression) it evaluates to a single value: either true or false, depending on whether either of the operands if "truthy". In this particular example, neither has ASCII value zero so both is truthy, and the expression is always true. It'll be converted to the type of dep (the rules say it becomes 1) and used for that exact lookup.
Since you did this with 'B' and 'b' too, you do then indeed have two equivalent cases.
Instead, write a separate case for each condition. Fortunately, since cases fall through, you don't need to repeat the "body" of the case: you can just put the two cases next to each other; just don't put a break between them:
case 'A':
case 'a':
// code here
break;
case 'B':
case 'b':
// code here
By the way, you misspelt default.

Group multiple cases together in the switch statement

Here below is my code for a switch statement:
switch(pin)
{
case 1:
break;
case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11:
case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20:
case 21: case 22: case 23: case 24:case 25:case 26:case 27:case 28:case 29: case 30: case 31:
case 32: case 33: case 34: case 35:
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines(taskHandleOut,1,1,10.0,DAQmx_Val_GroupByChannel,dataOut,NULL,NULL);
break;
default:
break;
In the above, the case 2-35 are to be grouped together for which, I mean, when pin is equal to 2-35, the specific task is to be performed.
I want to know if the above code is valid or not. I haven't seen case grouping in switch statements. Any weblinks for similar multiple case grouping is appreciated. Maybe there is some better way to do so instead of grouping multiple cases.
While your case may be better served with an if-check if (pin >= 2 && pin <= 35), it is common to group case labels like that.
gcc/clang/tinycc even have syntactic sugar for it:
switch(pin){
case 2 ... 35: /*nonstandard GNU extension; note well the whitespace*/
};
Yes, this is absolutely fine, although I'd write
if (pin >= 2 && pin <= 35){
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines( ...
}
if I were you. If you are using gcc exclusively as your compiler, then you could also use case ranges.
It is valid. It's called fallthrough, and it's the reason you have to put breaks to separate cases. That is, if you don't break, the instructions following your case will get executed anyway. Like in
int i = 1;
switch(i) {
case 1:
cout<<1<<endl;
case 2:
cout<<"nope!\n";
}
This will output
1
nope!
because there's no break before case 2:.
But in your case you may as well do
if (pin >= 2 && pin <= 35) {
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines(taskHandleOut,1,1,10.0,DAQmx_Val_GroupByChannel,dataOut,NULL,NULL);
}
Yes, you can. C++ provides fall-through for switch case statements. So unless you provide a break; at the end of the case:, control falls-through to the next case allowing you to do exactly what you describe with a switch. Some compilers allow short-hand for describing multiple case statements at once, but for portable C++, simply providing each case without a break; is all you need, e.g.
switch(pin)
{
case 1:
break;
case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17:
case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25:
case 26: case 27: case 28: case 29: case 30: case 31: case 32: case 33:
case 34: case 35:
/* do what you need with pins 2 - 35 */
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines (taskHandleOut, 1, 1, 10. 0,
DAQmx_Val_GroupByChannel, dataOut, NULL, NULL);
break;
default:
break;
}
Now any case 2-35 will execute your desired statements:
dataOut[pin-2] = 1;
DAQmxWriteDigitalLines (taskHandleOut, 1, 1, 10. 0,
DAQmx_Val_GroupByChannel, dataOut, NULL, NULL);
It's valid code but I would rather use default in your case especially when you have planned to use other numbers for other cases. default will be used like else in an if/else statement. Here default would be called for every number you don't have an case specified.

C++ switch statement evaluation

Assume we have a following code:
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
If the first condition is met (currentChar == 'G') are the following cases also compared, or the program jumps straight to doSomething()?
What would be faster to execute: the switch-case, or an if with || operator?
Clarification:
I want doSomething to be executed if any of the conditions is met. I also know that the 'G' case will occur in some 99% of all cases. Can I assume that it will be compared as the first if I put it on top of the list?
If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?
It will immediately jump to execute doSomething()
What would be faster to execute: the switch-case, or an if with || operator?
I don't think it would make any difference with any decent modern c++ compiler, and the emitted code should be fairly the same.
What would be faster to execute: the switch-case, or an if with || operator?
Go for switch(). If you have an enum or integer with small value set, switch() will usually create a jump table.
Once currentCharis compared to 'G', instructions jump to instruction doSomething(). You cannot rely on order of your cases to "optimize" the switch.
Note that comparison is not necessary sequential.
switch may be implemented as jump table for example:
void foo_switch(char c)
{
switch (c) {
case '0': bar0(); break;
case '1': bar1(); break;
case '2': bar2(); break;
case '3': bar3(); break;
};
}
void foo_if(char c)
{
if (c == '0') {
bar0();
} else if (c == '1') {
bar1();
} else if (c == '2') {
bar2();
} else if (c == '3') {
bar3();
}
}
void foo_table(char c)
{
if ('0' <= c && c <= '3') {
using voidFPtr = void(*)();
voidFPtr funcs[] = {&bar0, &bar1, &bar2, &bar3};
funcs[c - '0']();
}
}
Questions about the performance outcome of a particular style of code are almost always a waste of time.
Here's how gcc5.3 deals with this code after an optimisation pass:
test(char):
cmpb $59, %dil
je .L3
jle .L6
cmpb $77, %dil
je .L3
cmpb $84, %dil
je .L3
cmpb $71, %dil
je .L3
.L1:
rep ret
.L6:
cmpb $10, %dil
je .L3
cmpb $13, %dil
jne .L1
.L3:
jmp doSomething()
I really don't think you could write anything faster without creating a 256-entry jump table, which would have its own consequences in terms of cache locality and exhaustion.
If the first condition is met (currentChar == 'G') are the following
cases also evaluated, or the program jumps straight to doSomething()?
It falls through until it finds a break or hits the end.
What would be faster to execute: the switch-case, or an if with || operator?
You should worry about code readability and supportability, so use whatever is more readable for you. Then if you have issue with program speed work on optimization.
For readability - of course that's subjective, but with switch you get less verbose code, as you do not have to repeat variable name multiple times:
if( currentChar == 'G' || currentChar == 'B' || currentChar == 'C' )
so I would prefer switch in this situation.
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
This makes doSomething() be called if currentChar is G, T, M, ;, \r or \n. It's faster to use a switch than just plain if, because switch statements are often optimized into jump tables. This is why a switch must operate on a constant integral value.
There is no guarantee for the order of checking in a switch case. There is also no guarantee for the order of execution of || if there are no side effects for the expressions.
Basically, if the only difference is timing, c++ guarantees nothing about the order of stuff, on the basis of the as-if rule.
If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?
In your example, it will straight away jump to doSomething(). In case you don't want to have this behavior, then you need to insert break statements as shown for one case below:
switch (currentChar) {
case 'G': /*things to be done */ break /* This break will take it out of switch*/;
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
Also, note that in your example, break is not needed, as it is the last statement of your switch statement. Please refer this link for a working example of switch statement.
What would be faster to execute: the switch-case, or an if with || operator?
Assuming that you are using a decent compiler, the difference is minimum so that it can be ignored. Please refer this So link, in case you need to know more specifics.
Edit for your clarification:
I want doSomething() to be executed if any of the conditions is met.
Yes, as per your code, doSomething() would be executed even if only one of the conditions is met.
I also know that the 'G' case will occur in some 99% of all cases. Can I assume that it will be compared as the first if I put it on top of the list?
The remaining cases won't be checked.

C++ - Variable Decrement

Heys.
I have this code, which sets a table for some mystery reason. Size is 6x60. Which means SIZEY defined as 6, and SIZEX as 60.
void set_table(char** table)
{
int i,j,k=0;
for(i=0;i<SIZEY;i+=3){
for(j=0;j<SIZEX;j++){
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
table[i][j]=' ';
break;
case 2:
table[i][j]=(char)((((k-2)/50)%10)+48);
break;
case 3:
table[i][j]=(char)((((k-3)/5)%10)+48);
break;
case 4:
table[i][j]=' ';
break;
default:
continue;
}
}
}
}
I am doing this with 3 variables, as you can see. Question is, can i do that with 2 variables, or even with only 1 ?
Thanks in advance.
Here's a simplification for you:
switch(k++%5){
case 0:
table[i][j]='|';
break;
case 1:
case 4:
table[i][j]=' ';
break;
case 2:
case 3:
table[i][j]= '0';
break;
default:
continue;
}
With C++, one case can fall into another, such as with cases 1 and 2 above.
Your expressions for case 2 and 3 can be simplified. I'll use case 2 as an example:
((((k-2)/50)%10)+48)
Substituting 2 for k yields
((((2-2)/50)%10)+48)
Simplify:
((((0)/50)%10)+48)
Zero divided by anything is zero, simplifying again:
(((0)%10)+48)
Zero mod anything is zero, since it involves division:
((0)+48)
Simplifying:
(48)
Replacing with the equivalent character (since your array is char):
'0'

Can I match a range instead of a single value in a C++ switch statement?

I am new into programming. Is it possible to use <, > in a switch case?
For instance,
...
...
...
int i;
cin>> i;
...
...
switch(i){
case 20<i<35
...
C++ does not offer a switch syntax for matching ranges.
When ranges are relatively small, you could supply case labels, and rely on fall-through:
switch(i) {
case 20:
case 21:
case 22:
case 23:
case 24:
case 25: doSomething();
break;
case 26:
case 27:
case 28:
case 29: doSomethingElse();
break;
...
}
For medium-size ranges (1000 elements or so) you could use a vector of function objects to dispatch to a particular logic, but that requires a lot more work than writing a simple switch statement.
For large ranges your best bet is a chain of if-else statements.