将其更改为:
fgets(loop, 4, stdin);
转换为:
fgets(loop, 5, stdin);
在将缓冲区大小设置为5之后,例如char loop[5]= "yes";
,为了存储单词“yes”的3个字符,换行符fgets()
将被读取(因为它正在读取行,对吧?),以及字符串的NULL终止符(如您所知)。
要解释您的代码行为,您必须理解@DavidBowling的评论:
请注意,通过使用fgets(loop, 4, stdin);
,当输入“yes”时,换行符会留在输入流中,因此下一个输入调用会获取此换行符。
使用此程序来证明这一点:
#include<stdio.h>
#include<string.h>
int main()
{
char loop[4]= "yes";
while(strcmp(loop,"yes")==0)
{
printf("Do you want to continue? [yes|no]: ");
fgets(loop, 4, stdin);
printf("|%s|\n",loop);
}
return 0;
}
输出:
Do you want to continue? [yes|no]: yes
|yes|
Do you want to continue? [yes|no]: |
|
这段文字涉及IT技术,讲述了换行符在标准输入(STDIN)缓冲区中被保留,并且会在第二次调用fgets()时被消耗。从该方法的参考资料中可以看出:
“从流中读取字符并将它们存储为C字符串到str中,直到读取了(num-1)个字符或达到换行符或文件末尾,以先到者为准。
在复制到str的字符后自动追加一个终止空字符。”
让我们逐步看看发生了什么:
您键入“yes”,然后按Enter键,这使得标准输入缓冲区如下所示:
| y | e | s | \n |
现在执行第一个对 fgets(loop, 4, stdin);
的调用,这意味着该方法将尝试从 STDIN 中读取 3(4-1)个字符。它读取了 y
、e
和 s
,将它们从 STDIN 的缓冲区移动到您声明的程序缓冲区 loop
中,然后附加字符串 NULL 终止符。
现在 STDIN 缓冲区为:
| \n | | | |
在用户输入之前,
fgets(loop, 4, stdin);
将被执行(这是方法的职责,因为它们是等待在STDIN缓冲区中被消耗的数据 - 如果没有数据,那么该方法会耐心地等待用户输入...)。
现在,它将换行符复制到
loop
中,并停止在那里,因为现在STDIN缓冲区为空,并最终将字符串NULL终止符附加到
loop
中(在索引1处)。
现在,STDIN缓冲区为空:
| | | | |
由于用户没有更多的输入,因此代码的流程在while循环之后移动,当loop
是以换行符作为其第一个字符的字符串时,循环条件求值为false。
PS:删除fgets()输入中的尾随换行符。
fgets
函数也希望读取换行符,并且只有四个字符的情况下没有足够的空间来存放它。 - Some programmer dudefgets
后,您需要删除行尾换行符。 - Weather Vanefgets(loop, 4, stdin);
时,在输入"yes"时会将换行符留在输入流中,因此下一个输入调用会捕捉到这个换行符。 - ad absurdum