快速业务通道

C/C++ 误区二:fflush(stdin)

作者 佚名技术 来源 程序设计 浏览 发布时间 2012-06-29

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) 来清空输入缓冲,但是并非所有编译器都要支持这个功能(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 函数后面加上几句简单 的代码就可以了。

/* C 版本 */
#include <stdio.h>


int main( void )
{
int i, c;
for ( ; ; )
{
fputs("Please input an integer: ", stdout);
scanf("%d", &i);

if ( feof(stdin) || ferror(stdin) )
{ /* 如果用户输入文件结束标志(或 文件已被读完), */
/* 或者发生读写错误,则退出循环 */

/* do something */
break;
}
/* 没有发生错误,清空输入流。 */
/* 通过 while 循环把输入流中的余留数据“吃”掉 */
while ( (c = getchar()) != ''\n'' && c != EOF ) ;
/* 使用 scanf("%*[^\n]"); 也可以清空输入流, */

/* 不过会残留 \n 字符

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号