9、如何清空流及缓存

简介:     如下小程序,如果输入错误,不是整形,则输入的这个数会留在缓存区,没有被type取到,type输出默认值或初始值或上次取得到的值(视初始化int type = 0这一句的位置,及编译器优化时,把它放到了那里,在如下程序中,GCC有可能把其提到循环的外面)。

    如下小程序,如果输入错误,不是整形,则输入的这个数会留在缓存区,没有被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版本

示例代码

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 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++版本

示例代码

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif 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

目录
相关文章
|
缓存 Java 数据库连接
|
9月前
|
缓存 开发者
强制清理、刷新浏览器缓存
强制清理、刷新浏览器缓存
147 1
|
缓存 开发框架 NoSQL
7.4缓存
缓存是一个用来保存数据的区域,从缓存中读取数据要比从数据源读取数据的速度快很多。如果可以从缓存中获取要获取的数据则称之为“缓存命中”,多次请求命中的请求占全部请求的百分比叫做“命中率”,如果数据源中的数据保存到了缓存后,发生了变化则称之为“缓存数据不一致”
|
缓存 Linux
缓存区的刷新及配置
缓存区的刷新及配置
138 0
|
存储 缓存
运用惰性删除和定时删除实现可过期的localStorage缓存
使用localStorage可以在浏览器中存储键值对的数据。经常被和localStorage一并提及的是sessionStorage,它们都可以在当浏览器中存储键值对的数据。但是它们之间的区别是:存储在localStorage的数据可以长期保留;而当页面会话结束(也就是当页面被关闭)时,存储在sessionStorage的数据会被清除。
336 0
|
缓存
flush()清空文件缓存区
# 缓冲区:cpu 一级缓存 二级缓存 三级缓存 import time f =open('2.txt','a+' ,encoding='utf-8') f.write('helloworld\n') f.
1141 0
|
Web App开发 缓存 索引
|
缓存
缓存雪崩——使用缓存你不得不知道的坑
缓存雪崩——使用缓存你不得不知道的坑
2037 0
|
缓存 Java 数据库
数据字典的缓存刷新与读取的几种方式
之前有写过数据字典的相关业务是怎么做的,有朋友留言问如何读取,其实很简单,最简单的方式就是每次读取数据库,但是这样的做法很不好,因为数据字典在数据库中属于冷资源,不是经常会变得数据,这样的数据用缓存来做是最好的,在访问数据库前就直接拦截了去数据库的请求,这样减少数据库的压力,毕竟很多页面对于数据字典...
1337 0