Case label does not reduce to an integer constant in C? - c

I am working on a game and I ran my code and got the error "case label does not reduce to an integer constant." I think I know what this means, but how do I fix it? Here is my code:
#include<stdio.h>
#include<stdlib.h
int player_cash[3] = {50};
char job[][20] {
'A',
'B',
'C',
"Donate",
"Go to work",
"Exit"
};
int jobs;
int main()
{
while(player_cash[0] > 0) {
printf("Please type A, B, C, Donate, Go to work, or Exit\n");
switch(jobs) {
case 'A':
player_cash[0]-=5;
player_cash[1]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'B':
player_cash[0]-=5;
player_cash[2]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'C':
player_cash[0]-=5;
player_cash[3]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case "Donate":
player_cash[0]-=15; //Error here
player_cash[1]+=5;
player_cash[2]+=5;
player_cash[3]+=5;
printf("Cash donated\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case "Go to work":
player_cash[0]+=10; //Error here
printf("Work done\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case "Exit":
printf("Thanks for playing!\n\n"); //Error here
break;
default:
printf("Does not compute");
continue;
}
}
getchar();
return 0;
}
So, what I want the user to do is type in one of the options, and do the action that corresponds with it. How do I fix this?

You can't use strings as case expressions:
case "Donate":
Only integral expressions can be used, so e.g. case 'A': is OK.
Conceptually you have problems: jobs is an int, and you're testing for strings. If you want to allow the user to enter strings (more than a single character), you'll need to keep a string variable, and use something like fgets to get a full line of input.

Some of your case labels are characters (type char, indicated with 's). Those are integer constants.
Other labels are string literals (indicated with ") which have an effective type of const char *.1 Those are not integer constants and can not be used in this way.
1 For historical reasons they can often be used as if they were char *, but don't try to change them. Or else.

You cant compare string with c. "hello" == "hello" wont work as intend. switch only do simple c comparison on basic types.
switch(jobs) {
case 'A':
player_cash[0]-=5;
player_cash[1]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'B':
player_cash[0]-=5;
player_cash[2]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'C':
player_cash[0]-=5;
player_cash[3]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'D':
player_cash[0]-=15; //Error here
player_cash[1]+=5;
player_cash[2]+=5;
player_cash[3]+=5;
printf("Cash donated\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'G':
player_cash[0]+=10; //Error here
printf("Work done\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case 'E':
printf("Thanks for playing!\n\n"); //Error here
break;
default:
printf("Does not compute");
continue;
}
as you only read a character in getch(), you can compare this value. (but ask the user to input only one letter because he input "Donate", getch() will first read D, return, then read o, etc..)

Your job array had inconsistent initializers (mixed char and const char *)
You can't use string literals as case labels, as the char pointers are not compile time constants. Use integers:
enum jobType
{
jobA,
jobB,
jobC,
jobDonate,
jobGoToWork,
jobExit,
/* marker */
jobInvalid
};
enum jobType typeOfJob(const char* const name)
{
int i;
for (i=jobA; i!=jobInvalid; ++i)
if (0 == strcmp(jobNames[i], name))
return i;
return i;
}
Also, the player_cash was 1 element short (and was written out of bounds at index [3])
Code sample also shows how to avoid general gets badness, do some basic line-end trimming and do case insenstive comparison (stricmp on windows, IIRC): http://liveworkspace.org/code/227015a4e51126d55ca4eb1eea739b02
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int player_cash[4] = {50};
enum jobType
{
jobA,
jobB,
jobC,
jobDonate,
jobGoToWork,
jobExit,
/* marker */
jobInvalid
};
const char jobNames[][20] =
{
"A",
"B",
"C",
"Donate",
"Go to work",
"Exit"
};
enum jobType typeOfJob(const char* const name)
{
int i;
for (i=jobA; i!=jobInvalid; ++i)
#ifdef CASE_SENSITIVE
if (0 == strcmp(jobNames[i], name))
#else
if (0 == strcasecmp(jobNames[i], name))
#endif
return i;
return i;
}
const char* safer_gets()
{
static char input[1024];
char *p;
const char* t;
const char trimAt[] = "\r\n\t ";
fgets(input, sizeof(input), stdin);
for (t=trimAt; *t; ++t)
while(p = strrchr(input, *t))
*p = 0;
return input;
}
int main()
{
const char* input;
while(player_cash[0] > 0)
{
printf("Please type A, B, C, Donate, Go to work, or Exit\n");
input = safer_gets();
switch(typeOfJob(input))
{
case jobA:
player_cash[0]-=5;
player_cash[1]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case jobB:
player_cash[0]-=5;
player_cash[2]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case jobC:
player_cash[0]-=5;
player_cash[3]+=5;
printf("Cash=%i\n\n", player_cash[0]);
continue;
case jobDonate:
player_cash[0]-=15;
player_cash[1]+=5;
player_cash[2]+=5;
player_cash[3]+=5;
printf("Cash donated\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case jobGoToWork:
player_cash[0]+=10;
printf("Work done\n\n");
printf("Cash=%i\n\n", player_cash[0]);
continue;
case jobExit:
printf("Thanks for playing!\n\n");
break;
default:
printf("Does not compute");
continue;
}
}
getchar();
return 0;
}

Related

Why does this switch/case statement only execute the default case?

When the user inputs Yes,Only Maths,Only Science, the compiler executes Default.
I've tried with the same code but with Char replaced with Int it works as intended.. but with char it dosen't..
#include<stdio.h>
int main(){
char a;
printf("Have you passed in both maths and science?[Yes,Only Maths,Only Science]");
scanf(" %c", &a);
switch (a){
case 'Yes':
printf("That's amezing!");
break;
case 'Only Maths':
printf("That's good!");
break;
case 'Only Science':
printf("That's good!");
break;
case 'none':
printf("oof work harder next time!, i hope you will rock on that exam!");
break;
default:
printf("bozo do the typing right!");
break;
}
return 0;
}
A char by itself cannot store a string like "Yes". It will only store the first 'Y' and leave the rest. This is why none of the switch cases will match. Consider using string or char array to store an array of chars which can be compared. However, then the problem becomes that you cannot use switch with strings in C so you must use if, else.
#include <stdio.h>
int main(){
char a[15]; //15 should be a reasonable size
printf("Have you passed in both maths and science?[Yes,Only Maths,Only Science]");
fgets(a, 15, stdin);
if (strcmp(a, "Yes") == 0) printf("That's amezing!");
else if (strcmp(a, "Only Maths") == 0) printf("That's good!");
else if (strcmp(a, "Only Science") == 0) printf("That's good!");
else if (strcmp(a, "none") == 0) printf("oof work harder next time!, i hope you will rock on that exam!");
else printf("bozo do the typing right!");
return 0;
}
It is also recommended to use fgets instead of scanf to read strings.

Trouble getting a switch function to loop properly

I'm writing a program to 'encrypt' an inputted string of text by using a switch statement to correlate the given character with a symbol, and output that symbol in the place of the character. I put it in a while loop, the idea being that it would loop the full switch function each time until the received character is EOF. On a guess, I believe it is looping through just the first character, because I don't advance the getchar() statement, but I'm not sure how to do that so any help would be greatly appreciated. I say this because if I use return instead of break, it closes the while loop and only takes that first letter, if I use a break then it spams the first 'encrypted' char.
#include <stdlib.h>
#include <stdio.h>
/* C program to encrypt a given text message, assuming all lowercase */
int main() {
int Input, Encrypted;
printf("Please type your message\n");
Input = getchar();
while (Input != EOF) {
switch (Input) {
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'");break;
return 0;
}
}
return 0;
}
The simplest solution would be to remove the line
Input = getchar();
and to replace the line
while (Input != EOF) {
with:
while ( (Input=getchar()) != EOF && Input != '\n' ) {
Alternatively, if you find this while condition too confusing, you could also use an infinite loop, instead, like this:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
switch ( c )
{
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'"); break;
}
}
return 0;
}
Note that most character sets (such as ASCII) store the characters a to z consecutively. With these character sets, you don't need the long switch statement. Instead, you can simplify it to the following:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
const char map[] = "!##$%^&*`~-_=+[{]};:|,<.>'";
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
if ( 'a' <= c && c <= 'z' )
putchar( map[c-'a'] );
}
return 0;
}

kbhit and multiple calls on function

While making a asteroid shooter, I came around using _kbhit() and kbhit(). I'm no expert, but here is the problem I think I'm having:
int run = 1;
int main() {
while(run){
if(GetUserInput() == 2)
printf("W");
if(GetUserInput() == 1)
printf("S");
Sleep(50);
}
}
int GetUserInput(){
if(kbhit()){
char c = _getch();
if(c == 's')
return 2;
if(c == 'w')
return 1;
}
else
return 0;*
}
So, what I think is happening, it does the first check on GetUserInput(), and because of the nature of getch(), the keyboard is read from the buffer and discarded? Anyways, I store the value in c and should return appropriately. But it only does the first check. Is it because there is no more input on the buffer after the first check (in the main() function)?
Your problem is that you're trying to read once for every key you're interested in with this code:
if(GetUserInput() == 2)
printf("W");
if(GetUserInput() == 1)
printf("S");
For example, I press 'S', you read the key, check if the return value is 2 and it is not. Then you try to read another key, but I haven't pressed one, so the second check for 'S' also fails.
To fix this you need to perform all of your tests on the value you get from GetUserInput().
int val = GetUserInput();
if(val == 2)
printf("W");
else if(val == 1)
printf("S");
You don't need to use else if, but once you've found a match it makes no sense to keep checking if all of your checks are mutually exclusive. You might consider using a switch statement and an enum instead of hardcoded magic values, or even return the key value directly if one is pressed and a sentinel value like 0 that won't match any of the keys you're interested in.
Here is a complete example that works for me:
#include <conio.h>
#include <stdio.h>
int GetUserInput()
{
if (_kbhit())
{
char c = _getch();
switch (c)
{
case 's':
case 'S':
return 2;
case 'w':
case 'W':
return 1;
case 'x':
case 'X':
return -1;
}
}
return 0;
}
int main()
{
for (;;)
{
int c = GetUserInput();
switch (c)
{
case 1:
printf("W");
break;
case 2:
printf("S");
break;
case -1:
return 0;
}
}
return 0;
}

How to store and return a string in C

My code (below) takes a text file with hexadecimal values and converts the hexadecimal value to binary and prints it. How can I modify this so that my hex_to_binary function can initialise a string array and add the converted binary to the array and then return the array. Then I just want to print the output of the hex_to_binary function by adding a printf statement in my main function. Thanks in advance
#include <stdio.h>
int hex_to_binary(char*);
int main(int argc, char *argv[])
{
FILE *file;
file = fopen(argv[1],"r");
char line[100];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line);
}
fclose(file);
getchar();
return 0;
}
int hex_to_binary(char* hex_string)
{
int i=0;
printf("\nEquivalent binary value: ");
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': printf("0000"); break;
case '1': printf("0001"); break;
case '2': printf("0010"); break;
case '3': printf("0011"); break;
case '4': printf("0100"); break;
case '5': printf("0101"); break;
case '6': printf("0110"); break;
case '7': printf("0111"); break;
case '8': printf("1000"); break;
case '9': printf("1001"); break;
case 'A': printf("1010"); break;
case 'B': printf("1011"); break;
case 'C': printf("1100"); break;
case 'D': printf("1101"); break;
case 'E': printf("1110"); break;
case 'F': printf("1111"); break;
case 'a': printf("1010"); break;
case 'b': printf("1011"); break;
case 'c': printf("1100"); break;
case 'd': printf("1101"); break;
case 'e': printf("1110"); break;
case 'f': printf("1111"); break;
}
i++;
}
return 0;
}
There are several ways to do this.
The one thing you can't do is declare a character array in the function, use sprintf to print to it, and return it. You cannot be certain that the space it points to exists anymore after the function returns.
That is, DON'T do this:
int hex_to_binary(char *hex_string)
{
char binary_string[MAX_SIZE + 1];
<...>
return binary_string;
}
To do exactly what you state, you can call malloc to obtain the space inside the function, then return a pointer to it:
int hex_to_binary(char *hex_string)
{
char *binary_string;
if((binary_string = malloc(MAX_SIZE + 1)) == NULL)
return -1; /* Indicate failure */
binary_string[0] = '\0';
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return binary_string;
}
This is permitted, because malloc is allocating the memory, probably in the heap, and this memory will still exist afterwards. The issue is, the function that calls hex_to_binary needs to call free() to release this memory, otherwise every call steals a little bit of memory -- this is known as a memory leak.
That is, do:
char *binary_line;
while(!feof(file)){
fgets(line,100,file);
binary_line = hex_to_binary(line);
printf("%s", binary_line);
free(binary_line);
}
NOT
while(!feof(file)){
fgets(line,100,file);
printf("%s", hex_to_binary(line););
}
If you were to call the hex_to_binary in a loop, once per hex digit, you could change the case statements to return a pointer to a string, instead of printing:
switch(hex_digit)
{
case '0' : return "0000";
case '2' : return "0001";
<etc>
This returns a pointer to constant string that you could print and saves freeing the space afterwards.
Another option would be to pass hex_to_binary two parameters, one with the string to convert, and one a pointer to the space to write it to:
int hex_to_binary(char *hex_string, char *binary_line)
{
<etc>
switch(hex_string[i])
{
case '0' : strcat(binary_string, "0000"); break;
<etc>
return 0;
}
Call it like this:
char binary_line[MAX_SPACE + 1];
while(!feof(file)){
fgets(line,100,file);
hex_to_binary(line, binary_line);
printf("%s", binary_line);
}
strcat() function is what you want.
if I were you, for simplicity I do this one below :
Define Global Char array :
char buffer[1000]; // define a space to write our string
....
Change your hex function like this :
while(hex_string[i])
{
switch(hex_string[i])
{
case '0': strcat(buffer,"0000"); break;
case '1': strcat(buffer,"0001"); break;
case '2': strcat(buffer,"0010"); break;
....
}
}
In main use this to print your string :
printf("%s\n",buffer);
Note: Don't forget to clear buffer after your each hex_to_binary function call (otherwise it keeps the previous numbers inside)
change to like this :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char *hexstr_to_binstr(char *outbuff, const char *s);
int main(int argc, char *argv[]){
FILE *file = fopen(argv[1],"r");
char line[100];
char binstr[4*sizeof(line)];
while(fgets(line, sizeof(line), file)){
puts(hexstr_to_binstr(binstr, line));
}
fclose(file);
getchar();
return 0;
}
const char *xdigit_to_binstr(char x){
switch(x){
case '0': return("0000");
case '1': return("0001");
case '2': return("0010");
case '3': return("0011");
case '4': return("0100");
case '5': return("0101");
case '6': return("0110");
case '7': return("0111");
case '8': return("1000");
case '9': return("1001");
case 'a':
case 'A': return("1010");
case 'b':
case 'B': return("1011");
case 'c':
case 'C': return("1100");
case 'd':
case 'D': return("1101");
case 'e':
case 'E': return("1110");
case 'f':
case 'F': return("1111");
default : return "";
}
return NULL;//never reach this point
}
char *hexstr_to_binstr(char *outbuff, const char *s){
char *p = outbuff;
for(; *s ; ++s){
if(isxdigit(*s)){
memcpy(p, xdigit_to_binstr(*s), 4);
p += 4;
}
}
*p = 0;
return outbuff;
}

I am trying to reverse the string so it can read letter y as vowel in it

I am reversing the string so for example if I input word 'try' it would read y as a vowel and print out the word is legal.
The reverse function works but it doesn't pass to the switch statement value.
#include
//#include
void rev(char *);
void legal(char string);
int main()
{
char string[50];
char temp;
printf("Enter any string:");
scanf(" %s",&string);
//printf("Before reversing the string %s\t",string);
rev(string);
printf("\nReverse String is %s",string);
temp = legal(string);
printf("\nReverse String is %s",temp);
return 0;
}
void legal(char string)
{
switch(string)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'Y':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'y':
printf("\nWord is legal");
break;
default:
printf("\nWord is not legal");
break;
}
return 0;
}
//reversing string using pointers
void rev(char *str)
{
char *str1,temp;
str1=str;
while(*str1!='\0')
str1++;
str1--;
while(str<str1)
{
temp=*str;
*str=*str1;
*str1=temp;
str++;
str1--;
}
}
I see you have mistaken a char * with a char.
Instead, you must loop through the string, character by character and figure out with a flag if the word is legal or not..
here is how I would do it, not tested code ahead:
void rev(char *);
void legal(char *string);
int main()
{
char string[50];
int temp;
printf("Enter any string:");
scanf(" %s",&string);
//printf("Before reversing the string %s\t",string);
rev(string);
printf("\nReverse String is %s",string);
temp = legal(string);
printf("\nLegal? %d",temp);
return 0;
}
int legal(char *string)
{
char *ch = string;
int flag = 0;
while(*ch != '\0'){
switch(*ch)
{
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
case 'Y':
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'y':
flag = 1;
break;
default:
//nothing
break;
}
}
if(flag == 1){
printf("word is legal!");
}else{
printf("word is illegal!");
}
return flag;
}
C++ doesn't allow string or arrays in switch instructions, that might be the problem.
Plus you're assigning tempt to 0.
There are several errors in your code.
void legal(char string); returns a void, but you attempt to assign it here:
temp = legal(string);
legal takes a char, but you try to pass a char [] to it.
You return 0; in legal.
The problem is that the variable string is an array, while legal only accepts single char values. You can fix this by accepting a pointer or an array or some combination there-of and only checking the first digit if that is what you want.
Your corrected code would look like this:
void legal(char *string);
and then inside the legal function, you can reference the first character as *string.

Resources