首页 理论教育 stream状态C++STL精解

stream状态C++STL精解

时间:2023-10-25 理论教育 版权反馈
【摘要】:stream维持一种状态,用于标志IO是否成功,并能指出不成功的原因。上述标识仅能反映最后一次操作的stream状态,主要原因是这些标识可能被以前的某操作设置。多数情况下,stream不会抛出异常。标准化之后的stream允许对任何状态标识进行定义,此状态标识被设置时,会引发异常。进行反相测试,会返回“stream是否发生错误”,此时标志位failbit和badbit被设置为true。

stream状态C++STL精解

stream维持一种状态,用于标志IO是否成功,并能指出不成功的原因。每个流都包含相关联的状态。若状态是good,则说明操作是成功的;此时下一个输入操作可能成功,否则会失败。在读取变量过程中,操作状态如果不是good,该数据流不会产生任何作用。流状态为fail或bad之间存在着微妙的差异:若状态为fail,则可以假设流未被破坏,并且没有字符丢失;若状态为bad,就意味着彻底失败。

1.stream状态常数

stream定义了一些型别为iostate的常数,用以反映stream的状态。iostate是类ios_base的成员,其具体型别由实例版本决定,即iostate未被限定是列举型别和整数型别。iostate型别的常量主要包括

goodbit、eofbit、failbit和badbit。goodbit代表一切都好;eofbit代表文件末尾标志;fail-bit代表错误,即某个IO操作未成功;badbit代表毁灭性错误,不确定状态。failbit和badbit相比,后者是更严重的错误。二者的区别如下。

failbit:某项操作未能完成,但stream大体处于好的状态,即设立这个位;通常是由于读入格式错误,例如,程序需要读入整数,却遇到字符。

badbit:若stream由于不明原因而损坏或丢失数据,即设立这个位。例如,某个stream被定为指向“文件起点”的更前方。

eofbit经常和failbit同时出现,在eof之后试图读取数据时,会检测出end-of-file状态。在最后一个字符被读取时,eofbit并未出现,再次试图读取字符时,往往eofbit和failbit同时被设置,因为读取操作失败了。

上述常数并非全局性,而仅定义于类ios_base中,需要加作用域操作符。例如,

使用ios_base类的派生类也是可以的。以上标识能够在basic_istream和basic_ostream的所有对象中使用。streambuffer没有状态标识,单个streambuffer可被多个streamobject共享。

上述标识仅能反映最后一次操作的stream状态,主要原因是这些标识可能被以前的某操作设置。

2.stream状态相关成员函数

stream当前状态的一些标志可以由一些成员函数来访问。这些成员函数主要包括good()、eof()、fail()、bad()、rdstate()、clear()、clear(state)和setstate(state)。下面一一介绍。

good():若stream正常无误,返回true。表示goodbit已设置。该函数的返回值为bool类型,当basic_ios的rdstate等于goodbit时,返回值为1;否则,返回0。

bad():发生毁灭性错误时,返回true。此时badbit被设置。该函数的返回值为bool类型,若basic_ios的rdstate&badbit非零,返回值为1;否则返回0。

例如,

上述代码的输出结果为:

例如,

上述代码的输出结果为:

rdstate():返回当前已设置的所有标志;其返回值为iostate类型。

clear():清除当前所有标志;其返回值为空。

clear(state):清除所有标志后,设置标记state;其返回值为空。

setstate(state):设置state标志。其返回值为空。其实质是调用clear(_State|rdstate)函数。参数state代表需要设置的标志位。

需要说明的是被设置的位仅能反映过去曾发生的事情,如果某次操作后,发现某个或若干位被设置,无法确定究竟是该次或先前操作导致的该结果。如果想通过标志了解或获取错误信息,在操作前应先设置goodbit()。对于每种标志的访问,必须使用正确的访问方法。(www.xing528.com)

例如,

上述代码的输出结果为:

3.stream状态和异常

(1)stream状态

stream定义了两个用于bool表达式的operator void()和!()函数。C++的异常处理机制可以用于处理错误和异常。多数情况下,stream不会抛出异常。标准化之后的stream允许对任何状态标识进行定义,此状态标识被设置时,会引发异常。异常处理机制包含了excep-tion()函数。下面主要介绍上述3个函数的使用方法。

operator void()和!()函数,并不是显式地调用该函数,而是隐式地调用。例如,

结构中的bool条件并不一定要转化为bool,只要能够转化成某个整数型别或指针型别即可。转换为void是为了在同一表达式中读入对象并测试是否成功。例如,

此时的cin用于条件判断,cin会调用operatorvoid∗,返回“stream是否发生错误”。

通常,在while循环中,有时使用eof作为循环终止的条件,此时一般failbit和badbit均被设置。使用“>>”操作符时,默认情况下起头空格会被跳过。但如果从流中输入的是型别是char,空格是有意义的。流stream的成员put()函数和get(),可以实现IO过滤,或者使用流缓冲区迭代器streambuf_iterator也可实现IOfilter。

使用operator!进行反相测试,会返回“stream是否发生错误”,此时标志位failbit和badbit被设置为true。

注意:上述cin是stream的对象,而在使用“!cin”时,是描述cin状态的布尔值。

(2)处理异常

调用exception()函数,可获取目前的异常标识。调用带参数的exception()时,如果参数代表的标志被设置,也会引发相应异常。exception()函数的原型为:

对于该函数的第二种形式,如果其返回值是goodbit,表示没有任何异常被抛出;该函数的第一种形式是设置相应的标志位,并引发相应异常。若输入的参数是goodbit或者是0,则不会引发异常。

抛出异常是“程序调用clear()或setstate()之后”,设立某标志,如果该标志已被设置并且未被清除,同样也会抛出异常。抛出的异常是std::ios_base::failure对象,该对象是派生自类exception。

需要说明的是,获取错误信息的唯一可移植方式是借助what()函数。

what()函数的操作具有移植性。但what()的返回值不具有移植性,需要根据实际情况判断函数的返回结果。

stream的异常处理能力主要是在读取“格式化数据”时尽显身手,但在使用异常过程中仍然存在诸多问题。当读取数据至文件末尾时,会产生因end-of-file导致的异常。通过检查流状态可以分清异常的具体原因——是数据错误还是达到文件末尾。

下面以例7-3来说明exception()函数的使用方法。

例7-3

执行上述程序时,读者应输入一个整型数据(例如一个阿拉伯数字)。上述代码的执行结果如下:

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