从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
scanf("%u", &nr);
将换行符留在输入缓冲区中,因此fgets
找到一个空行而不需要输入更多输入。
由于这个原因(其中包括)混合(f)scanf
和fgets
通常是个坏主意。
作为快速修复,在第一个fgets
之前清空输入缓冲区,
int ch; while((ch = getchar()) != EOF && ch != '\n'); if (ch == EOF) { // oops }
一个更有原则性的修复方法是在使用fgets
获取整行(包括换行符)之前读取值,并使用strtoul
或sscanf
解码数字。
这是一个非常常见的错误。 使用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);