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

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

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

#include  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("%u", &nr); struct material list[nr]; for (i=0; i 将换行符留在输入缓冲区中,因此fgets找到一个空行而不需要输入更多输入。 

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

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

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

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

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

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

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

 char *pos; if ((pos=strchr(Name, '\n')) != NULL) *pos = '\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() ,另一个是在每个scanf之后使用getchar()消耗换行符,选择取决于你。

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

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

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