multiple label value in C switch case - c

Following is the excerpt from Dennis M Ritchie's book, ANSI C:
Each case is labeled by one or more integer-valued constants or constant expressions.
I could not come up with an example of a switch case where we have case with more than one label.
Any example illustrating the above property will be helpful.

Here's an example I found in a program which checks options:
switch (optionChar) {
case 'a': case 'A':
case 'f': case 'F':
case 'q': case 'Q':
case 'z': case 'Z': optionsOk = TRUE; break;
default: optionsOk = FALSE; break;
}
It's probably not how I would have written the code(a) but it's certainly valid. It's often used when the use of case results in shorter code than a long seties of || conjunctions for conditions that need substantially similar actions:
if (optionChar == 'a' || optionChar == 'A' || ...
And, in fact, K&R itself has an example, right after the quote you mention. It's in the code for counting different character classes:
while ((c = getchar()) != EOF) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
ndigit[c-'0']++;
break;
case ' ': case '\n': case '\t':
nwhite++;
break;
default:
nother++;
break;
}
}
(a) I probably would have done something along the lines of:
optionsOk = (strchr("aAfFqQzZX", optionChar) != NULL);

The gcc compiler has an extension for multiple values in a single case clause, such as:
case 1 ... 8:
However, it does not conform to the C standard.

The accepted answer is correct for C++ too. Stroustup's book Programming Principles says the same.
You can use several case labels for a single case. Often you want the same action for a set of values in a switch. It would be tedious to repeat the action so you can label a single
action by a set of case labels. For example:
He has given the following example:
int main() // you can label a statement with several case labels
{
cout << "Please enter a digit\n";
char a;
cin >> a;
switch (a) {
case '0': case '2': case '4': case '6': case '8':
cout << "is even\n";
break;
case '1': case '3': case '5': case '7': case '9':
cout << "is odd\n";
break;
default:
cout << "is not a digit\n";
break;
}
}

Related

Csh script call C program,arguments issue

This the line from the csh script
./model2grd $model -D$nx/$ny/$nz -O$x0/$y0 -I$dx/$dy -L$layer -C$coverage -Avel.dat -Gvel.grd
This is part of the model2grd.c
for (i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
case 'C':
cov = &argv[i][2];
lcov = TRUE;
break;
case 'A':
xyzfile = &argv[i][2];
lxyz = TRUE;
break;
case 'D':
sscanf(&argv[i][2],"%d/%d/%d",&nx,&ny,&nz);
break;
case 'I':
sscanf(&argv[i][2], "%lf/%lf", &dx, &dy);
break;
case 'O':
sscanf(&argv[i][2], "%lf/%lf", &xmin, &ymin);
break;
case 'L':
layer = atoi(&argv[i][2]);
break;
case 'N':
nan = (float)atof(&argv[i][2]);
break;
case 'Z':
cvalue = (float)atof(&argv[i][2]);
break;
case 'V':
verbose = TRUE;
break;
default:
break;
}
}
}
Does this mean that it takes with D(nx,ny,nz),with O(xmin and ymin),with L layer and with C coverage?Are Avel.dat and Gvel.grd input files or not?
Avel.dat and Gvel.grd are not input files. Look at the argument parsing again.
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
Consider that with this argument:
-Gvel.grd
In plain English, the switch examines the second character of each argument. In this case -Gvel.grd is the argument, so it looks at the G. Passing that test, the case statement then derives the address of the character that comes immediately after the G within the character string. In other words, the v.
Therefore, the file name is actually vel.grd. You should be able to apply this same logic to the rest of the arguments that follow the same pattern.

Switch statement not doing what I expect

What is wrong with this code:
switch (n)
{
case 0: strcpy(resultString, "Zero");
case 1: strcpy(resultString, "One");
case 2: strcpy(resultString, "Two");
case 3: strcpy(resultString, "Three");
case 4: strcpy(resultString, "Four");
case 5: strcpy(resultString, "Five");
case 6: strcpy(resultString, "Six");
case 7: strcpy(resultString, "Seven");
case 8: strcpy(resultString, "Eight");
case 9: strcpy(resultString, "Nine");
}
printf("%s", resultString);
It always prints "Nine" no matter the value of n. What am I doing wrong??
You need a break statement at the end of each case. Otherwise control falls straight through to the next case.
Change your code to:
switch (n)
{
case 0: strcpy(resultString, "Zero");
break;
case 1: strcpy(resultString, "One");
break;
case 2: strcpy(resultString, "Two");
break;
case 3: strcpy(resultString, "Three");
break;
case 4: strcpy(resultString, "Four");
break;
case 5: strcpy(resultString, "Five");
break;
case 6: strcpy(resultString, "Six");
break;
case 7: strcpy(resultString, "Seven");
break;
case 8: strcpy(resultString, "Eight");
break;
case 9: strcpy(resultString, "Nine");
break;
}
printf("%s", resultString);
You can find the switch statement documented here or in any book on the C language.
You need to break after each case.
case 0:
do soemthing;
break;
case 1:
do something;
break;
In many managed languages, it won't let "one case fall through to another," and throws an error. But C loves to let you do whatever you want!
You missed break; after each case
Example :
case 0: strcpy(resultString, "Zero");break;
..
..
case 8: .... ; break;
..
From the standard :
6.4.2 The switch statement [stmt.switch]
case and default labels in themselves do not alter the flow of control, which continues unimpeded across such labels. To exit from a switch, see break (6.6.1).
6.6.1 The break statement [stmt.break]
The break statement shall occur only in an iteration-statement or a switch statement and causes termination of the smallest enclosing iteration-statement or switch statement; control passes to the statement following the terminated statement, if any.
That means that is you don't use break after each case, you program will enter in the first case who matches the condition and will continue executing every line of the switch until the end.
You should just do something like :
switch( n )
{
case 0:
// ...
break; // <- Note the break
//...
default:
// ...
}

