在scanf之后使用puts和Gets不起作用

问题描述

如果我在puts()gets()之前使用scanf(),似乎gets()puts()函数不起作用。请参见下面的代码

如果我删除之前的部分,则puts()gets()可以正常工作。为什么呢?

#include <stdio.h>
#include <string.h>

int main (void)
{
    int numberOutcomes;
    char outcomeOne[50];

    printf("How many outcomes do you have on your form?\n");
    scanf(" %d",&numberOutcomes);
    printf("The number of outcomes you have on your form is %d\n",numberOutcomes);

    printf("Type in your first outcome then press Enter. For example: good outcome or bad outcome.\n");
    gets(outcomeOne);

    puts(outcomeOne);

    return 0;
}

解决方法

第一条建议,请勿使用gets()-无法安全使用 来避免潜在的缓冲区溢出(这是 few 从C11开始甚至已从ISO标准中删除的内容)。而是使用fgets(),它可以限制读入的内容。

关于您的特定问题,scanf(" %d",&numberOutcomes)将在跳过空格后在输入流中消耗足够的字符以填充numberOutcomes,而不再填充。重要的是,它不会不会占用行尾空格,例如当您按下 ENTER 提交输入时放在其中的\n字符。

因此,在gets()调用中,它只会得到一个空白行。

这些

这两个问题都可以通过选择scanf()样式输入或基于行的输入 来解决。对于前一种情况,扫描下一项通常会跳过输入流中的空白,对于后一种情况,读取行将读取包括尾随空白的整行。

您可以使通过混合两者来使它起作用,但这需要更多的努力。

我的建议是对所有内容使用基于行的输入,然后从您读取的字符串中sscanf特定数据。优点是:

  • 避免出现您发现的确切问题;和
  • 如果您需要处理多种行格式,则允许您在同一行上多次sscanf

为此,坚如磐石的行输入例程(例如this one)非常方便。