【问题标题】:CS50 caesar.c - ciphertext printing out of ASCII code rangeCS50 caesar.c - 密文打印超出 ASCII 码范围
【发布时间】: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] &gt; 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 是否为非负数。

标签: c cs50


【解决方案1】:

您应该使用int letter 而不是char letter

这是因为

letter = text[i] + key;

将溢出已签名的char,例如'z' + 23

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多