最近在输入输出流上载了好多次,所以看了资料,决定写下来供大家参考,欢迎指正:
首先明确一点,输入cin和输出cout有四个状态:
- godbit 无错误
- Eofbit 已到达文件尾
- failbit 非致命的输入/输出错误
- badbit 致命的输入/输出错误
badbit是一些系统底层或者硬件出错,比如文件系统错误,磁盘错误,网络错误等;不可恢复
failbit就是其他软件错误,如试图从不能解析为整数的字符串里想要读一个整数等,eof也会造成failbit被置位;可以恢复,一般用cin.clear();将cin的标志位改为godbit
cin.fail()可以检测的是badbit和failbit这两个标志位。
cin.bad()用来检测的是badbit标志位。
可以用下面的代码来查看状态位的信息;输出如下图:
cout <<"ios:: failbit:"<< ios:: failbit << endl;
cout <<"ios:: eofbit:"<< ios:: eofbit << endl;
cout <<"ios:: badbit:"<< ios:: badbit << endl;
cout <<"ios:: goodbit:"<< ios:: goodbit << endl;
cout <<"ios:: eofbit:"<< ios:: eofbit << endl;
cout <<"ios:: badbit:"<< ios:: badbit << endl;
cout <<"ios:: goodbit:"<< ios:: goodbit << endl;
图中各状态分别为0、1、2、4。其实就是二进制里的000、001、010、001。用这三个位来表示输入输出流的状态。
想知道每个标志位的状态,可以使用cin.rdstate()函数取得整个标志变量的值,然后与对应的标志常量相与就可以获得对应标志位的状态。如下面的代码:
cout <<"badbitstate:"<< ( x.rdstate( ) & ios::badbit ) << endl;
cout <<"eofbitstate:"<< ( x.rdstate( ) & ios::failbit ) << endl;
cout <<"eofbitstate:"<< ( x.rdstate( ) & ios::eofbit ) << endl;
cout <<"eofbitstate:"<< ( x.rdstate( ) & ios::failbit ) << endl;
cout <<"eofbitstate:"<< ( x.rdstate( ) & ios::eofbit ) << endl;
经常由于标志位处于错误状态,所以不能进行输入就直接跳过,比如下面的代码:
void main ()
{
int a,b;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin>>a>>b;
cout<<a<<b<<endl;
}
{
int a,b;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin>>a>>b;
cout<<a<<b<<endl;
}
当输入正确时,标志位为0,第五行可以继续进行输入;
当输入错误时,标志位状态为1,这里是因为输入类型不是int型,所以产生failbit ,非致命的输入/输出错误 ,读者可以根据上面的方式进行验证。
函数没有在第五行重新输入,直接退出。
首先我们利用上面所提到的用cin.clear()来将cin的标志位改为godbit,如下:
void main ()
{
int a,b;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.clear();
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin>>a>>b;
cout<<a<<b<<endl;
}
加上cin.clear();后可以看到标志位状态已经恢复正常,但是还是没有进行输入,而是直接退出了。这里是因为,q w没有读入到a b中,它们还在缓冲流里面,需要将其清除。
void main ()
{
int a,b;
char ch,ch1,ch2;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.clear();
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.get(ch);
cin.get(ch1);
cin.get(ch2);
cout<<ch<<" "<<ch1<<ch2;
cin>>a>>b;
cout<<a<<b<<endl;
}
{
int a,b;
char ch,ch1,ch2;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.clear();
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.get(ch);
cin.get(ch1);
cin.get(ch2);
cout<<ch<<" "<<ch1<<ch2;
cin>>a>>b;
cout<<a<<b<<endl;
}
我用char类型变量把缓冲区字符取出然后输出后,下面的cin可以正常使用了。
切记,在上面我用了三个cin.get(),是因为除了q和w,还有一个回车符在流里面,必须将其取出。
按理说ch2应该为换行符,但是我输出并没换行,也没有任何显示,这里有点疑惑??
也可以使用fflush(stdin);或者cin.sync();直接清空缓冲区,(两个效果类似)来进行重新输入,代码如下:
void main ()
{
int a,b;
//char ch,ch1,ch2;
cin>>a>>b;
cout<<a<<b<<endl;
cout<<"标志位状态为:"<<cin.fail()<<endl;
cin.clear();
cout<<"标志位状态为:"<<cin.fail()<<endl;
fflush(stdin);
//cin.sync();
/*cin.get(ch);
cin.get(ch1);
cin.get(ch2);
cout<<ch<<" "<<ch1<<ch2;*/
cin>>a>>b;
cout<<a<<b<<endl;
}
当然也可以用cin.ignore();这里就不过多叙述,留给读者进行尝试!