我希望更好地了解使用fgets()
和stdin
。
以下是我的代码:
int main()
{
char inputBuff[6];
while(fgets(inputBuff, 6, stdin))
{
printf("%s", inputBuff);
}
return 0;
}
假设输入为aaaabbbb
,按Enter键。通过使用循环计数,我明白在下一次输入之前,循环实际上会运行两次(包括我输入的aaaabbbb
)。
循环1:输入字符后,aaaabbbb\n
将存储在stdin
文件流的缓冲区中。 fgets()
将从文件流中检索特定数量的数据并将其放入inputBuff
。在这种情况下,它将一次检索5(6 - 1)个字符。因此,当fgets()
已经运行一次时,inputBuff
将存储aaaab
,然后进行打印。
循环2:然后,由于bbb\n
保留在文件流中,fgets()
将第二次执行,以便inputBuff
包含{{1}然后被打印出来。
循环3:程序将在文件流到达末尾(bbb\n
)时询问我的输入(第二次)。
问题:在EOF
流没有数据留在缓冲区(fgets()
)之后,stdin
似乎只会询问我的键盘输入。我只是想知道为什么我不能使用键盘在循环2中输入任何内容,而EOF
只是继续从fgets()
流中检索5个字符并将多余的数据留在文件流中以供下次检索。我对stdin
或stdin
有任何误解吗?谢谢你的时间!
答案 0 :(得分:1)
fgets()仅在'\ n'或EOF之前读取。之后的所有内容都将留在stdin中,因此当您再次调用fgets()时会被读取。但是,您可以通过使用getc()从stdin中删除多余的字符,直到达到\ 0。您可能需要查看联机帮助页。
答案 1 :(得分:1)
无论你问什么,fgets()
的手册页都有。只需要正确阅读它,它说
char *fgets(char *s, int size, FILE *stream);
fgets()最多只读取比
更少 来自流并将它们存储到s指向的缓冲区中。读 在 EOF或换行符后停止。如果读取换行符,则为 存储在缓冲区中。存储终止空字节(aq \ 0aq) 在缓冲区中的最后一个字符之后。
如果输入为aaaabbbb
且在fgets()
第二个参数中,您指定的大小为6
,即它将读取少一个5
字符,并且终止\0
将是已添加第一次inputBuff
保留aaaab
,因为仍然EOF
或\n
未发生,因此下次inputBuff
保留bbb\n
为新行也最后存储。
此外,您应该检查fgets()
的返回类型并检查是否发生\n
然后打破循环。例如
char *ptr = NULL;
while( (ptr = fgets(inputBuff, 6, stdin))!= NULL){
if(*ptr == '\n')
break;
printf("%s", inputBuff);
}
答案 2 :(得分:1)
你的程序的行为比你期望的更微妙:
fgets(inputBuff, 6, stdin)
从stdin
读取最多5个字节,并在获取换行符时停止读取,换行符存储在目标数组中。
因此,当您正确诊断时,第一个调用读取5个字节aaab
并打印它们,第二个调用读取4个字节bbb\n
并打印它们,然后第三个调用获取一个空输入流等待用户输入。
棘手的部分是stdin
如何从用户那里获得输入,也称为控制台输入。
默认情况下,控制台输入和stdin
通常都是行缓冲,因此无论传递给fgets()
的缓冲区大小如何,都可以输入完整的输入行。然而,如果您可以将stdin
设置为未缓冲且控制台输入为未烹饪,则第一个fgets()
确实会在您输入后立即读取前5个字节。
控制台输入是一个复杂的主题。这是一篇关于其内部运作的深入文章:https://www.linusakesson.net/programming/tty/