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

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.

Related

My program jump over to case condition although the condition don't was true [duplicate]

I have a switch in which I check a property of some sort and if the check yields a specific value, I want to check another value, so I did something like this:
switch(property_A)
{
case NA:
if(value_0 == property_B)
property_A = value_a;
else if(value_1 == property_B)
property_A = value_b;
case value_0:
...
break;
case value_1:
...
break;
}
So, I know this solves my problem, but I don't know if this is a good idea or maybe should I go about this another way
# the NA case is something like a default case but not exactly, because it does tell me something, but not enough
It depends on what you want to do. If you get to the case NA, without the break keyword, the value_0 case will be executed after one of the two if branches is finished. So if that's the behaviour you want, it's OK not to use break, but I don't think that's what you wanted to do.
I suggest you simply move the if - else statement above the switch and remove the NA case. This way, you will first assign the correct data to property_A and then you can do whatever you want with it in the switch.
EDIT: As Jack Deeth points out, if you omitted the break statement on purpose, it's a good idea to add a comment that you did so.
Convention is to add a comment explicitly telling future-you and any other maintainers you intended the fallthough and you haven't accidentally omitted the break;.
switch(foo) {
case 1:
bar();
// fallthrough
case 2:
baz();
break;
case 3:
fizzbuzz();
}
If you're using C++17 or later you can use the [[fallthrough]] attribute to avoid a compiler warning:
switch(foo) {
case 1:
bar();
[[fallthrough]]
case 2:
baz();
break;
case 3:
fizzbuzz();
}
The additional information provided in the comments to the question indicate that what's wanted is not what's written in the question:
switch(property_A)
{
case NA:
if(value_0 == property_B)
property_A = value_a;
else if(value_1 == property_B)
property_A = value_b;
// here, we fallthrough into the code for value_0
// but you want to switch on the new value instead
case value_0:
...
break;
}
What you say you actually want is to set property_A if it was initially NA, then jump to the correct label. In that case, you'll need the assignment to be outside of the switch statement. You could do this with a goto at the end of the NA case, but I recommend you just deal with the NA before the switch:
if (property_A==NA)
property_A = (value_0 == property_B) ? value_a
: (value_1 == property_B) ? value_b
: NA;
switch (property_A) {
case value_0:
...
break;
case NA:
// we get here only if none of the replacement conditions
// matched, outside the 'case'
}

switch-case automatic break

Are there any C compilers with extensions that provide the ability to automatically break at the end of each case statement (similar to what Swift has available) or an alterate switch available in a future C spec?
Mostly interested in this to avoid clutter in extensive switch-case scenarios.
I find this works "ok" but would prefer something clearer about the behavior.
#define case break; { } case
#define switch_break switch
switch_break (action)
{
default: printf ("Unknown action");
case action_none : // Nothing
case action_copy : doCopy ();
case action_paste : doPaste ();
case action_none : break; /* C requires a statement after final case */
}
If you hate writing break everytime, wrap the switch statement inside a function. Then break can be replaced with return statements. For example
int switch_func(char c) {
switch(c) {
case 'a': return 1;
case 'b': return 3;
case 'c': return 5;
case 'd': return 7;
. . .
default: return 0;
}
}
Reduces code only if return values are present.

optimizing switch case code

