scanf()将新行char留在缓冲区中


87

我有以下程序:

int main(int argc, char *argv[])
{
  int a, b;
  char c1, c2;
  printf("Enter something: ");
  scanf("%d",&a); // line 1
  printf("Enter other something: ");
  scanf("%d", &b); // line 2

  printf("Enter a char: ");
  scanf("%c",&c1); // line 3
  printf("Enter another char: ");
  scanf("%c", &c2); // line 4

  printf("Done"); // line 5

  system("PAUSE");

  return 0;
}

正如我在C书籍中所读到的那样,作者说scanf()在缓冲区中保留了一个新行字符,因此,该程序不会在用户输入数据的第4行处停止,而是将新行字符存储在c2中并移至第5行

那正确吗?

但是,这仅在char数据类型上发生吗?因为我没有int在第1、2、3行中看到此数据类型的问题,对吗?


有时建议fflush(stdin)可以在调用scanf()单个字符之前使用它。请阅读“使用fflush(stdin)”以讨论该方法的优缺点和替代方法(该方法或多或少在Windows上有效,而在大多数其他地方则无效)。
乔纳森·莱夫勒

您能告诉我们您指的是哪本书吗?
surya kiran

Answers:


78

scanf()函数会在尝试解析字符以外的转换之前自动跳过前导空格。字符格式(主要是%c;还有扫描集%[…]—和%n)是例外。他们不会跳过空格。

" %c"与前导空白一起使用可跳过可选的空白。不要在scanf()格式字符串中使用尾随空白。

请注意,这仍然不会消耗输入流中剩余的任何空格,甚至不会占用行尾,因此请注意如果在同一输入流上使用getchar()fgets()在其上也要留白。就像转换和其他非字符转换一样,我们只是让scanf跳过转换前的空白%d


请注意,除了转换外,非空格“指令”(使用POSIX scanf术语)也不同于转换,例如中的文字文本scanf("order = %d", &order);也不会跳过空格。文字order必须匹配下一个要读取的字符。

因此" order = %d",如果您想从上一行跳过换行符,但仍要求在固定字符串上进行文字匹配,则可能需要在此处,例如this Question


7
%c%n%[]是不消耗前导空格3个指定的期望。
chux-恢复莫妮卡2015年

@chux在其他情况下,scanf会在缓冲区中之前清除所有空白,还是忽略它们的输入,但它们仍然存在?
Suraj Jain

@SurajJain是的,
恢复莫妮卡的时间

3
请参阅scanf()格式字符串中尾随空白scanf()两次询问输入,而我希望它仅询问一次以格式字符串尾随空白的讨论。他们是一个坏主意-如果您期望人与人之间的互动,那么这将是非常糟糕的,而对于程序互动则是不利的。
乔纳森·莱夫勒

31

使用scanf(" %c", &c2);。这样可以解决您的问题。


7

另一个选项(我从这里得到)是通过使用assignment-supression选项读取和丢弃换行符。为此,我们只需输入一种格式即可读取介于%和之间带有星号的字符c

scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3

scanf 然后将读取下一个字符(即换行符),但不将其分配给任何指针。

最后,我将选择FAQ的最后一个选项

或者,根据您的要求,您也可能会忘记scanf()/ getchar(),使用fgets()从用户那里获取一行文本并自行解析。


2
这种技术的问题在于,如果用户a先输入空格然后换行,则被抑制的字符转换将读取空格并仍然保留换行符。如果用户按supercalifragilisticexpialidocious您的期望进行输入a,那么您将需要处理许多额外的字符。您也永远无法判断尾随抑制转换是否成功-从的返回中不计入转换scanf()
乔纳森·莱夫勒

3

getchar()在调用第二个之前使用scanf()

scanf("%c", &c1);
getchar();  // <== remove newline
scanf("%c", &c2);

1
如果用户没有输入其他任何内容(例如,尾随空格),则此方法有效。但这不如扫描到下一个换行符的循环好:(int c; while ((c = getchar()) != EOF && c != '\n') ;不在注释中时,写成三行)。通常就足够了;它不是万无一失的(您必须记住,傻瓜对崩溃的东西非常聪明)。
乔纳森·勒夫勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.