为什么在从scanf读取数据时必须按ctrl-d键?

为什么在从scanf读取数据时必须按ctrl-d键?,c,double,scanf,C,Double,Scanf,在上面的代码中,fgets直到我在%lf后面添加一个空格后才被读取(例如scanf(“%lf”,&b);), 或者在终端中按ctrl-d键而不是按enter键。为什么会这样?不要把fgets()和scanf()混为一谈 scanf()留下一个换行符(当您按ENTER键时),它会在看到换行符时立即终止对fgets()的输入读取,实际上您的fgets()根本不读取任何内容 : fgets()从流中最多读取一个小于大小的字符 并将它们存储到s指向的缓冲区中。阅读结束后停止 EOF或换行符。如果读取换行

在上面的代码中,
fgets
直到我在
%lf
后面添加一个空格后才被读取(例如
scanf(“%lf”,&b);
), 或者在终端中按ctrl-d键而不是按enter键。为什么会这样?

不要把
fgets()
scanf()混为一谈

scanf()
留下一个换行符(当您按ENTER键时),它会在看到换行符时立即终止对
fgets()
的输入读取,实际上您的
fgets()
根本不读取任何内容

:

fgets()从流中最多读取一个小于大小的字符 并将它们存储到s指向的缓冲区中。阅读结束后停止 EOF或换行符。如果读取换行符,它将存储到 缓冲器终止的空字节('\0')存储在最后一个字节之后 缓冲区中的字符

如果格式字符串中有空格(
scanf(“%lf”,&b);
),scanf调用将仅在输入非空格后返回,然后由
fgets()
调用读取。这种方法容易出错。因为如果你不进一步阅读,你将被迫输入一些东西

请参阅:

scanf(“%lf”,…)
在输入中遇到空白时,将停止并等待更多输入。在格式字符串中添加空格会导致从
stdin
中删除空白字符,并返回函数

另一种导致
scanf()
返回的方法是让它识别某种形式的错误。一种方法是让它看起来好像已经到达了文件的末尾。您还没有提到它,但是您的主机系统是unix的一种风格——键入CTRL-D(取决于终端设置,您可能需要在换行后按CTRL-D,或者可能输入两次),这使它看起来好像遇到了文件结尾。如果从
scanf()
检查返回值,在这种情况下,它也将返回
EOF
。不同的系统需要不同的操作来触发文件结束

无论哪种方式,
fgets(…,stdin)
都无法调用,直到
scanf()
返回。请注意,触发文件结束(取决于终端设置)也可能导致
fgets(…,stdin)
返回
EOF
(即它不一定读取输入)


在同一个流上(
stdin
)混合使用
scanf()
(或相关函数)和
fgets()
,这是一个非常糟糕的主意,因为它们确实以奇怪的方式交互(每个都依赖于与另一个不提供的流交互的行为)

可能重复您得到的拿铁咖啡答案,因为您的问题没有标记
c
,因此没有引起注意,今后请适当标记您的问题。好的,或者只有在阅读并理解相应的手册页,以及您的终端,可能还有壳牌的,以及;不幸的是,手动终端I/O是一个棘手的问题,由于某些原因,它往往发生在初学者的练习中,而不是在现实生活中。在现实生活中,您可以为GUI编程(具有完全不同的问题,但通常也同样棘手);或者你可能不必为人工或控制台问题而烦恼。我不喜欢这个链接的标题。我从15岁起就开始使用scanf()。如果有人应该理解复杂的编程概念,那么他们也应该能够理解scanf()是如何工作的。虽然一个人如果完全理解任何C函数(或语言),就可以正确地使用它,
scanf()
被认为是可以理解的。这是许多人长期持有的观点,有充分的理由。史蒂夫·萨米特可能在90年代初写下了这本书,但它是相关的,仍然适用。
scanf("%lf",&b);
fgets(str, 100, stdin);