Reputation: 437
I am implementing a Vigenere cipher in C. My solution kept enciphering the plain-text incorrectly. I thus decided to make a (somewhat arbitrary) change to my code. The aim of the alteration was simply to make the code more readable, by positioning my variables better, and giving them more appropriate names. However, This change has now caused the solution to encipher properly; I can't explain why the current solution works over the original one. Could someone perhaps enlighten me?
original.c
//...code to validate user input
string k = argv[1]; //'argv' being a main method parameter
string str = GetString();
//Encrypt using vigenere
for (int i = 0, n = strlen(str); i < n; i++) {
/*An int to keep track of which char to use from the keyword.
Only increment if str[i] was alphabetic.*/
int k_index = 0;
int k_len = strlen(k);
char letter_key = tolower(k[k_index % k_len]);
//Checking if str[i] is alphabetic
if (isalpha(str[i])) {
//Checking if str[i] is uppercase
if (isupper(str[i])) {
//enciphering using vigenere formula
str[i] = ((str[i] - 'A') + (letter_key - 'a')) % 26 + 'A';
printf("%c", str[i]);
k_index++;
}
//If not uppercase, it must be lowercase
else {
//enciphering using vigenere formula
str[i] = ((str[i] - 'a') + (letter_key - 'a')) % 26 + 'a';
printf("%c", str[i]);
k_index++;
}
} else {
printf("%c", str[i]);
}
}
Output
Key: "chasi"
Input/Result: "my plaintext" ---> "oa rnckpvgzv"
Should be: "of pdikutwfv"
updated.c
//...code to validate user input
string k = argv[1];
string str = GetString();
//Encrypt using vigenere
for (int i = 0, j = 0, n = strlen(str); i < n; i++) {
/*"int j" is to keep track of which char to use from the keyword.
Only increment if str[i] was alphabetic.*/
int k_len = strlen(k);
char letter_key = tolower(k[j % k_len]) - 'a';
//Checking if str[i] is alphabetic
if (isalpha(str[i])) {
//Checking if str[i] is uppercase
if (isupper(str[i])) {
//enciphering using vigenere formula
str[i] = ((str[i] - 'A') + letter_key) % 26 + 'A';
printf("%c", str[i]);
j++;
}
//If not uppercase, it must be lowercase
else {
//enciphering using vigenere formula
str[i] = ((str[i] - 'a') + letter_key) % 26 + 'a';
printf("%c", str[i]);
j++;
}
} else {
printf("%c", str[i]);
}
}
Output:
Key: "chasi"
Input/Result: "my plaintext" ---> "of pdikutwfv" (correct)
Upvotes: 0
Views: 72
Reputation: 782466
The original code does:
int k_index = 0;
each time through the loop. Then when it does:
char letter_key = tolower(k[k_index % k_len]);
it's using this 0
value, so letter_key
is always tolower(k[0])
. The places where it does k_index++;
have no effect, because the variable gets zeroed before it gets used again. So you're just using the first character of the key as the whole key.
In the updated code, the variable j
takes the place of k_index
. It gets initialized to 0
when the loop starts, not each time through the loop. So when you do:
char letter_key = tolower(k[j % k_len]) - 'a';
you're using the updated value of j
. This properly uses the whole key.
Upvotes: 3