I have below switch case in my code.
switch(condition)
case 'A' :
//Code part A
break;
case 'B' :
//Code part A
//Code part B
break;
case 'C' : //Some code
break;
code Part A is repeated in both case 'A' and case 'B'. I want to avoid duplication of code.
If we use fall though then we need to add an if condition for case B. Is this the only way for avoiding repetition of code?
If the order is not important, you can simply do:
switch (condition)
{
case 'B':
// Code part B
// no break
case 'A':
// Code part A
break;
...
}
A case 'B' will continue to execute through the case 'A' code because you didn't call a break.
Manipulating a switch statement to reduce duplication of code may work at first, but then you may add additional cases to the switch later, which may break that cleanness of that optimization. For example:
switch(condition)
case 'A' :
// Code part A
break;
case 'B' :
// Code part A
// Code part B
break;
case 'C' :
// Code part C
break;
case 'D' :
// Code part A
// Code part D
break;
Suddenly an optimization which seemed nice at the time, starts to become difficult to maintain, difficult to read and error prone.
Having already determined that there is common code, the cleanest response in my view is to write functions to perform the common code and call from each case. Going forward, this will continue to be maintainable.
Unfortunately, that's the only way, short of defining a function for partA.
You can reduce nesting by exiting the switch from inside the combined case label to make the code look a little more uniform:
switch (someValue) {
case 'A':
case 'B':
// Code part A
if (someValue == 'A') break;
// Code part B
break;
case 'C':
break;
}
This lets your part A and part B code have the same level of nesting.
Can "//Code part B" be executed before "//Code part A"? If so, you could just reorder them and let it fall through without an if condition.
I don't think there's much else to do, otherwise. One of the reasons for the creation of object-oriented languages was avoiding the duplication of code you have in imperative languages.

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

My book says to make a program that tracks the amount of money a power user owes to the company using only switch statements

It had the same syntax error at all places marked with double forward slash, syntax error was "case label does not reduce to integer constant"
I can't use if statements because my book is dumb and hates if statements (but only in the switch statement chapter)
#include <stdio.h>
int main()
{
double price;
int power;
char user,hrs;
printf("Enter what kind of consumer (R for residential, C for commercial, I for industrial): ");
scanf("%c",user);
printf("Enter amount of kilowatt hours used: ");
scanf("%d",power);
switch(user)
{
case 'R':
case 'r':
price=6.00+.052*power;
break;
case 'C':
case 'c':
switch(power)
{
case (power>1000): //
price=60.00+(power-1000)*.045;
case power<=1000: //
price=60.00;
}
break;
case 'I':
case 'i':
{
printf("Hours (P for peak, O for off-peak):");
scanf("%c",hrs);
switch(hrs)
{
case 'P':
case 'p':
switch(power)
{
case power>1000: //
price=76.00+.065*(power-1000);
break;
case power<=1000: //
price=76.00;
break;
}
case 'O':
case 'o':
switch(power)
{
case power>1000: //
price=40.00+.028*(power-1000);
break;
case power<=1000: //
price=40.00;
break;
}
break;
default:
printf("Business hour ID not recognized; try again");
break;
}
}
break;
default:
printf("Consumer ID not recognized; try again");
break;
}
printf("Price is %f", price);
return(0);
}
The expressions in your case statements must be constants like 'p', not expressions like power>1000.
If you need to do expressions like power>1000, you should use if/else structures to handle all appropriate cases.
The value of a case statement must be a constant integer.
You are free to use chars (e.g. 'a', 'x', etc) because they will be converted to integers by the compiler (using their ASCII code).
Using any other type of constant will yield unexpected and probably unpleasant results.
Besides, the compiler will complain (and rightly so) if you use the same value in two different case statements. This can be trickier than it seems. For instance :
#define WHATEVER 1
switch (xxx)
{
case 1 : return 1;
case WHATEVER : return 10; // error: duplicate case value
}
Frankly I don't think your exercise is such a good illustration of the practical use of a case statement.
99% of the times, the case values will come from an enumerated type, like for instance:
typedef enum {
CMD_START,
CMD_STOP
} Command;
function process_command (Command c)
{
switch (c)
{
case CMD_START:
do_start();
break;
case CMD_STOP:
do_stop();
break;
default:
panic ("unknown command %d", c);
}
}
When you switch on power, the case targets must be constants.
Since you are actually only interested in the binary outcome of power>1000, you can apply the switch to that:
switch(power>1000)
{
case 1:
price=76.00+.065*(power-1000);
break;
default:
price=76.00;
break;
}
The exercise is meant for you to understand that using a switch this way is very close to if-else. However, only do this to satisfy an academic exercise. No one would actually want to maintain code written this way. It is more natural to use if-else:
if(power>1000)
{
price=76.00+.065*(power-1000);
}
else
{
price=76.00;
}

Resources