由scanf("%d",&ch);引出的输入缓冲区问题
2013-03-05 17:02
197 查看
刚才一个朋友发了一段代码:
#include<stdio.h>
int main(void)
{
int i;
char c;
for(i=0;i<5;i++)
{
scanf("%d",&c);
printf("i=%d\r\n",i);
}
printf("The loop is finished!\r\n");
return 0;
}
问为什么输入一个数字,可以连续输入5次,而输入字符就只能输入一次循环就结束了呢?
这其实是输入流缓冲区的问题,刚才在网上找到一篇与这个问题相关的文章,把它贴在下面。同时这篇文章还提出了清除缓冲区的方法,放在这里以备后用。
*************************下文转自雨中飞燕博客**************************
1.为什么fflush(stdin) 是错的
首先请看以下程序:
Code
这个程序首先会提示用户输入一个整数,然后等待用户输入,如果用户输入的是整数,程序会输出刚才输入的整数,并且再次提示用户输入一个整数,然后等待用户输入。但是一旦用户输入的不是整数(如小数或者字母),假设 scanf 函数最后一次得到的整数是 2 ,那么程序会不停地输出“Please input an integer: 2”。这是因为scanf("%d", &i);只能接受整数,如果用户输入了字母,则这个字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而 scanf 函数不会等待用户输入,直接就去缓冲中读取,可是缓冲中的却是字母,这个字母再次被遗留在缓冲中,如此反复,从而导致不停地输出“Please
input an integer: 2”。也许有人会说:“居然这样,那么在 scanf 函数后面加上‘fflush(stdin);’,把输入缓冲清空掉不就行了?”然而这是错的!C和C++的标准里从来没有定义过 fflush(stdin)。也许有人会说:“可是我用 fflush(stdin) 解决了这个问题,你怎么能说是错的呢?”的确,某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(linux 下的 gcc 就不支持),因为标准中根本没有定义 fflush(stdin)。MSDN
文档里也清楚地写着fflush on input stream is an extension to the C standard(fflush 操作输入流是对 C 标准的扩充)。当然,如果你毫不在乎程序的移植性,用 fflush(stdin) 也没什么大问题。以下是 C99 对 fflush 函数的定义:
int fflush(FILE *stream);
如果 stream 指向输出流或者更新流(update stream),并且这个更新流最近执行的操作不是输入,那么 fflush 函数将把这个流中任何待写数据传送至宿主环境(host environment)写入文件。否则,它的行为是未定义的。
原文如下:
int fflush(FILE *stream);
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior
is undefined.
其中,宿主环境可以理解为操作系统或内核等。
由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。
故而使用 fflush(stdin) 是不正确的,至少是移植性不好的。
2.清空输入缓冲区的方法
虽然不可以用 fflush(stdin),但是我们可以自己写代码来清空输入缓冲区。只需要在 scanf 函数后面加上几句简单的代码就可以了
#include<stdio.h>
int main(void)
{
int i;
char c;
for(i=0;i<5;i++)
{
scanf("%d",&c);
printf("i=%d\r\n",i);
}
printf("The loop is finished!\r\n");
return 0;
}
问为什么输入一个数字,可以连续输入5次,而输入字符就只能输入一次循环就结束了呢?
这其实是输入流缓冲区的问题,刚才在网上找到一篇与这个问题相关的文章,把它贴在下面。同时这篇文章还提出了清除缓冲区的方法,放在这里以备后用。
*************************下文转自雨中飞燕博客**************************
1.为什么fflush(stdin) 是错的
首先请看以下程序:
Code
这个程序首先会提示用户输入一个整数,然后等待用户输入,如果用户输入的是整数,程序会输出刚才输入的整数,并且再次提示用户输入一个整数,然后等待用户输入。但是一旦用户输入的不是整数(如小数或者字母),假设 scanf 函数最后一次得到的整数是 2 ,那么程序会不停地输出“Please input an integer: 2”。这是因为scanf("%d", &i);只能接受整数,如果用户输入了字母,则这个字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而 scanf 函数不会等待用户输入,直接就去缓冲中读取,可是缓冲中的却是字母,这个字母再次被遗留在缓冲中,如此反复,从而导致不停地输出“Please
input an integer: 2”。也许有人会说:“居然这样,那么在 scanf 函数后面加上‘fflush(stdin);’,把输入缓冲清空掉不就行了?”然而这是错的!C和C++的标准里从来没有定义过 fflush(stdin)。也许有人会说:“可是我用 fflush(stdin) 解决了这个问题,你怎么能说是错的呢?”的确,某些编译器(如VC6)支持用 fflush(stdin) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(linux 下的 gcc 就不支持),因为标准中根本没有定义 fflush(stdin)。MSDN
文档里也清楚地写着fflush on input stream is an extension to the C standard(fflush 操作输入流是对 C 标准的扩充)。当然,如果你毫不在乎程序的移植性,用 fflush(stdin) 也没什么大问题。以下是 C99 对 fflush 函数的定义:
int fflush(FILE *stream);
如果 stream 指向输出流或者更新流(update stream),并且这个更新流最近执行的操作不是输入,那么 fflush 函数将把这个流中任何待写数据传送至宿主环境(host environment)写入文件。否则,它的行为是未定义的。
原文如下:
int fflush(FILE *stream);
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior
is undefined.
其中,宿主环境可以理解为操作系统或内核等。
由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。
故而使用 fflush(stdin) 是不正确的,至少是移植性不好的。
2.清空输入缓冲区的方法
虽然不可以用 fflush(stdin),但是我们可以自己写代码来清空输入缓冲区。只需要在 scanf 函数后面加上几句简单的代码就可以了
相关文章推荐
- 由scanf("%d",&ch);引出的输入缓冲区问题
- scanf("%c",&ch);不接受输入
- 由while(scanf("%d",&n)!=EOF)引出的小问题
- scanf("%c",&ch)直接跳过的问题
- 由while(scanf("%d",&n)!=EOF)引出的小问题
- c语言scanf()停止接受输入及scanf("%c",&c)吃掉回车或者空格字符的问题
- 关于scanf("%c",&ch)直接跳过的问题
- 嵌入式 关于scanf("%c",&ch)实现拦截时候出现直接跳过的问题
- scanf引出的输入缓冲区问题
- 关于 cgdb & gdbtui 的输入scanf()问题
- NET中"无法显示 XML 页。 使用 XSL 样式表无法查看 XML 输入。"问题的解决
- 一个字符变量存储到动态分配内存引发的输入问题解决--连续输入scanf函数存在缓冲区的问题
- scanf("%d\n",&a);中\n带来的问题的解释
- 浮点库的连接问题(针对有的时候scanf("%f",&fn);出现的异常)
- Delphi2009输入"."后不出现助记输入选择框的问题!
- c语言中scanf("%c",&c)吃掉回车或者空格字符的问题
- 关于输入scanf()中缓冲区的几个问题
- scanf(), getchar(), 以及gets(),空白符以及输入缓冲区的问题
- C语言学习笔记——scanf("%c",&ch) 读取字符
- Linux下无法输入"\"和"|"的问题