9、如何清空流及缓存

    如下小程序,如果输入错误,不是整形,则输入的这个数会留在缓存区,没有被type取到,type输出默认值或初始值或上次取得到的值(视初始化int type = 0这一句的位置,及编译器优化时,把它放到了那里,在如下程序中,GCC有可能把其提到循环的外面)。因为缓存区中有数据,所以cin不会等待用户输入,直接去缓存中读取,发现缓存中的数据不是整形,便把这个数据流在缓存区中,如此反复。这有点类似epollET模式,只要缓存中有数据,没有新的事件发生,则不会提示用户再去读,得用户把缓存中的数据全部读完才行。

void main( void )

{

while(1)

{

int type = 0;

cin >> type;

cout << type;

}

}

1、解决方案

1)错误的方法:通过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)  是不正确的,至少是移植性不好的。(VS支持,GCC不支持)

2)正确的解决方法:

1C版本

示例代码

View Code
#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 字符。 */
/*上述表达式是正则表达式,[^/n]表示非回车符*/
printf(
"%d/n", i);
}
return 0;
}

2C++版本

示例代码

View Code
#include <iostream>
#include
<limits> // 为了使用numeric_limits
using std::cout;
using std::endl;
using std::cin;
using std::numeric_limits;
using std::streamsize;
int main()
{
int value;
for ( ; ; )
{
cout
<< "Enter an integer: ";
cin
>> value;
if ( cin.eof() || cin.bad() )
{
// 如果用户输入文件结束标志(或文件已被读完),
// 或者发生读写错误,则退出循环
// do something
break;
}
// 读到非法字符后,输入流将处于出错状态,
// 为了继续获取输入,首先要调用 clear 函数
// 来清除输入流的错误标记,然后才能调用
// ignore 函数来清除输入流中的数据。
cin.clear();
// numeric_limits<streamsize>::max() 返回输入缓冲的大小。
// ignore 函数在此将把输入流中的数据清空。
// 这两个函数的具体用法请读者自行查询。
cin.ignore( numeric_limits<streamsize>::max(), '/n' );
cout
<< value << '/n';
}
return 0;
}

参考

1 http://blog.csdn.net/csu305/article/details/3321084

http://www.cplusplus.com/reference/clibrary/cstdio/fflush/

http://linux.die.net/man/3/fflush

posted @ 2011-09-07 08:13  浪里飞  阅读(1002)  评论(0编辑  收藏  举报