【问题标题】:Why is the first string ignored when reading with fgets from stdin? [duplicate]为什么从标准输入使用 fgets 读取时忽略第一个字符串? [复制]
【发布时间】:2012-12-25 19:38:14
【问题描述】:

可能重复:
Dev-C++ Input skipped

我正在尝试使用 fgets 从标准输入读取字符串数组,但我要读取的第一个字符串总是被忽略。是什么导致了这个问题?

#include <stdio.h>

int main()
{
    int i;
    struct material
    {
        char name[30];
        float price, kg;
    };
    unsigned m,nr;
    printf("Lorry capacity=");
    scanf("%u", &m);
    printf("Number of materials=");
    putchar('\n');
    scanf("%u", &nr);
    struct material list[nr];
    for (i=0; i<nr; i++)
    {
        printf("Name=");
        fgets(list[i].name, 30, stdin);
    }
    putchar('\n');
    for (i=0; i<nr; i++)
    {
        printf("%s ", list[i].name);
    }
    return 0;
}

【问题讨论】:

  • 您正在混合scanf()fgets()。只用fgets(),会简单很多。

标签: c stdin fgets


【解决方案1】:
scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
    printf("Name=");
    fgets(list[i].name, 30, stdin);

scanf("%u", &amp;nr); 将换行符留在输入缓冲区中,因此fgets 无需进一步输入即可找到空行。

出于这个原因(以及其他原因),混合(f)scanffgets 通常是个坏主意。

作为一种快速修复,在第一个 fgets 之前清空输入缓冲区,

int ch;
while((ch = getchar()) != EOF && ch != '\n');
if (ch == EOF) {
    // oops
}

更原则性的解决方法是在使用 fgets 之前读取值以获得包括换行符在内的整行,并使用 strtoulsscanf 解码数字。

【讨论】:

    【解决方案2】:

    这是一个非常常见的错误。使用 scanf 读取数字后,您通过按 ENTER 键入的换行符留在输入缓冲区中,因此第一次调用 fgets 会读取仅包含该换行符的(非常短的)行。

    【讨论】:

      【解决方案3】:

      我注意到我可以通过使用getchar() 读取输入缓冲区中的换行符来摆脱它。

      另外,我必须使用以下代码从 fgets() 输入中删除尾随换行符:

      char *pos;
      if ((pos=strchr(Name, '\n')) != NULL)
          *pos = '\0';
      

      【讨论】:

        【解决方案4】:

        通常被误解的一件事是,当您要求用户提供输入时,您会获得免费赠品。

        电脑询问材料量时:

        材料数量=
        51

        如果您输入“51”,您实际上会得到三个字符:'5''1''\n'。当您按下回车键时,所有内容都带有换行符。

        从用户那里获取输入的不同实用程序会处理这种不同的情况。 fgets() 将读取换行符,然后将输入存储为 "51\n"。如果您使用scanf() 的字符串格式特定器"%s" 将其读取为字符串,您将仅获得数字"51",并且换行符留在stdin 缓冲区中。

        因此,在您的情况下,您通过scanf 读取了一个数字:

        scanf("%u", &nr);
        

        留下换行符,然后当您尝试进行下一次阅读时:

        fgets(list[i].name, 30, stdin);
        

        fgets 获取该换行符并存储它。

        所以这里有很多可能的修复,一个是只使用fgets(),另一个是在每次scanf之后使用getchar()换行,选择取决于你。

        顺便说一句:您可以在 printfs 中插入换行符:printf("Number of materials=\n");

        【讨论】:

          【解决方案5】:

          您可以在每个 scanf 之后执行 fgets,然后它将吃掉待处理的换行符:

          char dummy[10];
          ...
          scanf (...);
          fgets (dummy, 1, stdin);
          

          【讨论】:

            猜你喜欢
            • 2020-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-02
            • 1970-01-01
            • 2019-05-04
            • 1970-01-01
            相关资源
            最近更新 更多