Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use arrays in switch statement case (C)?

I'm doing a CS50 problem set where I have to make a game of scrabble basically two people write a word and each letter in the word gives certain amount of points. E.g. A gives one point and Z gives 10 I was trying to make the storing system using a switch statement and a couple of char arrays containing each letter and how many points it gives. E.g. array One stores letters that give one point and Two two points and so on but I figured out I can't put arrays in x position the (case x:) so i tried a few things and got this. Is there a way to make this more efficient or should I go back to switch statements or what?

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    //get the strings from the players and store them in a string data type
    string p1 = get_string("Player 1: ");
    string p2 = get_string("Player 2: ");
    //make score data types for each player
    int score1 = 0;
    int score2 = 0;
    char one[20] = {'a','A','e','E','i','I','l','L','n','N','o','O','r','R','s','S','t','T','u','U'};
    char two[4] = {'d','D','g','G'};
    char three[8] = {'b','B','c','C','m','M','p','P'};
    char four[10] = {'f','F','h','H','v','V','w','W','y','Y'};
    char five[2] = {'k','K'};
    char eight[4] = {'j','J','x','X'};
    char ten[4] = {'q','Q','z','Z'};
    int str = strlen(p1);
    for (int N = 0; N < str; N++)
    {
        if (p1[N] == one[0] || p1[N] == one[1] || p1[N] == one[2] || p1[N] == one[3] || p1[N] == one[4] || p1[N] == one[5] || p1[N] == one[6] || p1[N] == one[7] || p1[N] == one[8] || p1[N] == one[9] || p1[N] == one[10] || p1[N] == one[11] || p1[N] == one[12] || p1[N] == one[13] || p1[N] == one[14] || p1[N] == one[15] || p1[N] == one[16] || p1[N] == one[17] || p1[N] == one[18] || p1[N] == one[19])
        {
            score1++;
        } else if (p1[N] == two[0] || p1[N] == two[1] || p1[N] == two[2] || p1[N] == two[3])
        {
            score1 += 2;
        } else if (p1[N] == three[0] || p1[N] == three[1] || p1[N] == three[2] || p1[N] == three[3] || p1[N] == three[4] || p1[N] == three[5] || p1[N] == three[6] || p1[N] == three[7])
        { 
            score1 += 3;
        }
    }
}
like image 614
user26580059 Avatar asked Dec 22 '25 06:12

user26580059


2 Answers

I think @TangentiallyPerpedicular is right to suggest a lookup table, but memory is cheap, so rather than make your array have 26 elements and do math to convert a character to an index, make it larger and do the lookups right on the ASCII value of each character.

Designated initializers make the initialization quite straightforward.

int main() {
    int char_vals[256] = {
        ['A'] = 1, ['E'] = 1, ['I'] = 1,
        ['L'] = 1, ['N'] = 1, ['O'] = 1,
        ['R'] = 1, ['S'] = 1, ['T'] = 1,
        ['U'] = 1,
        ['D'] = 2, ['G'] = 2,
        ['B'] = 3, ['C'] = 3, ['M'] = 3,
        ['P'] = 3,
        ['F'] = 4, ['H'] = 4, ['V'] = 4,
        ['W'] = 4, ['Y'] = 4,
        ['K'] = 5,
        ['J'] = 8, ['X'] = 8,
        ['Q'] = 10, ['Z'] = 10
    };

    // ...
}

Alternatively when you want to check for membership in an array, you should be using a loop.

    char one[20] = {'a', 'A', 'e', 'E', 'i', 'I', 'l', 'L', 'n', 'N', 'o', 'O', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U'};

    for (size_t N = 0; N < str; N++)
        int worth_one = 0;
        for (size_t i = 0; i < sizeof(one); i++) {
            if (str[N] == one[i]) {
                worth_one = 1;
                break;
            }
        }

        if (worth_one) {
            score1++;
            continue;
        }

        // Repeat for two, three, four, etc.
    }

Beware that such an approach has linear runtime complexity while the lookup table has constant runtime complexity.

like image 64
Chris Avatar answered Dec 23 '25 19:12

Chris


In addition to multiple correct solutions using arrays, you can also use a switch statement if that is what you are expected to:

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>

int compute_score(const char *word) {
    int score = 0;
    for (size_t i = 0; word[i]; i++) {
        unsigned char uc = word[i];  // always use unsigned char with ctype macros
        switch (toupper(uc)) {
          case ' ':    // Accept space as wildcard. No points.
            break;
          case 'A':
          case 'E':
          case 'I':
          case 'L':
          case 'N':
          case 'O':
          case 'R':
          case 'S':
          case 'T':
          case 'U':
            score += 1;
            break;
          case 'D':
          case 'G':
            score += 2;
            break;
          case 'B':
          case 'C':
          case 'M':
          case 'P':
            score += 3;
            break;
          case 'F':
          case 'H':
          case 'V':
          case 'W':
          case 'Y':
            score += 4;
            break;
          case 'K':
            score += 5;
            break;
          case 'J':
          case 'X':
            score += 8;
            break;
          case 'Q':
          case 'Z':
            score += 10;
            break;
          default:
            printf("not a letter: `%c`\n", uc);
            return -1;
        }
    }
    return score;
}

int main(void) {
    //get the strings from the players and store them in a string data type
    string p1 = get_string("Player 1: ");
    string p2 = get_string("Player 2: ");
    //compute the player scores
    int score1 = compute_score(p1);
    int score2 = compute_score(p2);
    printf("Player 1 got %d points for '%s'\n", score1, p1);
    printf("Player 2 got %d points for '%s'\n", score2, p2);
    return 0;
}
like image 34
chqrlie Avatar answered Dec 23 '25 20:12

chqrlie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!