注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

亮丽

一直想安静的过着安静的日子,安静的爱着爱我的人

 
 
 

日志

 
 
 
 

fflush函数小结及使用误区收藏  

2009-08-12 11:36:07|  分类: 编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

fflush函数小结及使用误区:

参考:http://www.ninstein.com/blog/article.asp?id=12

1、C99 对 fflush 函数的定义:

int fflush(FILE *stream);

如果stream指向输出流或者更新流(update stream),并且这个更新流最近执行的操作不是输入,那么fflush函数将把任何未被写入的数据写入stream指向的文件(如标准输出文件stdout)。否则,fflush函数的行为是不确定的。

fflush(NULL)清空所有输出流和上面提到的更新流。如果发生写错误,fflush函数会给那些流打上错误标记,并且返回EOF,否则返回0。

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

<stdio.h>,成功返回0,出错返回EOF。

2、使用注意点及误区

为什么 fflush(stdin) 是错的?

首先请看以下程序:

Quote:

程序代码 程序代码

#i nclude<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) 也没什么大问题。

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

虽然不可以用 fflush(stdin),但是我们可以自己写代码来清空输入缓冲区。只需要在 scanf 函数后面加上几句简单的代码就可以了。

Quote:

程序代码 程序代码

/* C 版本 */

#i nclude<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;

}

 

运行结果:

当输入数字时,正常;

当输入字母时,i的值不改变,printf输出的仍是上一次的值。由于输入缓冲区每次都被清空,所以也就不存在scanf自动不停读取缓冲区的值的情况。

/* C++ 版本 */

Quote:

#i nclude <iostream>

#i nclude <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;

}

该版本有待进一步研究。之前在C++ Primer上讲述过其细节。

参考资料:

ISO/IEC 9899:1999 (E) Programming languages — C  7.19.5.2 The fflush function

The C Programming Language 2nd Edition By Kernighan & Ritchie

  评论这张
 
阅读(270)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018