C 关于fgets()和stdin一起使用的机制

C 关于fgets()和stdin一起使用的机制,c,stdin,fgets,C,Stdin,Fgets,我想更好地了解如何使用fgets()和stdin。 以下是我的代码: int main() { char inputBuff[6]; while(fgets(inputBuff, 6, stdin)) { printf("%s", inputBuff); } return 0; } 假设我的输入是aaaabbbb,然后按Enter键。通过使用loopcount,我了解到在下一次输入之前,实际上循环将运行两次(包括我输入的那一次) 循环1:

我想更好地了解如何使用
fgets()
stdin
。 以下是我的代码:

int main()
{
    char inputBuff[6];
    while(fgets(inputBuff, 6, stdin))
    {
        printf("%s", inputBuff);
    }
    return 0;
}
假设我的输入是
aaaabbbb
,然后按Enter键。通过使用loopcount,我了解到在下一次输入之前,实际上循环将运行两次(包括我输入的那一次)

循环1:键入字符后,
aaaabbbbb\n
将存储在
stdin
文件流的缓冲区中。而
fgets()
将从文件流中检索特定数量的数据,并将它们放入
inputBuff
。在这种情况下,它将一次检索5(6-1)个字符。这样,当
fgets()
已经运行一次时,
inputBuff
将存储
aaaab
,然后进行打印

循环2:然后,由于
bbb\n
留在文件流中,
fgets()
将第二次执行,以便
inputBuff
包含
bbb\n
,然后被打印

循环3:当文件流到达末尾(
EOF
)时,程序将请求我的输入(第二次)


问题:似乎
fgets()
只会在
stdin
流的缓冲区中没有剩余数据(
EOF
)之后才要求我输入键盘。我只是想知道为什么我不能使用键盘在循环2中输入任何内容,而
fgets()
只需继续从
stdin
流中检索5个字符,并将多余的数据保留在文件流中以备下次检索。我对
stdin
fgets()
有任何误解吗?谢谢你抽出时间

fgets()
只在
'\n'
EOF
之前读取。之后的所有内容都将保留在
stdin
中,因此在再次调用
fgets()
时将被读取。但是,您可以从
stdin
中删除多余的字符,例如使用
getc()
,直到到达
'\0'
。您可能需要查看手册页以了解这一点。

所有内容都在
fgets()的手册页中。
无论您要求什么。只需要正确地阅读它,它说

char*fgets(char*s,int-size,FILE*stream)

fgets()读取的字符数最多比sizecharacters少一个 并将它们存储到s指向的缓冲区中。阅读 在EOF或换行符后停止。如果读取了换行符,则为 存储到缓冲区中。存储一个终止的空字节(aq\0aq) 在缓冲区中最后一个字符之后

如果输入为
aaaabbbb
且在
fgets()中
您指定大小为
6
的第二个参数,即它将少读一个
5
字符,并将添加终止
\0
,因此第一次
inputBuff
保持
aaaaaab
,并且由于仍然
EOF
\n
没有出现,因此下次
inputBuff
保持
bbb\n
新行也最终被存储

此外,还应检查
fgets()
的返回类型,并检查
\n
是否发生,然后断开循环。例如

char *ptr = NULL;

while( (ptr = fgets(inputBuff, 6, stdin))!= NULL){
          if(*ptr == '\n')
                   break;
          printf("%s", inputBuff);
}

程序的行为比您预期的更微妙:

fgets(inputBuff,6,stdin)
stdin
读取最多5个字节,并在获取存储到目标数组中的换行符时停止读取

因此,当您正确诊断时,第一个调用读取5字节
aaab
并打印它们,第二个调用读取4字节
bbb\n
并打印它们,然后第三个调用获取一个空输入流并等待用户输入

棘手的部分是
stdin
如何从用户那里获取输入,也称为控制台输入

默认情况下,控制台输入和stdin
通常都是行缓冲的,因此无论传递给
fgets()
的缓冲区大小如何,都可以键入完整的输入行。但是,如果您可以将
stdin
设置为未缓冲,将控制台输入设置为未煮熟,那么第一个
fgets()
确实会在您键入前5个字节后立即读取它们


控制台输入是一个复杂的主题。下面是一篇关于其内部运作的深入文章:

现实在什么程度上偏离了你的预期还不太清楚。您能显示产生意外输出的输入吗?在Fine手册中:
fgets()从流中最多读取一个小于大小的字符,并将它们存储到s指向的缓冲区中。EOF或换行符后,读取停止。如果新行被读取,它将被存储到缓冲区中。“\0”存储在缓冲区中最后一个字符之后。
是否希望丢弃
“bbb\n”
,并请求新的输入?如果是这样的话,当一行的长度事先未知时,程序怎么能读取它呢?你说的“我只是想知道为什么我不能用键盘在循环2中输入任何东西,而fgets()只能继续从stdin流中检索5个字符…”到底是什么意思?您是否想在前一个字符串中间插入一些东西(在<代码> BBB\N/COD>之前),或者有<代码> FGES读取新行,或者什么?对不起,我有一些编码任务要做,所以我不能马上回复您的评论。很抱歉这么晚才回复@n、 没有,我没有收到任何意外的输出。只是想知道为什么“有时”每当调用fgets()时,我没有被要求输入某个内容。Thx提醒我需要添加一个条件以打破循环。“fgets()从流中最多读入一个小于sizecharacters的字符,并将它们存储到s指向的缓冲区中。读取在EOF或换行后停止。”这是否意味着fgets()在缓冲区中存储“aaaab”后还没有完成其“第一次”读取输入过程?