Ваши проблемы - логические c ошибки, которые появляются в результате изменений, которые вы пытались внести в код, который вышел из-под контроля. У вас есть ненужные циклы и неиспользуемая переменная в вашем коде. Вам нужно изменить область действия объявления u
, чтобы она повторно инициализировалась на каждой итерации. Вам просто нужно удалить for (int i = 0, n = strlen(key); i < n; i++)
l oop, ни i
, ни n
не используются. То же самое для ciphertext
и l
(ell).
Вам необходимо переместить int u = 64;
сразу после if (isupper(plaintext[k]))
, чтобы оно сбрасывалось на каждой итерации.
Я подозреваю, что все printf
операторы были для отладки, и вы действительно хотите только вывод key
. В целом, вы можете изменить свой код на:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, string argv[]) {
if (argc == 2) { /* validate key given */
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
{
int u = 64;
for (int j = 0; j < 26; j++)
{
u = u + 1;
if (u == plaintext[k]) {
printf("%c", key[j]);
break;
}
}
}
else
printf("%c", plaintext[k]);
}
putchar ('\n');
}
}
Пример использования / Вывод
$ ./bin/cs50_cypher2 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext: ABD
ciphertext: JTE
Упрощение логики c
Если вы думаете о том, что на самом деле делает код выше, его можно уменьшить до:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext: ");
printf("ciphertext: ");
for (int k = 0, p = strlen(plaintext); k < p; k++)
{
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else
putchar (plaintext[k]);
}
putchar ('\n');
}
Или если вы используете оператор троичный , ваш for
l oop сводится к простому:
for (int k = 0, p = strlen(plaintext); k < p; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
И поскольку нет необходимости звонить strlen(plaintext)
, вы можете полностью исключить string.h
и просто l oop for (int k = 0; plaintext[k]; k++)
, начиная с plaintext
является строкой с нулевым символом в конце, вся ваша программа может уменьшиться до:
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
int main (int argc, string argv[]) {
if (argc < 2) { /* validate key given */
fputs ("usage: ./program key\n", stderr);
return 1;
}
string key = argv[1];
string plaintext = get_string("plaintext : ");
printf("ciphertext: ");
for (int k = 0; plaintext[k]; k++)
putchar (isupper(plaintext[k]) ? key[plaintext[k] - 'A'] : plaintext[k]);
putchar ('\n');
}
Обработка строчных букв
Вы знаете, что key
введено в качестве первого аргумента все в верхнем регистре. Поэтому, если вы хотите вывести строчную букву key
, вы должны вызвать tolower()
на клавише после того, как вы применили смещения. Поскольку для заглавной буквы вы просто хотите узнать смещение внутри 26-символьной клавиши, вы просто узнаете, сколько букв ваша текущая буква от 'A'
и получите это смещение в key[]
, например
key[plaintext[k] - 'A']
Для ввода строчных букв необходимо определить смещение в key
для разницы в строчных буквах, а затем применить tolower()
к клавише, например,
tolower(key[plaintext[k] - 'a'])
См. ASCII Таблица и описание
В целом, ваш for
l oop может быть записан как:
for (int k = 0; plaintext[k]; k++) {
if (isupper(plaintext[k]))
putchar (key[plaintext[k] - 'A']);
else if (islower(plaintext[k]))
putchar (tolower(key[plaintext[k] - 'a']));
else
putchar (plaintext[k]);
}
Пример использования / Вывод
$ ./bin/cs50_cypher4 JTREKYAVOGDXPSNCUIZLFBMWHQ
plaintext : AbZ 50
ciphertext: JtQ 50
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.