Vigenere Cipher работает только до пробела (" ") в C - почему?
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
string k = argv[1];
string s = GetString();
int l = strlen(k);
for(int i = 0, n = strlen(s); i < n; i++)
{
if(s[i] >= 65 && s[i] <= 90)
{
int i2 = ((s[i]-65) + (k[i%l]-97)) % 26;
printf("%c", i2+65);
} else if(s[i] >= 97 && s[i] <= 122)
{
int i2 = ((s[i]-97) + (k[i%l]-97)) % 26;
printf("%c", i2+97);
} else
{
printf("%c", s[i]);
}
}
printf("\n");
return 0;
}
Я удалил столько частей, сколько смогу, чтобы сделать код более актуальным для вопроса. В основном, почему этот код работает, когда в "s" нет пробела (" ") и нет, когда "s" состоит из пробела (" ")?
Как большинство из вас может знать, идея заключается в том, что аргумент, введенный в argv[1], является "ключевым словом" для шифра. Затем пользователь вводит "обычный текст" для шифрования (-й). Он работает, когда я пытаюсь использовать разные слова или предложения, если в нем нет пробела, "". Я просто не понимаю логику этого. Почему цикл прерывается, если s[i]
это не одно из первых двух условий - я бы подумал, что "другое" условие сработает.
Я был бы очень признателен, если бы кто-то смог пролить свет на это - большое спасибо заранее!
PS: я знаю, что есть некоторые дополнительные библиотеки в верхней части и пользовательский ввод в argv[1]
не подтверждено с помощью isalpha()
, Я просто хочу лучше понять процесс цикла, у меня есть эти проверки в другом файле.
1 ответ
Вот код, который реализует комментарий "отдельные счетчики для строки и ключа", который я сделал. Он также использует буквенные коды 'a'
а также 'A'
(и избегает необходимости использования 'z'
или же 'Z'
) вместо использования чисел. Предполагается, что вы имеете дело с однобайтовым кодовым набором (не UTF-8, если вы не работаете в диапазоне ASCII), где строчные и прописные буквы находятся в непрерывном диапазоне (так что это Надежно работает с EBCDIC, но будет работать с большинством других кодовых наборов), а также игнорирует символы с ударением. (Это должно было бы сделать setlocale("")
чтобы получить специфичные для локали интерпретации того, какие символы являются буквами.)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
return 1;
}
string k = argv[1];
int l = strlen(k);
for (int i = 0; i < l; i++)
{
int c = k[i];
if (!isalpha(c))
{
fprintf(stderr, "%s: non-alpha character %c in key string\n", argv[0], c);
return 1;
}
k[i] = tolower(c);
}
printf("Enter a string to be encrypted:\n");
string s = GetString();
int n = strlen(s);
for (int i = 0, j = 0; i < n; i++)
{
int c = (unsigned char)s[i];
if (isupper(c))
c = ((c - 'A') + (k[j++ % l] - 'a')) % 26 + 'A';
else if (islower(c))
c = ((c - 'a') + (k[j++ % l] - 'a')) % 26 + 'a';
putchar(c);
}
putchar('\n');
return 0;
}
Вот примерный прогон, который демонстрирует слабость использования "a" в качестве одной из букв в ключе для этого шифра Vigenere:
./vc caesArandAbrAcaDabRa
Enter a string to be encrypted:
It is reported that Caesar said "Veni, vidi, vici" when he conquered Britain.
Kt mk rvpbutfu tjaw Cbvscr wsiu "Vrqi, wzdk, vlcj" nhgn lw cfndxesvd Drltbzn.