使用 printf 打印不带空字符的字符串

Ram*_*esh 0 c

我昨天参加了 Google Code Jam 2019 Round 1C。以下是代码的一部分。

char str[5]={r1,r2,r3,r4,r5};
printf("%s\n", str);
Run Code Online (Sandbox Code Playgroud)

法官给出了错误的答案。但是如果我在打印语句之前添加这一行str[5]='\0';,它就可以工作。

实际上我检查了运行程序,它似乎打印正常。那么,我可以知道为什么法官给出了错误的答案以及哪里出了问题吗?谁能帮忙告诉我打印带有空字符和不带有空字符的字符串的区别?有人可以确认它是否总是给出正确的结果吗?

ybu*_*ill 5

按照约定,C 字符串以 null 结尾。这意味着printf或任何其他接收 C 字符串的函数将读取指向的内存,直到遇到空字符。

在您的情况下, 中没有空终止符str,因此printf将继续从接下来的内存中读取。这是未定义的行为。当你自己尝试时,你很幸运在之后没有跟随str,所以printf就停在前面了。如果你不太幸运,你可能会遇到垃圾或段错误。这可能就是法官执行代码时发生的情况。

请注意,这str[5] = '\0'也是未定义的行为,因为str[5]超出了数组的大小。

有效的替代解决方案:

包括空终止符:

char str[6]={r1,r2,r3,r4,r5,0};
Run Code Online (Sandbox Code Playgroud)

或者将缓冲区的大小传递给printf

printf("%.5s\n", str);
Run Code Online (Sandbox Code Playgroud)

或者:

printf("%.*s\n", (int)sizeof(str), str);
Run Code Online (Sandbox Code Playgroud)

或者使用fwrite

fwrite(str, 1, sizeof(str), stdout);
fputc('\n', stdout);
Run Code Online (Sandbox Code Playgroud)

  • @Ramesh:不,这是绝对正确的。数组的大小与您声明的一样大。您将它与“字符串文字”混淆了。如果您编写“char s[] = "abcde";”,那么数组的大小将需要为 6 才能包含 null 终止符。但您的代码中并非如此。不要争论,直接用“sizeof(str)”检查数组的大小。 (2认同)
  • @Ramesh:你的问题是“为什么法官拒绝你的答案”,答案是“因为它不符合标准”。编写符合标准的代码的目的是保证代码在所有实现上都以相同的方式工作。在您的特定计算机上发生的情况无关紧要,因为在另一个符合标准的实现上它可能会给出不同的结果。我敢打赌,Google Code Jam 在内部会使用一些额外的检查来进行判断。 (2认同)