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.
Related
I am creating a program for an online coding course which takes a poker hand and calculates the odds of the hand winning. I am currently in the early stages, writing the functions necessary to advance to the next part of the assignment. I have isolated my issues to one function, card_from_letters.
I created my-test-main.c to test card_from_letters. It creates two chars, representing the suit and value of a poker card. It then creates the struct testCard2.
A card_t struct has two components: an unsigned int for value, and an enumerated type for suit between SPADES and CLUBS. I cannot change the struct card_t.
int main(void) {
char sui = 'c';
char val = 'Q';
card_t testCard2 = card_from_letters(val, sui);
printf("last test! My card %c%c is value %d, and suit %d!\n", val, sui, testCard2.value, testCard2.suit);
}
This is my function card_from_letters:
card_t card_from_letters(char value_let, char suit_let) {
card_t temp;
assert(suit_let == 'd' ||'h' || 'c' || 's');
assert((value_let >= '2' && value_let <= '9') || (value_let = '0' || 'K' || 'Q' || 'J' || 'A'));
switch (value_let) {
case '2': temp.value = 2; break;
case '3': temp.value = 3; break;
case '4': temp.value = 4; break;
case '5': temp.value = 5; break;
case '6': temp.value = 6; break;
case '7': temp.value = 7; break;
case '8': temp.value = 8; break;
case '9': temp.value = 9; break;
case '0': temp.value = 10; break;
case 'K': temp.value = 13; break;
case 'Q': temp.value = 12; break;
case 'J': temp.value = 11; break;
case 'A': temp.value = 14; break;
}
switch (suit_let) {
case 's': temp.suit = SPADES; break;
case 'h': temp.suit = HEARTS; break;
case 'd': temp.suit = DIAMONDS; break;
case 'c': temp.suit = CLUBS; break;
}
return temp;
}
When val is set between '2' and '9', I am able to run card_from_letters with no problem. When I run my-test-main.c as it is here through gdb, the execution arrow makes it to switch (value_let), but then skips all cases and enters switch (suit_let), where it returns the correct suit. What am I missing here? How come card_from_letters works for chars 2 to 9, but not 0 to A?
I am starting to learn C and I am having problem with changing numbers from character array to integer array. Here is my Code and I got random number and I have no idea why I am having those numbers.
The answer is 0 , 45, 45, 45
and I used 15 for plus sign, 25 for minus, 35 for multiply and 45 for division just for testing.
And also the answer which I want is if char[]="+123"-> int[0]=15;int[1]=1;int[2]=2;int[3]=3;
Thanks in advance and very much appreciated!
#include <stdio.h>
int main(){
int i=0;
char retezec[]="123+";
int array_length=(sizeof(retezec) / sizeof(retezec[0])-1);
int new_array[50];
while(retezec[i++]!='\0'){
switch(retezec[i]){
case '0':
new_array[i]=0;
case '1':
new_array[i]=1;
case '2':
new_array[i]=2;
case '3':
new_array[i]=3;
case '4':
new_array[i]=4;
case '5':
new_array[i]=5;
case '6':
new_array[i]=6;
case '7':
new_array[i]=7;
case '8':
new_array[i]=8;
case '9':
new_array[i]=9;
case '+':
new_array[i]=15;
case '-':
new_array[i]=25;
case '*':
new_array[i]=35;
case '/':
new_array[i]=45;
}
}
for(int i=0;i<array_length;i++){
printf("%d\n",new_array[i]);
}
}
Adding with the previous answers the reason you are getting 45 every time is that you haven't given the break keyword in every condition of switch case. Just add it and you will get the desired output :)
For example:
case '0':
new_array[i]=0;
break;
See the link below to have a good understanding. Hope it will help you.
https://www.programiz.com/c-programming/c-switch-case-statement
In your code -
while(retezec[i++]!='\0'){
switch(retezec[i]){
....
i is 0 when while loop condition is first evaluated, but in switch i already becomes 1. So your switch block checks elements from index 1 and not 0. Same way new_array is populated from index 1. The new_array[0] then have garbage value (as you are not initializing new_array)
You can use a for loop which will loop until array_length instead of the while loop like -
for (i = 0; i < array_length; i++) {
switch(retezec[i]) {
....
}
}
Also the switch case looks like an overkill. May be replace it with if-else
This can be boiled down significantly knowing that the C standard define the binary representation of 0 to 9 to necessarily be continuous.
#include <stdlib.h> /* for calloc() */
#include <stdio.h> /* for fprintf() */
int main(void)
{
char retezec[] = "123+";
size_t array_length = sizeof retezec / sizeof *retezec; /* sizeof evaluates to size_t not int. */
int * new_array = calloc(array_length * sizeof *new_array); /* Only get as much as needed, and have set to all 0s. */
if (NULL == new_array)
{
perror("calloc() failed");
return EXIT_FAILURE;
}
for (size_t i = 0; retezec[i] != '\0'; ++i) /* Use a for-loop where a for-loop can be used. */
{
switch(retezec[i])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
new_array[i] = retezec[i] - '0';
break;
case '+':
new_array[i] = 15;
break;
case '-':
new_array[i] = 25;
break;
case '*':
new_array[i] = 35;
break;
case '/':
new_array[i] = 45;
break;
default:
sprintf(stderr, "Unhandled character: '%c'\n", retezec[i]);
break;
}
}
for(size_t i = 0; i < array_length; ++i)
{
printf("%d\n", new_array[i]);
}
free(new_array);
return EXIT_SUCCESS;
}
I'm doing an exercise from KNKings book "C Programming: A modern approach" which involves converting a phone number in alphabetic form, entered by the user, into numeric form. When the program encounters non-alphabetic characters (digits or punctuations, for example), it should leave them unchanged. I may assume that the user only enters upper-case letters.
However, my program seems to produce garbage, to say the least.
#include <stdio.h>
#define MAX_SIZE 50
int main(void)
{
char alphabetic[MAX_SIZE], ch;
int num_elements = 0;
printf("Enter phone number: ");
int i;
for (i = 0; i < MAX_SIZE && ((ch = getchar()) != '\n'); i++){
alphabetic[i] = ch;
num_elements++;
}
for (i = 0; i <= num_elements; i++){
switch (alphabetic[i]){
case 'A': case 'B': case 'C': alphabetic[i] = '2'; break;
case 'D': case 'E': case 'F': alphabetic[i] = '3'; break;
case 'G': case 'H': case 'I': alphabetic[i] = '4'; break;
case 'J': case 'K': case 'L': alphabetic[i] = '5'; break;
case 'M': case 'N': case 'O': alphabetic[i] = '6'; break;
case 'P': case 'R': case 'S': alphabetic[i] = '7'; break;
case 'T': case 'U': case 'V': alphabetic[i] = '8'; break;
case 'W': case 'X': case 'Y': alphabetic[i] = '9'; break;
default: break;
}
}
printf("%s\n", alphabetic);
return 0;
}
In particular, I enter: COLLECT-800.
It outputs something like this: u░#■ ║k ╩
What did I do wrong?
You have the right idea, but there are two things missing in your program:
Most importantly, the null terminator at the end of the string. After your for loop in which you read the number, add the line:
alphabetic[i] = '\0';
If the user enters lowercase letters, they are ignored in the switch statement. To get around this, include <ctype.h> and change the switch quantity from alphabetic[i] to toupper(alphabetic[i]). Calling toupper on an already upper case letter is benign.
You're not putting a null-terminator anywhere so it's undefined behavior when you read the string regardless of whether you modified it afterwards. Put this line:
alphabetic[num_elements] = 0;
After your for (i = 0; i < MAX_SIZE &&... loop.
Personally, I wouldn't do the getchar loop and instead read in the string like this:
scanf("%49s", alphabetic); // reads in a string up to 50 characters
for (i = 0; alphabetic[i]; i++) { ...
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;
}
}
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])