In the CS50 2019 Caesar assignment, I am supposed to perform Caesar shifts on characters by a given number of letters (key).
To do this, I add the value of key to each letter, as such:
for each character in plaintext:
plaintext[character] += key
Since I want z to loop back to a, I then wrote:
while (ciphered_character > 122)
{
ciphered_character -= 26;
}
Running the program with plaintext of z and a key of 26 causes 26 to be added to z (which is represented by 122). This causes plaintext[character] to overflow (past 127, I presume) and become negative before the while loop even kicks in. This gives a garbage output.
I know I can check for potential overflows beforehand and subtract 26 first, but that complicates my code. Can I give the variable 'more room' to prevent it from overflowing?
Do I use a different data type? What is the best practice here?
If you only care about lower case then this will work for you:
for each character in plaintext:
plaintext[character] = (plaintext[character] - 'a' + key) % 26 + 'a'
Subtracting 'a' to give you a value of 0-25, then add the key. If there is a overflow the modulo will give you the updated value in the 0-25 range which is added back to 'a' to get the correct character.
If you do need to handle both upper and lower case then you will need two different cases - one using 'a' and the other using 'A'. Select the the correct case for each character by checking isupper(plaintext[character])
Fun project;
I did it like this, assuming ASCII and using the full range of printable characters, from Space to ~
void caeser_shift(char* text, int key)
{ while (*text) { *text++ = ((*text-' ') + key) %('~'-' ') + ' '; } }
int main(void)
{
char plaintext[] = "Hello World; This is a test.";
caeser_shift(plaintext, 26);
printf("%s\n", plaintext);
return 0;
}
Success #stdin #stdout 0s 4520KB
b!((+:q+.( U:n$%/:%/:{:0!/0H
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With