从stdin读取fgets时,为什么忽略第一个字符串?

时间:2012-12-25 19:38:14

标签: c stdin fgets

  

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

我试图使用fgets从stdin读取一个字符串数组,但是我想要读取的第一个字符串总是被忽略。是什么导致了这个问题?

#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;
}

5 个答案:

答案 0 :(得分:2)

scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
    printf("Name=");
    fgets(list[i].name, 30, stdin);

scanf("%u", &nr);将换行符留在输入缓冲区中,因此fgets找到一个空行而无需输入更多输入。

由于这个原因(其中包括),混合(f)scanffgets通常是一个坏主意。

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

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

更原则性的修复方法是在使用fgets获取整行(包括换行符)之前读入值,并使用strtoulsscanf解码数字。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

我注意到我可以通过getchar()读取输入缓冲区中剩下的换行符。

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

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

答案 3 :(得分:0)

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

当计算机询问材料数量时:

  

材料数量=
        51

输入“51”,你真正得到三个字符:'5''1''\n'。点击回车键时,所有内容都会带有换行符。

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

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

scanf("%u", &nr);

离开换行符,然后当您尝试执行下一行读取时:

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

fgets选择该换行并存储它。

所以这里有一堆修复,一个是仅使用fgets(),另一个是在每次扫描后使用getchar()消耗换行符,选择由您决定。

BTW:您可以在printfs中插入换行符:printf(“材料数量= \ n”);

答案 4 :(得分:-1)

你可以在每次scanf之后做一个fgets,然后吃掉待处理的换行符:

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