【问题标题】:Why doesn't multiple `\n` characters end up in the standard input stream?为什么标准输入流中没有多个 `\n` 字符?
【发布时间】:2015-01-13 14:58:21
【问题描述】:

这个问题一直困扰着我。考虑以下程序:

#include <stdlib.h>
#include <stdio.h>

int main(void){

  char one,mid,final;
  int num;

  printf("Enter the first character:\n");
  scanf("%c",&one);

  printf("Enter any integer:\n");
  scanf("%d",&num);

  printf("Enter the middle character:\n");
  scanf("%c",&mid);

  printf("Enter the final character:\n");
  scanf("%c",&final);

  printf("You have entered\n");
  printf("\"%c\" and \"%d\" and \"%c\" and \"%c\"\n",one,num,mid,final);

  return EXIT_SUCCESS;
}

假设输入是

A\n
34\n
B\n

这里,

第一个scanf 得到A 并将\n 留在stdin 中。
第二个nd 不考虑\n,因为%d 跳过它们,因此得到34。这个scanf 还在stdin 中留下\n 字符。
第三个rdscanf 得到第二个scanf 剩下的\n
第 4 个scanf 得到B 并再次将\n 留在stdin 中。

我的问题是:为什么最后一个 scanf 不消耗第一个 scanf 留下的 \n 字符?

【问题讨论】:

  • 第二次 scanf 调用确实消耗了第一次调用中的\n。它只是丢弃它,并继续阅读。
  • 所以%d 在扫描整数之前会吞噬所有空白字符?
  • @mafso, scanf 在循环体中刷新stdin,以防第二个scanf 失败。 scanf 不是第一个、第二个、第三个或第四个scanf。这可能会让未来的读者感到困惑,因此我将其删除。
  • 这是一个改进,谢谢。但仍然:为什么应该第四个scanf消耗第一个留在输入流中的东西?
  • @CoolGuy:是的,%d 转换说明符告诉scanf 使用并忽略任何前导空格,包括换行符。实际上,告诉scanf 使用前导空格的唯一转换说明符是%c%[ 转换说明符。请注意,格式字符串中的空格也会消耗空格,因此您可以通过编写scanf( " %c", &amp;c ); 来避免您的问题(注意%c 之前的空格)。

标签: c newline stdin scanf


【解决方案1】:

跳过的字符不在流中的“左侧”。输入流只能在一个方向上读取一次,1 所以一旦跳过一个字符,它就消失了。

1 没有额外的花哨,例如缓冲

【讨论】:

  • 啊,谢谢你解决了我的疑问。你的回答真的很有帮助!
  • @Matt Ball 尝试setvbuf(stdin,NULL,_IONBF,0); int c; char ch; scanf("%d", &amp;c); scanf("%c", &amp;ch); printf("%d\n", ch); 并输入“-x”。我的 GCC 打印 45(ASCII '-')。第一个scanf() 读取'-''x',没有形成一个int 并将它们都放回下一个scanf()。 IOW:在某些特定情况下,char 可能会被多次读取。
  • @chux 谢谢。不幸的是,我无法删除此答案,因为它已被接受。随意(大量)编辑我的答案,或发布您自己的答案并说服 OP 接受您的答案。
  • @chux ,您到了那里的观察非常好。我应该对此发布一个新问题吗?
  • @Cool Guy 不需要新问题(反正它很可能是个骗子)。 scanf() 是 C 中最复杂的函数 - 很少使用它,更喜欢 fgets()sscanf()strtol() 等。
猜你喜欢
  • 1970-01-01
  • 2015-11-19
  • 2011-08-30
  • 2023-02-23
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 2019-09-15
相关资源
最近更新 更多