Switch statement not doing what I expect - c

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:
// ...
}

Related

multiple label value in C switch case

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

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.

Adding "th", "nd" or "rd" to a date in C

I'm modifying some driver software for my keyboard and part of it is a plugin that outputs the date to my keyboard screen. At the moment it says 1 January but I really want it to say 1st, 2nd, 3rd or 4th or whatever.
I've been looking everywhere for some kind of code that will give me some kind of an idea on how to do it but I can only find examples for C# and I'm using C.
Edit:
const char *ordinals[] = {"", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th", "30th", "31st"};
sprintf(date, "%s %s", ordinals[t->tm_mday], mon);
Since you need this only for numbers 1 through 31, the easiest approach is to define an array of ordinals, like this:
const char *ordinals[] = {"", "1st", "2nd", "3rd", "4th"..., "31st"};
...
printf("%s of %s", ordinals[dayNumber], monthName);
This is better than doing it algorithmically, because it is more readable, and is easier to internationalize, should you run into this at some point later on.
This works for all nonnegative n:
char *suffix(int n)
{
switch (n % 100) {
case 11: case 12: case 13: return "th";
default: switch (n % 10) {
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
}
printf("%d%s\n", n, suffix(n));
void day_to_string(int day, char *buffer)
{
char *suff = "th";
switch(day)
{
case 1:
case 21:
case 31:
suff = "st";
break;
case 2:
case 22:
suff = "nd";
break;
case 3:
case 23:
suff = "rd";
break;
}
sprintf(buffer, "%d%s", day, suff);
}
Should do it. Note however that if you want to ever translate your program to another language, you may need to follow dasblinkenlight's suggestion, as you may find that the rules in some languages isn't the same as in English.
You can do it with a condition.
#include <stdio.h>
const char *suff;
switch (day)
{
case 1: /* fall-through */
case 21: /* fall-through */
case 31:
suff = "st";
break;
case 2: /* fall-through */
case 22:
suff = "nd";
break;
case 3: /* fall-through */
case 23:
suff = "rd";
break;
default:
suff = "th";
break;
}
printf("%d%s\n", day, suff);

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