Choose of a lot of cases instead of c >= '0' && c <= '9' to 0-9 numbers checking

The following code is part of an intepreter that I'm reading. I'm trying to figure why exactly use this instead of simple c >= '0' && c <= '9'?
switch(ch) {
//...
case '0': case '1': case '2':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9':
//etc
break;
//more cases
}
I'm very curios too why choose use a switch for that. How it is a code of a interpreter,I believe that the author have a background C know. Is this fastest than c >= '0' && c <= '9' condition or is this some way to leave the compiler make some optmization? it's compiled by using gcc
You can not use a condition in a switch case. If you want to use c >= '0' && c <= '9', then you have to use an if statement, then it possibly makes checking other cases difficult, for example:
if (c >= '0' && c <= '9') {
// ...
} else if (c == 'a') {
// ...
} else if (c == 'b') {
// ...
} else if (c == 'c') {
// ...
} // more cases
will probably not be better than
switch(ch) {
//...
case '0': case '1': case '2':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9':
//etc
break;
case 'a': //...
case 'b': //...
case 'c': //...
//etc
}
Specifically for digits only, this is guaranteed to produce the same results as the equivalent if.
However, depending on the "more cases" part the code may be easier to read when written using switch. For example, if "more cases" wants to catch all lowercase letters it would be theoretically wrong to write the test like this:
if (c >= 'a' || c <= 'z')
so you would have to write it like this:
if (c == 'a' || c == 'b' || ...)
In this case, it's much easier to use switch than if/elseif.
maybe
if(isdigit(ch)){
//etc
} else {
//more cases
}
As #Zack mentioned, it depends a great deal on what the "more cases" are. Many compilers will generate an optimized combination of conditional instructions and jump tables when there are a lot of cases in the switch. It's not necessarily just a matter of readability.
If you use GCC or Clang you can also write:
switch(ch) {
//...
case '0' ... '9':
//stuff
break;
//more cases
}

Making a switch statement in C with an array?

I am trying to make a switch statement that takes in a word into an array and then throws each letter through a switch statement and allocates a point to each letter depending on which letter it is and giving a final point value for the word, and I can't seem to get the array part right. Any help would be appreciated!
int main(){
int letter_points = 0;
char word[7];
int word_length = 7;
int i;
printf("Enter a Word\n");
scanf("%s", word);
for(i = 0; i < word_length; i++){
switch(word){
//1 point
case 'A':
case 'E':
case 'I':
case 'L':
case 'N':
case 'O':
case 'R':
case 'S':
case 'T':
case 'U':
letter_points++;
break;
//2 points
case 'D':
case 'G':
letter_points += 2;
break;
//3 points
case 'B':
case 'C':
case 'M':
case 'P':
letter_points += 3;
break;
//4 points
case 'F':
case 'H':
case 'V':
case 'W':
case 'Y':
letter_points += 4;
break;
//5 points
case 'K':
letter_points += 5;
break;
//8 points
case 'J':
case 'X':
letter_points += 8;
break;
//10 points
case 'Q':
case 'Z':
letter_points += 10;
break;
}
}
printf("%d\n", letter_points);
return;
}
It would probably be faster to have a lookup array:
int const letter_score[26] = { 1, 2, 1, 3, ..., 10 };
/* key: A B C D Z */
score += letter_score[c - 'A']; // or "toupper(word[i]) - 'A'"
Caveat: this requires an encoding in which the upper-case letters are arranged contiguously, such as Unicode or ASCII.
Try using this
switch(word[i]){
in the switch statement. As it stands, you are not testing each element in your array even though you are iterating over the range of the array. Having said that I would go for the approach suggested by Kerrek SB in the other answer. This is much neater and more compact.
The variable word is an array, but you want to switch on each character. Thus, you need:
switch(word[i])
In C, you cannot use arrays in switch (and expressions for case). Also, the type passed to switch() and types specified in each case must match. So the most you can do is switch on a character. You almost got it right though, except that you are passing the whole array into switch. Use index to reference a character instead. For example:
switch (word[i]) {
...
}
You have word as an array of size7, you cannot switch on the array, you have to swicth on each character of the array so use:
switch(word[i])

Newbie: After adding cases to a switch in C, it breaks

switch(ch)
{
//input a number
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[g.y][g.x] = ch - '0';
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
// delete an input from the board
case '0':
case KEY_BACKSPACE:
case KEY_DC:
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[y][x] = 0;
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
}
Problem: Case '1' through case '9' worked fine. Then I added case '0', case KEY_BACKSPACE and case KEY_DC. Although it compiles, none of the cases now work, including cases '1' - '9'. What am I missing?
All of your cases are falling through. I assume that you should have a break; before case 0:.
You are missing a break;. In C, switch has fall-through semantics. Once a case is met, all subsequent cases are exceuted unless a break; stops execution.

Resources