`
VincentZheng
  • 浏览: 51477 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

【转】C/C++ 误区二:fflush(stdin)

    博客分类:
  • C
阅读更多
1.为什么 fflush(stdin) 是错的

首先请看以下程序:
#include<stdio.h>

int main( void )
{
    int i;
    for (;;) {
        fputs("Please input an integer: ", stdout);
        scanf("%d", &i);
        printf("%d\n", i);
    }
    return 0;
}

这个程序首先会提示用户输入一个整数,然后等待用户输入,如果用户输入的是整数,程序会输出刚才输入的整数,并且再次提示用户输入一个整数,然后等待用户输入。但是一旦用户输入的不是整数(如小数或者字母),假设 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) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(gcc3.2不支持),因为标准中根本没有定义 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函数将把任何未被写入的数据写入stream指向的文件(如标准输出文件stdout)。否则,fflush函数的行为是不确定的。fflush(NULL)清空所有输出流和上面提到的更新流。如果发生写错误,fflush函数会给那些流打上错误标记,并且返回EOF,否则返回0。

由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。故而使用 fflush(stdin) 是不正确的,至少是移植性不好的。

2.清空输入缓冲区的方法

虽然不可以用 fflush(stdin),但是我们可以自己写代码来清空输入缓冲区。只需要在 scanf 函数后面加上几句简单的代码就可以了。
/* C 版本 */
#include<stdio.h>

int main( void )
{
    int i, c;
    for (;;) {
        fputs("Please input an integer: ", stdout);
        if ( scanf("%d", &i) != EOF ) { /* 如果用户输入的不是 EOF */
            /* while循环会把输入缓冲中的残留字符清空 */
            /* 读者可以根据需要把它改成宏或者内联函数 */
            /* 注:C99中也定义了内联函数,gcc3.2支持 */
            while ( (c=getchar()) != '\n' && c != EOF ) {
                  ;
            } /* end of while */
        }
        printf("%d\n", i);
    }
    return 0;
}

/* C++ 版本 */
#include <iostream>
#include <limits>  // 为了使用numeric_limits

using std::cout;
using std::endl;
using std::cin;

int main( )
{
	int value;
	for (;;) {
		cout << "Enter an integer: ";
		cin >> value;
		/* 读到非法字符后,输入流将处于出错状态,
		 * 为了继续获取输入,首先要调用clear函数
		 * 来清除输入流的错误标记,然后才能调用
		 * ignore函数来清除输入缓冲区中的数据。 */          
		cin.clear( );
		/* numeric_limits<streamsize>::max( ) 返回缓冲区的大小。
		 * ignore 函数在此将把输入缓冲区中的数据清空。
		 * 这两个函数的具体用法请读者自行查询。 */
		cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );
		cout << value << '\n';
	}
	return 0;
}

参考资料:

ISO/IEC 9899:1999 (E) Programming languages — C 7.19.5.2 The fflush function
The C Programming Language 2nd Edition By Kernighan & Ritchie
ISO/IEC 14882(1998-9-01)Programming languages — C++
分享到:
评论

相关推荐

    免费下载:C语言难点分析整理.doc

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    c语言难点分析整理,C语言

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    C语言难点分析整理.doc

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 ...

    高级C语言 C 语言编程要点

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    C语言难点分析整理

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    史上最强的C语言资料

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    高级C语言详解

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    高级进阶c语言教程..doc

    68. C/C++ 误区二:fflush(stdin) 376 69. C/C++ 误区三:强制转换 malloc() 的返回值 380 70. C/C++ 误区四:char c = getchar(); 381 71. C/C++ 误区五:检查 new 的返回值 383 72. C 是 C++ 的子集吗? 384 73. C...

    C标准库源代码(学习C/C++必备)

    C标准库源代码\FFLUSH.C C标准库源代码\FGETC.C C标准库源代码\FGETCHAR.C C 标准库源代码\FGETPOS.C C标准库源代码\FGETS.C C标准库源代码\FGETWC.C C标准库源代码\FGETWCHR.C C标准库源代码\FGETWS.C C标准库源...

    教师管理系统(c/c++)

    fflush(stdin);//清空缓存,以便不影响后面的输入 scanf("%d",&i); fflush(stdin); if(i==0) { printf("是否保存更改?1:是 0:否\t"); scanf("%d",&s); fflush(stdin); if(s==1) save(); exit(0); } ...

    C/C++ 拳皇争霸

    fflush(stdin); gets(name); if(Checktoseek(name)==-1) { strcpy(player[n].name,name); player[n].Hp=rand()%1000; player[n].AP=rand()%(100+1)+50; player[n].Dp=rand()%(10-5+2)+5; player[n].Rp...

    C/C++实现控制台输出不同颜色字体的方法

    主要介绍了C/C++实现控制台输出不同颜色字体的方法,涉及C++控制台文字属性相关设置操作技巧,需要的朋友可以参考下

    c/c++函数库说明(api)html版

    所有的 C / C++ 函数 Constructors (cppstring) Constructors (cppvector) Operators (cppbitset) Operators (cppdeque) Operators (cppstack) Operators (cppstring) Operators (cppvector) abort (stdother...

    通讯录管理系统C++

    以下是部分源码: #include #include #include #include #include using namespace std; class book { public: book();//默认构造函数 ... ※ 1.... ※ 2.... ※ 3.... fflush(stdin); return choose; }

    C++简单日志类 仅供参考 上次上传的那个忘了fflush(hf);

    简单C++类: void My_Log::Write_Log(const char *szFormat, ...) { FILE *hf = NULL; va_list ap; if(!szLogFile[0]) return; hf = fopen(szLogFile, "a"); if(!hf) return; va_start(ap, szFormat); ...

    关于fflush关于fflush关于fflush关于fflush

    关于fflush关于fflush关于fflush关于fflush关于fflush关于fflush关于fflush关于fflush

    长整数加法代码C++

    长整数加法,c++ //创建链表 l_store r_store(l_store h) //带头结点 { int flag=0; //flag 用来标识整数的符号 0表示 '+' 1表示 '-' ... fflush(stdin); //刷新输入缓冲区 while(ch!='\n') {

    file@libc.zip_file operations c_ftell

    C语言文件操作函数集(功能描述、示例代码),如fopen/fclose/fileno/ftell/fflush等。

    C语言的用法

    taxainxide miaoshu fflush stdin 的用法

    基于C语言fflush()函数的使用详解

    fflush(stdout)这个例子可能不太明显,但对stdin很明显。 如下语句: int a,c; scanf(“%d”,&a); c=getchar(); 输入: 12(回车) 那么 a=12 ,c= ‘\n’ 而: int a,c; scanf(“%d”,&a); fflush(stdin); c=getchar...

Global site tag (gtag.js) - Google Analytics