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

时间:2017-01-10 09:38:47

标签: c double scanf

scanf("%lf",&b);
fgets(str, 100, stdin);

在上面的代码中,在fgets之后添加空格(例如%lf)之前,不会读取scanf("%lf ",&b);, 或者在终端中按 ctrl-d 而不是输入。为什么会这样?

2 个答案:

答案 0 :(得分:0)

不要混用fgets()scanf()

scanf()会留下一个换行符(当您按下ENTER键时)会在fgets()输入读取后fgets(),只要它看到一个换行符,就会有效地为{{1} scanf("%lf ",&b);不读任何东西。

fgets()

  

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

如果格式字符串(fgets())中有空格,则只有在输入非空格后才会返回scanf调用,然后{{1}}调用将读取该空格。这种方法容易出错。因为如果你不进一步阅读,你将被迫输入一些内容。

请参阅:fgets()

答案 1 :(得分:0)

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

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

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

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