Search code examples
ccs50caesar-cipher

=PSET 2 CAESAR= How do I convert ASCII range down to a value from 0 to 25?


I first did this:

// Convert ASCII range down to a value from 0 to 25

char uppercase[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char lowercase[27] = "abcdefghijklmnopqrstuvwxyz";
char convertedUppercase[27];
char convertedLowercase[27];

for (int i = 0; i <= 26; i++)
{
    convertedUppercase[i] = uppercase[i] - 'A';
    convertedLowercase[i] = lowercase[i] - 'a';
}

// For each character in the plaintext: (DOESN'T WORK)

for (int i = 0, n = strlen(p); i <= n; i++)
{
    // Rotate the character if it's a letter // ci = (pi + k) % 26

    if (isalpha(p[i]))
    {
        if (isupper(p[i]))
        {
            c[i] = ((p[i]) + k) % 26;
        }
        else if (islower(p[i]))
        {
            c[i] = ((p[i]) + k) % 26;
        }
    }
}

printf("ciphertext: %s\n", c);

but then I realized that the value of convertedUppercase will just be like 0 = NUL instead of 0 = A. Can anyone give me a hint what to do?

edit:

From the CS50 Discord:

"The caesar cipher formula (p + k) % 26 works on the premise that p (the plain text character) has a value of 0 - 25 (representing a - z or A - Z)

So if your plain char is 'x', that would have a value of 23, and if your key was 2, then the ciphered char would be:

(23 + 2) % 26
(  25  ) % 26
= 25  'z'

I'm kinda lost on how to do it.


Solution

  • This would be so much easier if you would provide a MRE.
    I guess what you are observing is that you see a truncated cipertext if you attempt to output it via printf() with "%s".
    This is however only because any "A" (that is a ciper A, i.e. after shifting by key) results in a 0 (which terminates string output, being the '\0' terminator) and most other letters result in unprintable characters.

    This is because you only shift by key and map to 0-25 what needs to be the number representation (i.e. numeric instead of textual ciper) here:

    c[i] = ((p[i]) + k) % 26;
    

    In order to turn into textual cipher instead of numeric ciper, you need to do

    • convert textual to numeric, with -'A'
    • shift by key, with +k
    • map to 0-25, with %26
    • convert numeric to textual, with +'A'

    I.e.

    c[i] = ((p[i]-'A') + k) % 26 + 'A';
    

    E.g. "H" from "Hello World".

    • textual to numeric, 'H' - 'A' -> 7
    • shift by key, 7 + 4 -> 11
    • map to 0-25, 11%26 -> 11
    • numeric to textual, 11 + 'A' -> 'L' is cipher

    E.g. "W" from "Hello World".

    • textual to numeric, 'W' - 'A' -> 22
    • shift by key, 22 + 4 -> 26
    • map to 0-25, 26%26 -> 0
    • numeric to textual, 0 + 'A' -> 'A' is cipher