Reputation: 175
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
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
Reputation: 76767
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'
printf("%c", ((plaintext[i] + key - 65) % 26) + 65);
and
printf("%c", ((plaintext[i] + key - 97) % 26) + 97);
respectively.
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
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