【发布时间】:2021-01-03 08:21:07
【问题描述】:
我正在处理凯撒问题的 CS50(2021x 版本),遇到了问题。我的程序在 ASCII 范围之外打印(感谢不和谐的好奇猕猴桃提供了这个提示)。错误消息显示“:( 使用 23 作为密钥将“barfoo”加密为“yxocll”,输出无效的 ASCII 文本”。我遇到的另一个问题是“世界,问好!”,出于同样的原因(无效的 ASCII文本)。其他的加密很好。
我已经通过调试器发现“字母”变量有时会变成负整数,例如 -119'/211',但不知道为什么会这样。我希望看到与 ASCII 中的字母相关的正值。发生这种情况时,这些字母将停止在控制台上打印。
如果我输入 ./caesar 23 | cat -A 然后将 barfoo 作为明文给出,密文将显示为 yxM-^IcM-^FM-^F$。
int main(int argc, string argv[])
{
// only 1 arugment, and positive argument only
if (argc == 2 && argv[1] > 0)
{
// check if each char of argument is digit
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isdigit(argv[1][i]))
{
// do nothing
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
// change the key to how much letters should move over
int input = atoi(argv[1]);
int key = input % 26;
char letter;
// get the input
string text = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i])) // if it is an alphabet
{
if (islower(text[i])) // if it is lowercase
{
letter = text[i] + key; // add key to text[i]
if (letter > 122)
{
// loop around the alphabet
letter -= 26;
}
printf("%c", letter);
}
else // if it is uppercase
{
letter = text[i] + key; // add key to text[i]
if (letter > 90)
{
// loop around the alphabet
letter -= 26;
}
printf("%c", letter);
}
}
else // if it is not an alphabet
{
printf("%c", text[i]);
}
}
printf("\n");
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
【问题讨论】:
-
argv[1] > 0不是检查 NULL 或字符串长度的正确方法,只需检查argc的值就足够了 -
顺便说一句,您无需在
islower()或isupper()之前检查isalpha()。 b) 不要硬编码幻数,使用'Z'而不是90。 -
对不起,我想我写的代码不清楚。在该行上,我试图检查用户是否输入了非负数。有没有更好的写法?
-
3)
letter = text[i] + key;应该是if(isupper(text[i])) {letter = (text[i] - 'A' + key) % 26 + 'A';}等,因为密钥可能是 26 的许多倍数。 -
您需要先执行
atoi,然后验证input是否为非负数。