#c #algorithm #encryption #cs50 #vigenere
#c #алгоритм #шифрование #cs50 #виженер
Вопрос:
Я реализую шифр Виженера в C. Мое решение продолжало неправильно шифровать обычный текст. Поэтому я решил внести (несколько произвольное) изменение в свой код. Целью изменения было просто сделать код более читаемым, улучшив расположение моих переменных и присвоив им более подходящие имена. Однако это изменение теперь привело к правильному шифрованию решения; Я не могу объяснить, почему текущее решение работает поверх исходного. Может кто-нибудь, возможно, просветит меня?
оригинал.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]);
}
}
Вывод
Key: "chasi"
Input/Result: "my plaintext" ---> "oa rnckpvgzv"
Should be: "of pdikutwfv"
обновлено.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]);
}
}
Вывод:
Key: "chasi"
Input/Result: "my plaintext" ---> "of pdikutwfv" (correct)
Комментарии:
1. @user3386109 его исправили
2. В исходном коде
k_index
устанавливается обратно0
каждый раз через цикл. Обновленный код устанавливает его0
в начале, затем увеличивает его во время циклов.3. @Barmar аааа, я вижу! Вот почему, по крайней мере, первый символ всегда правильный в исходном коде!
4. Переменная — не единственное изменение. Вы также изменили строки «шифрования».
5. @WeatherVane да, но математика, стоящая за строками шифрования, все та же. Просто вычисление ‘letter_key’ выполняется ранее.
Ответ №1:
Исходный код не:
int k_index = 0;
каждый раз через цикл. Затем, когда это произойдет:
char letter_key = tolower(k[k_index % k_len]);
он использует это 0
значение, так letter_key
всегда tolower(k[0])
. Места, где это не k_index ;
имеет никакого эффекта, потому что переменная обнуляется до того, как она будет использована снова. Итак, вы просто используете первый символ ключа как весь ключ.
В обновленном коде переменная j
занимает место k_index
. Он инициализируется 0
при запуске цикла, а не каждый раз в цикле. Поэтому, когда вы делаете:
char letter_key = tolower(k[j % k_len]) - 'a';
вы используете обновленное значение j
. При этом правильно используется весь ключ.