【问题标题】:Why does puts() print an extra character in the end?为什么 puts() 最后会打印一个额外的字符?
【发布时间】:2014-12-14 10:03:19
【问题描述】:
#include<stdio.h>
#include<conio.h>
int main()
{
char test [7];
for(int i=0;i<10;i++)
scanf("%c",&test[i]);
puts(test);
getch();
return 0;
}

我正在使用 DevC++(大学规则)并且我知道 gets() 没有边界检查,所以我故意使用 for() 循环来输入字符串。当我输入一个大于数组大小的字符串时,puts 正在打印一个额外的字符。为什么这样 ??

示例输入:helloworld 输出:你好

示例输入:Hellopeople 输出:Hellopep

【问题讨论】:

  • 没有gets,请忘记这个功能曾经存在过。 OTOH fgets 活得很好,你应该使用它而不是你的手写循环,如果你没有用 NUL 字符终止你的字符串,原则上它可以工作。另外,故意溢出最多 10 个字符的 7 个字符长缓冲区是什么原因?
  • UB 多重复制。不要超出数组边界,并注意 SO 是可搜索的。
  • @n.m.故意溢出只是为了在溢出的情况下检查 puts 的行为。你能解释一下为什么 puts() 应该只打印 7 个字符而打印更多的 8 个字符。以及为什么打印的字符是紧随其后的。
  • 检查溢出是如何工作的没有什么意义,除非你知道事情是如何在没有溢出的情况下工作的。 (1) 去除溢出,恢复正常的非溢出行为。 (2) 谷歌“空终止字符串”是什么意思。在你接触 C 中的字符串之前,你需要熟悉这个概念。

标签: c arrays string puts


【解决方案1】:

这是因为你的内存溢出了。你的数组只有七个字符,你尝试用十个填充它:

char test [7];             // Array indexes 0-6 allowed.
for(int i=0;i<10;i++)      // Array indexes 0-9 used.
    scanf("%c",&test[i]);

您可以通过以下方式修复它(包括允许使用字符串终止符):

char test [11];            // Array indexes 0-10 allowed.
for(int i=0;i<10;i++)      // Array indexes 0-9 used.
    scanf("%c",&test[i]);
test[10] = '\0';           // And add string terminator before puts().

如果您想要一个具有缓冲区溢出保护的强化用户输入功能,从fgets() 构建的东西通常是标准 C 中的最佳方式。例如,this 之类的东西。

【讨论】:

    【解决方案2】:

    当您尝试将 10 个字符存储到最多可以存储 7 个元素的缓冲区中时,您有一个 buffer overflow

    char test [7];
    for(int i=0;i<10;i++)
      scanf("%c",&test[i]);
    

    您可以通过将缓冲区设置为 10 个元素来解决此问题(这样它就可以存储 9 个字符以及最后一个用于 \0 的字符)并使用以下代码:

    char test [10]; //10 elements long
    scanf("%9s",test); //Get at-most 9 chars
    

    或者你也可以使用fgets

    【讨论】:

      【解决方案3】:

      您的 test 数组只有 7 个字符,而您通过 for 循环将 10 个字符读入其中。这可能会崩溃。

      puts 也希望您的字符串以 0 结尾。您没有在字符后显式放置 0,因此输出将包含字符后的任何垃圾,直到第一个 0 字节。

      【讨论】:

        【解决方案4】:

        您的字符串不以 '\0' 结尾。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-28
          • 2020-07-05
          • 2021-09-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多