在C语言中,关于“清空输入缓冲区”的概念存在很多混乱。这种混淆几乎完全来自于流行但有缺陷的scanf
函数的一个奇怪事实:它通常不会读取完整的输入行,并且通常会在转换其输入后在输入流中保留换行符\n
。例如,如果您编写一个程序:
printf("Type a number:\n");
scanf("%d", &n);
如果用户输入"123"并按下回车键,则数字123将被存储在变量n中,但是对应于回车键的字符"\n"将留在输入流中。如果你的程序接下来要做的事情是调用fgets或getchar,想象一下你将开始读取用户输入的下一行,那么你的程序将立即读取剩余的换行符。看起来好像用户多输入了一行空白,或其他什么东西。
这个问题非常普遍。大量的初学者C程序员都会遇到这个问题。简而言之,有三种推荐的解决方法:
1.在调用像scanf这样保留输入缓冲区中换行符的函数之后,在调用期望从新行开始的函数如getchar或fgets之前,使用小循环while((c = getchar()) != '\n' && c != EOF)读取和丢弃scanf留在输入缓冲区中的换行符。
2.完全不使用scanf,或者如果你使用了,就不要尝试将它与调用getchar或fgets混合使用。
3.(普遍但严重有问题的)调用fflush(stdin)刷新不需要的输入。
第三种解决方案的问题已经被广泛讨论,所以我不会再多说那些问题或那个解决方案。推荐的“便携式”替代方法是第一种,但显然它只在至少有一个不需要的换行符在等待刷新时才有效。如果没有,解决方案1将错误地读取并丢弃所需输入的一行。
因此,你不能在程序的任何地方都使用解决方案1。你不能随意地在你的程序中添加它;你不能在可能使用fflush(stdin)的任何地方都使用它。通常情况下,如前所述,只有在调用scanf之后,在调用getchar或fgets之前才需要它。
在问题的代码片段中,可能根本不需要使用解决方案1。fgets函数完全能够干净地读取单独的输入行。不一定需要额外的输入清除或换行符丢弃。(然而,如果在do_something()下面调用了scanf,可能需要额外的换行符处理。)