user1707643
user1707643

Reputation:

Case label does not reduce to an integer constant in 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?

Upvotes: 2

Views: 13643

Answers (4)

sehe
sehe

Reputation: 393613

  1. Your job array had inconsistent initializers (mixed char and const char *)

  2. 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;
    }
    
  3. 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;
}

Upvotes: 1

pb2q
pb2q

Reputation: 59637

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.

Upvotes: 7

tomahh
tomahh

Reputation: 13661

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..)

Upvotes: 1

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.

Upvotes: 1

Related Questions