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;
}
}
}