当我从命令行使用stdin
命令将文件重定向到MyProgram < cl.txt
时,scanf
并没有等我按Enter键。
但是当我在程序中使用scanf
而没有这样做时,它会一直阻塞,直到按下回车键。
它究竟是如何确定的?在遇到\n
之前,它是否继续阅读流?还是真的等我按一个键?
当我没有写任何内容并按Enter键时,它也不会停止阻止并继续询问。我真的很困惑。
答案 0 :(得分:6)
scanf
只是从其输入流中读取。如果输入流是管道,并且该管道的另一端与tty相关联(如果您通过按键盘上的键以交互方式输入数据,通常就是这种情况),scanf将在读取数据后立即返回完成其格式字符串(或无法匹配)。然而,tty,如果它处于熟模式(这是默认模式,除非你努力将tty放入原始模式,你应该假设它正在烹饪你输入的内容),不会将任何数据写入管道直到你回来。
换句话说,这不是你的scanf阻塞。 (好吧,它阻塞,但它不是经验延迟的来源。)相反,tty驱动程序在等待你将任何数据传递给你的程序之前点击返回。
答案 1 :(得分:5)
是否继续阅读流,直到&#39; \ n&#39;遇到了什么?
通常stdin
处于线缓冲模式(_IOLBF
,请参阅setvbuf)。只要缓冲区为空,stdin就会等待输入一个全新的行,即等到你按Enter键并将\n
插入缓冲区:
On Input,当请求输入操作且缓冲区为空时,缓冲区将填充到下一个换行符。
注意:控制台(终端)通常自己实现缓冲,并且在您按Enter键之前不会向流发送任何数据 - 这允许您编辑数据(如使用删除和退格键)在将它们发送到应用程序之前。因此,即使stdin
方没有缓冲(例如,当您执行setvbuf(stdin, NULL, _IONBF, 0)
时),scanf
可能仍会等到按下Enter键。
答案 2 :(得分:2)
当您调用scanf时,它会立即等待输入。在第一个示例中,输入以“cl.txt”的形式提供。在第二个示例中,在按下某个键之前不会提供任何输入。同步IO将阻塞其正在执行的线程,直到它收到输入。