martinb
martinb

Reputation: 175

Print Caesar Shift in C is printing the entered text of HELLO

I am trying to perform a Caesar cipher from text from user using modulo operation with the ascii characters. But, my code simply prints the entered test. For example, when the text entered is HELLO the program returns "HELLO". The goal is for a key of 13 it should print URYYB. Thank you.

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int key = atoi(argv[1]);

string plaintext = get_string("Enter plaintext: ");

for (int i = 0; i < strlen(plaintext); i++)
{
    if (isalpha(plaintext[i]))
    {
        if (isupper(plaintext[i]))
        {
            printf("%c", ((plaintext[i] + key) % 26) + 65);
        }
        else if (islower(plaintext[i]))
        {
            printf("%c", ((plaintext[i] + key) % 26) + 97);
        }
        else
        {
            printf("%c", plaintext[i]);
        }
    }
}
printf("\n");

Upvotes: 1

Views: 406

Answers (3)

Arkku
Arkku

Reputation: 42149

You are adding key to the value of each plaintext character, when it is meant to apply to the corresponding letter's index in the alphabet. For example, in case of the 'H' in ASCII, your formula is: (72 + 13) % 26 which gives 7 (which is also the index of H in the alphabet, when starting from zero).

You need to convert the (ASCII) value of the character to its index before applying key, e.g., ((plaintext[i] - 'A' + key) % (1 + 'Z' - 'A')) + 'A'.

The solution for 'H' would then become (72 - 65 + 13) % 26, which gives 20 (the correct answer, 7 + 13, the index of U).

Upvotes: 2

Lajos Arpad
Lajos Arpad

Reputation: 76767

Preliminary analysis

Character code of 'H' is 72.

(72 + 13) % 26 + 65 = 85 % 26 + 65 = 7 + 65 ~ 'H'

Let's see if we subtract 65 first:

(72 - 65 + 13) % 26 + 65 = (7 + 13) % 26 + 65 = 20 % 26 + 65 = 20 + 65 = 85 ~ 'U'

Solution

printf("%c", ((plaintext[i] + key - 65) % 26) + 65);

and

printf("%c", ((plaintext[i] + key - 97) % 26) + 97);

respectively.

Proof

If you have a character code, C, where S <= C < S + 26, then the formula you used is:

((C + key) % 26) + S

however, the actual letter is L and we know that

C = S + L,

so the formula is

((S + L + key) % 26) + S

and, since

(A + B) % C = ((A % C) + (B % C)) % C,

replacing A with (S), B with (L + key) and C with 26, we get:

((S % 26) + ((L + key) % 26)) % 26, we see that the result is distorted by (S % 26), which, in the case of 65 is exactly 13. Since a distortion of 13 + the key of 13 you used in the modulo class of 26 will yield the initial letter!

So, the proposed new formula of

((C + key - S) % 26) + S = (((S + L) + key - S) % 26) + S = ((L + key) % 26) + S

is exactly what you need.

Upvotes: 2

0___________
0___________

Reputation: 67721

Your cipher function just does nothing if the key is 13:

run a bit amended one and see the result :D

int main()
{
    int key = 13;

    char  plaintext[] = "HELLO";

    for (int i = 0; i < strlen(plaintext); i++)
    {
        if (isalpha(plaintext[i]))
        {
            if (isupper(plaintext[i]))
            {
                printf("%d, %d\n", (int)plaintext[i], (int)(((plaintext[i] + key) % 26) + 65));
            }
            else 
            {
                if (islower(plaintext[i]))
                {
                    //printf("%c", ((plaintext[i] + key) % 26) + 97);
                }
                else
                {
                    //printf("%c", plaintext[i]);
                }
            }
        }
    }
    printf("\n");
    return 0;
}

Upvotes: 0

Related Questions