缓冲区及流状态、cin.sync()、cin.clear()、cin.ignore()

来源:互联网 发布:数据交换标准 编辑:程序博客网 时间:2024/05/17 00:54

1、输出缓冲区

每一个IO对象都管理一个缓冲区,输入时先把内容输入到缓冲区中,当缓冲区被刷新时将内容写入到真是的输出设备或者文件,缓冲区被刷新有以下几种情况:

1、程序正常结束,作为main函数返回的一部分,将清空所有的缓冲区

2、在一些不确定的情况下缓冲区可能已经满了,因此在写下一个值之前会对缓存区进行刷新

3、用操纵符显示的进行刷新:

endl:刷新流,输出内容换行

flush:刷新流,但不在输出中添加任何形式的字符

ends:在缓冲区中插入空字符null并刷新

4、在每次输出操作执行完后,用unitbuf操作符设置流的内部状态,从而清空缓冲区

5、将输入流与输出流关联。

2、流状态的控制

以下代码用于输出failbit、eofbit、badbit、goodbit几个标志的常量值

cout<<"ios::failbit:"<<ios::failbit<<endl;cout<<"ios::eofbit:"<<ios::eofbit<<endl;cout<<"ios::badbit:"<<ios::badbit<<endl;cout<<"ios::goodbit"<<ios::goodbit<<endl;

以下代码用于输出failbit、eofbit、badbit、goodbit几个标志当前的状态,1表示可用,0表示错误状态

cout<<"cin.fail():"<<cin.fail()<<endl;cout<<"cin.eof():"<<cin.eof()<<endl;cout<<"cin.bad():"<<cin.bad()<<endl;cout<<"cin.good:"<<cin.good()<<endl;

3、cin.clear()、cin.sync()、cin.ignore()用法

cin.clear()是将错误状态更改为有效状态
cin.sync()是清除缓冲区中的未读信息
cin.ignore()是忽略缓冲区中指定个数的字符

int v;char c,d;while(cin>>v,!cin.eof()){  if(cin.fail()){   cerr<<"bad data!"<<endl;   cout<<"cin.fail():"<<cin.fail()<<endl;   cin.ignore();           c=getchar();   cout<<"c:"<<c<<endl;   cin.clear();   d=getchar();   cout<<"d:"<<d<<endl;   cout<<"cin.fail():"<<cin.fail()<<endl;   }}

当输入1 2 3 a 4 5 e时,上述程序cin.ignore()在cin.clear()之前执行,在c=getchar(); cout<<"c:"<<c<<endl;仍然输出a;表明此时cin.ignore()并没有执行,否则在用getchar()获取缓冲区的字符串时不会输出a。此时while循环中cin>>获得的仍然是a,因此程序陷入死循环。

int v;char c,d;while(cin>>v,!cin.eof()){  if(cin.fail()){   cerr<<"bad data!"<<endl;   cout<<"cin.fail():"<<cin.fail()<<endl;    c=getchar();   cout<<"c:"<<c<<endl;   cin.clear();  cin.ignore();   d=getchar();   cout<<"d:"<<d<<endl;   cout<<"cin.fail():"<<cin.fail()<<endl;     }}

上述程序cin.ignore()在cin.clear()之后执行,执行完cin.ignore后,缓冲区中的字符被舍弃,程序继续到while循环执行。

要特别注意cin.ignore()一定要在cin.clear()之后执行;如果cin为错误标志是不能执行cin.ignore()函数中忽略字符的操作的,必须先用cin.clear()重新将错误标志置为可用,才能执行ignore()中忽略字符的操作,不懂得可以看ignore源码。

4、

void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.clear(istream::failbit);continue;}}}

c++ primer上有一个错误程序,对以上程序的改进方法如下

第一种方法(cin.sync();cin.clear())

#include<iostream>using namespace std;void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.sync();  cin.clear();continue;}}}

第二种方法(cin.clear();cin.sync())

#include<iostream>using namespace std;void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.clear();cin.sync();continue;}}}

第三种方法(cin.clear();cin.ignore());以下用cin.ignore()的地方均可换为cin.sync()

#include<iostream>using namespace std;void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.clear();cin.ignore();continue;}}}

第四种方法(cin.clear(istream::goodbit);cin.ignore)

#include<iostream>using namespace std;void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.clear(istream::goodbit);cin.ignore();continue;}}}

第五种方法(cin.clear(istream::failbit ^ cin.rdstate());cin.ignore())

#include<iostream>using namespace std;void main(){int data;while(cin>>data,!cin.eof()){if(cin.bad())throw runtime_error("IO stream corrupted");if(cin.fail()){cerr<<"bad data,try again!"<<endl;cin.clear(istream::failbit ^ cin.rdstate());cin.ignore();continue;}}}