【发布时间】:2020-05-04 20:16:05
【问题描述】:
我不明白为什么它说“输出无效的 ASCII 文本”!
为了让您了解问题的背景,我发布了所描述的操作。 从这里开始!
在替换密码中,我们通过将每个字母替换为另一个字母来“加密”(即以可逆方式隐藏)消息。为此,我们使用一个密钥:在这种情况下,将字母表中的每个字母映射到我们加密时它应该对应的字母。要“解密”消息,消息的接收者需要知道密钥,以便他们可以反转过程:将加密文本(通常称为密文)翻译回原始消息(通常称为明文)。
例如,一个键可能是字符串NQXPOMAFTRHLZGECYJIUWSKDVB。这个 26 个字符的键意味着A(字母的第一个字母)应该转换成N(键的第一个字符),B(字母的第二个字母)应该转换成@ 987654325@(键的第二个字符),以此类推。
然后,像HELLO 这样的消息将被加密为FOLLE,根据密钥确定的映射替换每个字母。
让我们编写一个名为替换的程序,使您能够使用替换密码来加密消息。在用户执行程序时,他们应该通过提供命令行参数来决定他们将在运行时提供的秘密消息中的密钥。
以下是该程序可能如何工作的几个示例。例如,如果用户输入了YTNSHKVEFXRBAUQZCLWDMIPGJO的密钥和HELLO的明文:
$ ./substitution YTNSHKVEFXRBAUQZCLWDMIPGJO
plaintext: HELLO
ciphertext: EHBBQ
如果用户提供VCHPRZGJNTLSKFBDQWAXEUYMOI 的密钥和hello, world 的明文,程序可能会这样运行:
$ ./substitution VCHPRZGJNTLSKFBDQWAXEUYMOI
plaintext: hello, world
ciphertext: jrssb, ybwsp
请注意,逗号和空格都没有被密码替换。只能替换字母字符!还要注意,原始消息的大小写已被保留。小写字母保持小写,大写字母保持大写。
键本身的字符是大写还是小写无关紧要。 VCHPRZGJNTLSKFBDQWAXEUYMOI 的键在功能上与 vchprzgjntlskfbdqwaxeuymoi 的键相同(就此而言,VcHpRzGjNtLsKfBdQwAxEuYmOi)。
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./substitution KEY");
return 1;
}
else if (argc == 2)
{
string text = argv[1];
string storing = text;
int counter = 0;
int i = 0;
bool number = true;
bool flag = true;
while (flag == true && i < 26)
{
if ((int)text[i] >= 48 && (int)text[i] <= 57)
{
number = false;
}
if (((int)text[i] >= 65 && (int)text[i] <= 90) || ((int)text[i] >= 97 && (int)text[i] <= 122))
{
counter++;
for ( int j = 0; j < counter - 1; j++)
{
if ((int)storing[j] == (int)text[i] || (int)storing[j] + 32 == (int)text[i])
{
flag = false;
}
}
}
i++;
}
if (number == false)
{
printf("Key must only contain alphabetic characters.");
return 1;
}
if (flag == false)
{
printf("Key must not contain repeated characters.");
return 1;
}
if (counter < 26)
{
printf("Key must contain 26 characters.");
return 1;
}
}
string plaintext = get_string("plaintext:");
string key = argv[1];
int counter;
bool not_letter;
bool capital1;
bool capital;
int crypto[strlen(plaintext)];
for (int i = 0; i < strlen(plaintext); i++)
{
capital1 = false;
capital = false;
not_letter = false;
if ((int)plaintext[i] >=65 && (int)plaintext[i] <= 90)
{
counter = (int)plaintext[i] - 65;
capital = true;
}
else if ((int)plaintext[i] >=97 && (int)plaintext[i] <= 122)
{
counter = (int)plaintext[i] - 97;
capital1 = true;
}
else
{
not_letter = true;
}
if (not_letter == true)
{
crypto[i] = (int)plaintext[i];
}
else if (capital == true)
{
if ((int)key[i] >=65 && (int)key[i] <= 90)
{
crypto[i] = (int)key[counter];
}
else if ((int)key[i] >=97 && (int)key[i] <= 122)
{
crypto[i] = (int)key[counter] - 32;
}
}
else if (capital1 == true)
{
if ((int)key[i] >=65 && (int)key[i] <= 90)
{
crypto[i] = (int)key[counter] + 32;
}
else if ((int)key[i] >=97 && (int)key[i] <= 122)
{
crypto[i] = (int)key[counter];
}
}
}
printf("ciphertext: ");
for (int i = 0; i < strlen(plaintext); i++)
{
printf("%c", (char)crypto[i]);
}
printf("\n");
return 0;
}
当我用 CS50 的 check50 cs50/problems/2020/x/substitution 测试程序时,它说:
:) substitution.c exists
:) substitution.c compiles
:) encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
:) encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
:) encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:) encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key
:) encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key
! :( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key
output not valid ASCII text
! :( encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
output not valid ASCII text
:) handles lack of key
:) handles invalid key length
:) handles invalid characters in key
:) handles duplicate characters in key
:) handles multiple duplicate characters in key
【问题讨论】:
-
不要硬编码 ASCII 码。使用
isalpha()、tolower()等内置函数。 -
并使用函数。一个用于验证密钥,一个用于制作字典或其他任何东西,一个用于编码字符串。简单的函数更容易理解和调试。
-
当明文字符为大写且替换也为大写时,您的程序会产生非 ASCII 输出。我认为这应该为您指明正确的方向。
-
其实比这更令人困惑。如果您提供纯文本
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,它会为A生成一个非ASCII 替换。但如果明文只是ABCDEFGHIJKLMNOPQRSTUVWXYZ,则密文是正确的。 -
所以你似乎让一些上/下状态在字符之间持续存在。
标签: c arrays string encryption cs50