2

可能重复:
Dev-C++ 输入被跳过

我正在尝试使用 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;
}
4

5 回答 5

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)scanf和通常是一个坏主意。fgets

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

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

一个更有原则的解决方法是在使用之前读入值fgets以获取包括换行符在内的整行,并使用strtoulor解码数字sscanf

于 2012-12-25T19:41:43.127 回答
1

我注意到我可以删除输入缓冲区中留下的换行符,方法是使用getchar().

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

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos = '\0';
于 2012-12-25T20:21:50.163 回答
1

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

于 2012-12-25T19:41:46.740 回答
0

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

电脑询问材料量时:

材料数量=
51

你输入“51”,你真的得到了三个字符:'5''1''\n'。当您按下回车键时,所有内容都带有换行符。

从用户那里获得输入的不同实用程序处理这个不同。fgets()将读取换行符,然后将输入存储为"51\n". scanf()如果您使用's string format specificer将其作为字符串读取,"%s"您将仅获得数字"51",并且换行符留在stdin缓冲区中。

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

scanf("%u", &nr);

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

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

fgets拿起该换行符并存储它。

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

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

于 2012-12-25T21:11:07.300 回答
-1

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

char dummy[10];
...
scanf (...);
fgets (dummy, 1, stdin);
于 2012-12-25T19:44:12.990 回答