stream维持一种状态,如果状态是good,表示操作成功;
如果不是good,该流没有任何作用。
stream定义了一些型别为iostate的常数,来反应stream的状态。
1. iostate是class ios_base的成员;
2. 具体由实例版本确定;
iostate的常量包括:
其中,badbit比failbit更严重:
failbit: 某项操作未完成,但是stream大体完成,即设立这个位;通常是由于读入格式错误,如程序需要读入整数,但是遇到字符;
badbit: 若stream由于不明原因而损坏或丢失数据,即设立这个位;例如某个stream被定为指向“文件起点”的更前方。
eofbit和failbit经常同时出现,在eof之后试图读取数据时,会检测到end-of-file状态。在读取最后一个字符时,eofbit未出现,再次试图读取的时候,eofbit和failbit同时被设置,因为读取操作失败了。
上述所有常数并非全局性,因此:需要添加域操作符,如:
std::ios_base::eofbit
使用ios_base的派生类也可以。通常以上标志类由base_ios维护,能够在basic_istream和basic_ostream的所有对象中使用。
stream当前状态可以由一些成员函数来访问。包括:
good(): 若state正常,返回true;返回值类型为bool型;
eof() : 文件读取文件,遇到eof标志,返回true,表示eofbit被设置;
fail():若发生错误,表示failbit或者badbit被设置;
bad() : 发生毁灭性错误,返回true,此时badbit被设置;若rdstate()&badbit非零,函数返回1;
rdstate(): 返回当前已设置的所有标志;函数返回值类iostate类型;
clear() : 清除当前所有标志后;返回值为空;
setstate(state) : 设置state标志,返回值为空。实质是调用clear(_state|rdstate),state为要设置的标志位;
例子:
//-----------cout的状态--------------------
bool good = cout.good();
bool bad = cout.bad();
bool fail = cout.fail();
cout << "goodbit: " << good << endl;
cout << "badbit: " << bad << endl;
cout << "faildbit: " << fail << endl;
fstream fs;
bool eof = fs.eof();
cout << "eofbit: " << eof << endl;
ios_base::iostate rdstaste = cout.rdstate();
cout << "rdstate: " << rdstaste << endl;
//-------------------------------
结果为:
goodbit: 1
badbit: 0
faildbit: 0
eofbit: 0
rdstate: 0
多数情况下,stream不会抛出异常。标准化的stream允许对任何状态的标志进行定义,此状态标志被设置的时候,会引发异常。
异常处理机制包含了函数
- [exception()];
stream定义两个用于bool表达式的函数:
while(std::cin){}
结果中bool条件并不一定要转换我bool,只要能够转化为某个整数型或者指针型别就可以。
转换为void*,是为了在同一表达式中读入对象并测试是否成功。如:
if(std::cin>>x){}
此时,cin用于条件判断,cin调用operator void * ,返回“stream是否发生错误”。
通常,在while循环中,有时采用eof标志作为循环结束的条件,此时failbit和badbit均被设置。
使用“cin”操作符,默认情况下起头空格被跳过,但是如果从流中输入的是char,空格是有意义的。
使用operator!进行反相测试,会返回“stream是否发生错误”。此时标志位failbit和badbit被设置为true;
if(!std::cin>>x){}
[注]: 上述cin是stream对象,二用!cin时,描述cin状态的布尔值。
调用exception时候,可以获得引发异常的标志。调用带参数的exception(),如果参数的标志被设置,会引发相应异常。函数原型为:
exception(flags) //设置“会引发异常”的标志
exception() //返回引发异常的标志
说明 :
1. 函数的第二种形式: 如果返回的是goodbit,表示没有任何异常被抛出;
2. 函数第一种形式: 设置相应标志位,并引发相应异常。如果输入的是goodbit或者0,则不会引发异常。
3. 抛出异常: 是在“程序调用clear()或者setstate()之后”,设立该标志后,如果该标志已被设置并且未被清除,同样会抛出异常。抛出的异常是std::ios_base::failure对象,派生自exception类。
当获取错误信息时候,唯一可移植方式是借助函数what().只有函数what()有可移植性,what()的返回值不具有移植性。
例子:
//----------省略--------
ios_base::iostate old = cin.exceptions();//获取异常
cout << "old exception: " << old << endl;
int x = 0;
try{
cin.exceptions(ios::eofbit | ios::failbit | ios::badbit);//设置标志位
// cin.exceptions(ios::goodbit);
cin >> x;
}
catch (exception& e){//如果相应异常,就捕获
cout << "exceptions : " << e.what() << endl;
}
//-----------省略-----------
需要输入一个整型值,但是我们输入一个字符,引发错误,结果为:
old exception: 0
n
exceptions : ios_base::failbit set: iostream stream error
如果设置标志位为goodbit或0,结果为:
old exception: 0
n
不会捕捉到异常。