关于同时使用 fgets() 和 stdin 的机制
About the mechanism of using fgets() and stdin together
我想更好地理解 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
包含bbb\n
,然后被打印出来。
循环 3: 当文件流已到达末尾时,程序将要求我输入(第二次)(EOF
)。
问题: 似乎 fgets()
只会在 stdin
流没有数据留在缓冲区后才要求我的键盘输入(EOF
).我只是想知道为什么我不能在循环 2 中使用键盘输入任何内容,而 fgets()
只是继续从 stdin
流中检索 5 个字符并将多余的数据留在文件流中以供下次检索.我对stdin
或fgets()
有什么误解吗?感谢您的宝贵时间!
fgets()
只读到 '\n'
或 EOF
。之后的所有内容都将保留在 stdin
中,因此当您再次调用 fgets()
时会被读取。但是,您可以从 stdin
中删除多余的字符,例如使用 getc()
直到达到 '[=17=]'
。您可能需要查看联机帮助页。
fgets()
手册页中的所有内容,无论您问什么。只需要正确阅读它,上面写着
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than sizecharacters
from stream and stores them into the buffer pointed to by s. Reading
stops after an EOF or a newline. If a newline is read, it is
stored into the buffer. A terminating null byte (aq[=26=]aq) is stored
after the last character in the buffer.
如果输入是 aaaabbbb
并且在 fgets()
第二个参数中您将大小指定为 6
即它将少读取一个 5
字符并终止 [=17=]
将被添加,所以第一次 inputBuff
保持 aaaab
并且由于仍然 EOF
或 \n
没有发生所以下一次 inputBuff
保持 bbb\n
作为最后也存储了新行。
你还应该检查 fgets()
的 return 类型并检查 \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 个字节。
控制台输入是一个复杂的主题。这是一篇关于其内部工作原理的深入文章:https://www.linusakesson.net/programming/tty/
我想更好地理解 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
包含bbb\n
,然后被打印出来。
循环 3: 当文件流已到达末尾时,程序将要求我输入(第二次)(EOF
)。
问题: 似乎 fgets()
只会在 stdin
流没有数据留在缓冲区后才要求我的键盘输入(EOF
).我只是想知道为什么我不能在循环 2 中使用键盘输入任何内容,而 fgets()
只是继续从 stdin
流中检索 5 个字符并将多余的数据留在文件流中以供下次检索.我对stdin
或fgets()
有什么误解吗?感谢您的宝贵时间!
fgets()
只读到 '\n'
或 EOF
。之后的所有内容都将保留在 stdin
中,因此当您再次调用 fgets()
时会被读取。但是,您可以从 stdin
中删除多余的字符,例如使用 getc()
直到达到 '[=17=]'
。您可能需要查看联机帮助页。
fgets()
手册页中的所有内容,无论您问什么。只需要正确阅读它,上面写着
char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than sizecharacters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (aq[=26=]aq) is stored after the last character in the buffer.
如果输入是 aaaabbbb
并且在 fgets()
第二个参数中您将大小指定为 6
即它将少读取一个 5
字符并终止 [=17=]
将被添加,所以第一次 inputBuff
保持 aaaab
并且由于仍然 EOF
或 \n
没有发生所以下一次 inputBuff
保持 bbb\n
作为最后也存储了新行。
你还应该检查 fgets()
的 return 类型并检查 \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 个字节。
控制台输入是一个复杂的主题。这是一篇关于其内部工作原理的深入文章:https://www.linusakesson.net/programming/tty/