【问题标题】:C: Output with symbols in Caesar’s cipher encrypts, WHY? pset2 cs50C:用凯撒密码加密的符号输出,为什么? pset2 cs50
【发布时间】:2014-07-17 20:14:12
【问题描述】:

这是 edx.org 的 cs50x 课程的 pset2 中的凯撒密码加密问题。

我已经用另一种算法解决了这个问题,但这是我第一次尝试,我仍然很好奇为什么所有这些符号都出现在凯撒文本的右侧。

即。我输入文本“Testing”,输出为“Fqefuz�����w����l��B��”,但没有符号,答案是正确的。

谁能解释一下?

int main(int argc, string argv[])
{
    bool keyOk = false;
    int k = 0;   
    do
    {
        if(argc != 2) // Checking if the key was correctly entered.
        {
            printf("You should enter the key in one argument from"
                " the prompt(i.e. './caesar <key>').\n");
            return 1;
        }
        else
        {
            k = atoi(argv[1]); // Converting string to int.
            keyOk = true; // Approving key.
        }
    }
    while(keyOk == false);

    string msg = GetString(); // Reading user input.
    char caesarMsg[strlen(msg)];

    for(int i=0, n = strlen(msg); i < n; i++)
    {

        if( (msg[i] >= 'a') && (msg[i] <= 'z') )
        // Processing lower case characters
        {
            caesarMsg[i] = ((((msg[i] - 97) + k) % 26) + 97);
        }
        else if( (msg[i] >= 'A') && (msg[i] <= 'Z') )
        // Processing upper case characters
        {
            caesarMsg[i] = ((((msg[i] - 65) + k) % 26) + 65);
        }
        else
        {
            caesarMsg[i] = msg[i];
        }

    }
    printf("%s", caesarMsg);
    printf("\n");        
}

【问题讨论】:

  • 您新编码的字符串缓冲区太小了 1 个字节。您还需要为终止零留出空间。 (此外,您甚至不添加终止零。)
  • char caesarMsg[strlen(msg)]; --> char caesarMsg[strlen(msg)+1];
  • 我已经尝试过这个“char caesarMsg[strlen(msg)+1];”并且不工作。我最近读到关于终止零,我会记住的。感谢您的回答。
  • OT:如果您要检查文字字符 'a'..'z' 和 'A'..'Z',最好在接下来的计算中也使用它们,而不是半魔法值“97”和“65”。

标签: c string c-strings cs50


【解决方案1】:

根本问题是 C 确实 有完整的、正确的或一流的“字符串”数据类型。在C strings 中实际上是以NUL ('\0') (*) 字符结尾的字符数组。

看看

  string msg = GetString();  // Reading user input.
  char caesarMsg[strlen(msg)];

这相当于

  char* msg = GetString();  /* User or library function defined elsewhere */

/* calculates the length of the string s, excluding  the terminating null
   byte ('\0') */
  size_t len = strlen(msg);  

  char caesarMsg[len];  /* Create an character (byte) array of size `len` */

希望这可以更清楚地说明本节无法正常工作的原因。我添加的变量len 是字符串msg 中非NUL 字符序列的长度。因此,当您创建长度为len 的字符数组caesarMsg 时,没有空间存储NUL 字符。

for 循环正确执行,但printf("%s", caesarMsg); 将继续打印字符,直到找到 NUL 或崩溃。

顺便说一句,您可以轻松地将末尾的两个 printf 语句简化为一个 printf 语句。

printf("%s\n", caesarMsg); 

字符串和字符数组是 C 新手的常见混淆来源,而 C 新手也经常会感到困惑。一些额外的参考资料:


咆哮:创建string typedef 的人是邪恶的/犯了一个严重的错误,误导学生认为 C 的字符串是“真实的”(或一流的)数据类型。


(*) NULNULL 不同,因为 NULL(空指针)被转换为指针,因此它与其他指针大小相同,其中 NUL 是空指针字符(以及charint 的大小)。

【讨论】:

  • 迈克尔·泰勒,感谢您提供的出色信息。在 for 循环中我改变了这个: n = strlen(msg) 对于这个 n = strlen(msg) + 1 并且像一个魅力一样工作。谢谢您,我非常感谢您提供的信息。
猜你喜欢
  • 1970-01-01
  • 2014-03-27
  • 2014-03-07
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-11
  • 2016-08-30
相关资源
最近更新 更多