我是C语言的新手,正在尝试理解将fgets()
指向stdin
时发生了什么。
基本上我的问题是这样的,如果我在fgets()
中指定一个文件指针,则fgets()
会从该位置开始读取,直到遇到\n
、EOF
或指定的limit-1
为止。
那么,如果我将其指向stdin
,它为什么会表现不同呢?换句话说,是什么让它“等待”用户输入而不是简单地找不到可读取的内容然后返回NULL
呢?
谢谢您的时间。
fgets()
函数从参数流中读取数据。如果该流被绑定到设备或管道上,则会阻塞,直到从设备/管道获得输入或检测到文件结束。
stdin
通常与终端绑定。从终端读取任何挂起的输入,在fgets()
情况下,会一直读取,直到键入换行符或输入足够的字符。这里有一个额外的层次需要理解:终端的内核驱动程序默认执行自己的缓冲,即使键入的字符比fgets()
所期望的多,输入操作也会阻塞,直到键入换行符。这些额外的字符留在终端缓冲区中。
可以使用stty
系统调用(在Posix系统上)将终端配置为原始模式(而不是默认的熟悉模式)。这样做将删除设备驱动程序中的缓冲,但缓冲仍将在FILE *
流中执行。只有在执行此缓冲操作之后,fgets()
才能访问来自流的字符。通常,绑定到设备的流默认为行缓冲,导致流缓冲匹配设备驱动程序缓冲。如果将设备设置为原始模式并将流设置为无缓冲,则字符将在键入时对fgets()
可用,并且当其读取到换行符或已读取size-1
个字符时,fgets()
将停止读取。
还要注意,您可以通过在unix和OS/X系统上键入Control-D以及在Windows系统上键入Control-Z Enter来输入文件结束符。
scanf("%d", &n);
读取一个整数,则终端读取并发送到流中的其余行仍然在 stdin
流缓冲区中结束。fgets()
将读取它,并且不会从终端请求任何输入,因为它已经看到了挂起的换行符。 - chqrliefgets
是如何等待的呢?如果我指定 fgets
从一个空文件中读取,它将不会等待文件被填充任何内容。谢谢回答! - Stefanfgets
函数提供了一个阻塞读取,其含义取决于设备。文件通常被定义为“快速”设备,只等待硬件操作完成。终端、管道和套接字是“慢速”设备,可以等待事件发生。 - David Schwartzfgets
函数可以让你进行阻塞读取,具体意义取决于设备。 - David Schwartz
fmemopen
返回的FILE *
上,根据实现的不同,它可能不会等待。 - Daniel Jour