【问题标题】:What signals to scanf to read?scanf 读取什么信号?
【发布时间】:2022-01-20 19:34:29
【问题描述】:

在接下来的 sn-p 中,读取 int 后,'\n' 保留在 stdin 中,并由第二个 scanf 读取。

是在输入时调用scanf,然后读取标准输入中的内容,还是在输入发生之前调用它?

scanf 输入准备就绪的信号是什么?例如,如果我在键盘上键入 12345,而 scanf 正在读取一个 int,则可以将其读取为 1、12、123 ... 如果输入是要读取的信号,为什么 scanf 不从标准输入中清除该字符?

#include <stdio.h>

int main()
{
    int a;
    scanf( "%d", &a );
    
    char b;
    scanf( "%c", &b );
    
    printf( "%d %c", a, b );
    return 0;
}

【问题讨论】:

  • 在sn-p中,b将读取a的条目留下的'\n'。要正确使用 " %c" 作为格式字符串,格式字符串中的前导空格将消耗空格('\n' 是空白,spacetab 等。)始终验证 scanf() 的返回.返回是发生的成功转换的数量。所以if (scanf ("%d", &amp;a) == 1) 你知道提供了一个有效的整数。 (除了检查 EOF 之外,不需要使用 "%c" 进行验证。)
  • 感谢您的回答! scanf 在 '\n' 之前调用,并等待它?
  • scanf 不使用尾随空格。上面的评论让您可以在下一次转换之前使用它。
  • 当您在输入a 的值后按[Enter] 时,会将'\n' 插入到输入流中。如果您没有考虑换行符 - 您的下一次尝试读取将读取 \n'。这也是鼓励您使用fgets() 获取所有用户输入的主要原因,这是一个足够大的缓冲区,然后使用sscanf() 从缓冲区解析任何需要的信息。 fgets() 将消耗尾随 '\n'
  • 所以任何空白都可以向 scanf 发出信号来读取?

标签: c scanf stdin


【解决方案1】:

scanf 有点像模式匹配函数。例如:

scanf("%d %f", &a, &b);

首先从左边开始寻找一个 int,忽略所有空格。如果在成功读取之前出现了一些意外字符,函数会立即返回。现在,字符串中的最后一个字符将是 read,然后 put back 以供下一次调用 scanf 读取。这就是为什么我们需要再次按下回车键来结束下一个调用,而没有读取任何其他内容。为了解决这个问题,我们可以对 即将到来的 scanf 调用进行模式匹配:

scanf(" %c", &c1);
  • 注意字符串前面的空格。这向scanf 表明,预计将匹配一个空白字符。

【讨论】:

  • 几乎 - "indicates to scanf that one whitespace character is expected to be matched" - 没有。它告诉scanf() 丢弃所有前导空格——不管有多少空格字符。
  • 更重要的是,我不确定 OP 是否理解 buffered I/O 的概念。 scanf 是“面向行的” - 在您点击“换行符”之前不会读取任何内容(或者除非您明确关闭缓冲)。因此他对“12345”感到困惑。
  • 您可以使用"... at least one ..." 进行更正。这将使它正确。来自man 3 scanf “一系列空白字符(空格、制表符、换行符等;参见 isspace(3))。该指令匹配输入中任意数量的空白,包括无空白。”
  • 这意味着(对于行缓冲输入)是当用户输入输入时,scanf() 不会在输入每个字符时对其进行处理。相反,每个字符都放置在内部读取缓冲区中(您无法控制),当按下 [Enter] 时,整行输入将传递给 scanf() 以进行匹配格式字符串scanf() 然后返回发生的成功转换次数,它告诉您是否所有您期望 scanf() 填充的变量都已填充。
  • 它在读取缓冲区中缓冲,然后以stdin 的形式提供。我将不得不查看 glibc 源以确定使用的缓冲区(我认为这并不重要),但你是正确的,它以stdin 的形式提供给程序。在过去的几年里,这个领域发生了一些变化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
相关资源
最近更新 更多