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 数据库连接
|
6月前
|
存储 缓存 对象存储
合理地处理不需要的缓存
【6月更文挑战第8天】本文介绍了管理缓存数据过期的重要性,以避免内存浪费和过时信息的使用。缓存系统通常允许设置默认过期策略或为每个对象指定绝对或滑动过期时间。缓存服务常使用LRU策略进行逐出,但过度使用可能导致内存超出异常。
60 10
合理地处理不需要的缓存
|
6月前
|
存储 缓存 NoSQL
在应用中使用缓存服务
【6月更文挑战第24天】本文介绍redis缓存的基本知识和使用。Redis超越简单的键值存储,Redis查询直接针对键,不支持复杂查询,适合特定场景的高性能缓存。用于减少数据库交互,优化性能。并提供练习源码查阅。
93 1
|
缓存 开发者
强制清理、刷新浏览器缓存
强制清理、刷新浏览器缓存
232 1
|
缓存 Linux
缓存区的刷新及配置
缓存区的刷新及配置
209 0
|
缓存 关系型数据库 RDS
缓存失效竟然可以这么解?
数据传输提供的数据订阅功能,可以在不影响业务的情况下,实现简单、可靠的缓存失效逻辑。这种缓存失效机制为阿里巴巴多年架构优化沉淀下来的经验,下面我们一起来看数据订阅究竟怎么实现这种机制。
10615 0
|
缓存
flush()清空文件缓存区
# 缓冲区:cpu 一级缓存 二级缓存 三级缓存 import time f =open('2.txt','a+' ,encoding='utf-8') f.write('helloworld\n') f.
1179 0
|
Web App开发 缓存 索引
|
缓存
缓存雪崩——使用缓存你不得不知道的坑
缓存雪崩——使用缓存你不得不知道的坑
2078 0