9、如何清空流及缓存

news/2024/7/9 17:56:59 标签: c/c++, 操作系统, epoll

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

示例代码

ContractedBlock.gif ExpandedBlockStart.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++版本

示例代码

ContractedBlock.gif ExpandedBlockStart.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

转载于:https://www.cnblogs.com/mydomain/archive/2011/09/07/2169396.html


http://www.niftyadmin.cn/n/1071982.html

相关文章

Mysql 字符串分隔函数

/*** 字符串分隔方法* 获取字符串分隔之后的数组长度*/DROP FUNCTION IF EXISTS func_get_split_total;DELIMITER ;;CREATE FUNCTION func_get_split_total(    f_string text, # 长度不够会导致临时表数据不全&#xff0c;# mysql字符类型varchar有长度限制(最大65535)&am…

使用Cucumber+Rspec玩转BDD(3)——用户登录

使用CucumberRspec玩转BDD(3)——用户登录 2009年3月7日 星期六 ### 温故知新 ###在前面的两篇文章中&#xff0c;笔者向读者朋友们分别演示了用户注册和注册用户通过邮件激活帐号的开发过程。当用户注册成功并激活帐号后&#xff0c;系统应该可以让用户登录站点&#xff0c;这…

今天发布视频-现代黄河三角洲

历史上黄河一直在改道&#xff0c;从1989年到现在&#xff0c;黄河从东南方向入海改道为主要以东北方向入海。

Logstash学习之路(四)使用Logstash将mysql数据导入elasticsearch(单表同步、多表同步、全量同步、增量同步)...

一、使用Logstash将mysql数据导入elasticsearch 1、在mysql中准备数据&#xff1a; mysql> show tables; ---------------- | Tables_in_yang | ---------------- | im | ---------------- 1 row in set (0.00 sec)mysql> select * from im; ---------- | id…

下周发布大洋箱式取样视频

大洋底质取样调查常规方法就是箱式取样&#xff0c; 视频中箱式取样的区域位于多金属结核区&#xff0c; 从取样结果看&#xff0c;结核丰度不错。

Silverlight中的RadialGradientBrush

RadialGradientBrush的属性解释 GradientOrigin:渐变开始的坐标 Center:是最外层渐变的坐标 RadiusX:表示渐变圆的Width&#xff0c;默认值是0.5&#xff08;是通过测量当前的渐变区域&#xff08;左上角到右下角&#xff09;的Width&#xff0c;然后得到一个比例&#xff0c;0…

今天发布视频-Cesium是地理信息的未来

Unreal Engine&#xff0c;虚幻引擎是全球最开放、最先进的实时3D创作平台&#xff0c;主要用作游戏引擎。 Cesium for Unreal &#xff0c;可以将 3D 真实世界的地理空间数据加载到 Unreal 中使用了。 Cesium是地理信息的未来。

记事本的秘密

开始->程序->附件->记事本... 新建个记事本文件吧... 在里面输入“aaaa bbb ccc ddddd”&#xff08;引号不算&#xff0c;只要是4-3-3-5的个数形式的字母&#xff0c;中间加空格&#xff09; 然后保存&#xff0c;关闭记事本&#xff0c;再找到你刚才保存的记事本文件…