Ranwolf Surveyir
Ranwolf Surveyir

Reputation: 23

CS50 caesar.c - ciphertext printing out of ASCII code range

I'm going through CS50 (2021x version) of Caesar problem, and ran into problem. My program is printing outside of ASCII range (thanks to curiouskiwi over at discord for this hint). The error message says ":( encrypts "barfoo" as "yxocll" using 23 as key, output not valid ASCII text". Another one I'm having trouble is "world, say hello!", for same reason (Not valid ASCII text). Other ones are encrypting fine.

I've stepped through the debugger and found that 'letter' variable is sometimes becoming a negative integer like -119'/211', but can't figure out why that may be so. I expected to see positive value associated with an alphabet in ASCII. When this happens the letters will stop printing on the console.

If I type ./caesar 23 | cat -A and then give barfoo as plaintext, the cyphertext will come out as yxM-^IcM-^FM-^F$.

int main(int argc, string argv[])
{
    // only 1 arugment, and positive argument only
    if (argc == 2 && argv[1] > 0)
    {
        // check if each char of argument is digit
        for (int i = 0, n = strlen(argv[1]); i < n; i++)
        {
            if (isdigit(argv[1][i]))
            {
                // do nothing
            }
            else
            {
                printf("Usage: ./caesar key\n");
                return 1;
            }
        }

        // change the key to how much letters should move over
        int input = atoi(argv[1]);
        int key = input % 26;
        char letter;

        // get the input
        string text = get_string("plaintext: ");
        printf("ciphertext: ");

        for (int i = 0, n = strlen(text); i < n; i++)
        {
            if (isalpha(text[i])) // if it is an alphabet
            {
                if (islower(text[i])) // if it is lowercase
                {
                    letter = text[i] + key; // add key to text[i]
                    if (letter > 122)
                    {
                        // loop around the alphabet
                        letter -= 26;
                    }
                    printf("%c", letter);
                }
                else // if it is uppercase
                {
                    letter = text[i] + key; // add key to text[i]
                    if (letter > 90)
                    {
                        // loop around the alphabet
                        letter -= 26;
                    }
                    printf("%c", letter);
                }
            }
            else // if it is not an alphabet
            {
                printf("%c", text[i]);
            }
        }
        printf("\n");
    }
    else
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
}

Upvotes: 0

Views: 238

Answers (1)

Weather Vane
Weather Vane

Reputation: 34575

You should use int letter instead of char letter.

This is because

letter = text[i] + key;

will overflow signed char for, say, 'z' + 23.

Upvotes: 1

Related Questions