条件状态

实现 IO 的继承正是错误发生的根源。一些错误是可恢复的;一些错误则发生在系统底层,位于程序可修正的范围之外。IO 标准库管理一系列条件状态(condition state) 成员,用来标记给定的 IO 对象是否处于可用状态,或者碰到了哪种特定的错误。

strm::iostate

机器相关的整型名,由各个 iostream 类定义,用于定义条件状态

strm::badbit

strm::iostate 类型的值,用于指出被破坏的流

strm::failbit

strm::iostate 类型的值,用于指出失败的 IO 操作

strm::eofbit

strm::iostate 类型的值,用于指出流已经到达文件结束符

s.eof()

如果设置了流 s 的 eofbit 值,则该函数返回 true

s.fail()

如果设置了流 s 的 failbit 值,则该函数返回 true

s.bad()

如果设置了流 s 的 badbit 值,则该函数返回 true

s.good()

如果流 s 处于有效状态,则该函数返回 true

s.clear()

将流 s 中的所有状态值都重设为有效状态

s.clear(flag)

将流 s 中的某个指定条件状态设置为有效。flag 的类型是strm::iostate

s.setstate(flag)

给流 s 添加指定条件。flag 的类型是 strm::iostate

s.rdstate()

返回流 s 的当前条件,返回值类型为 strm::iostate

考虑下面 IO 错误的例子:

int ival;
cin >> ival;

如果在标准输入设备输入 Borges,则 cin 在尝试将输入的字符串读为 int型数据失败后,会生成一个错误状态。类似地,如果输入文件结束符(end-of-file),cin 也会进入错误状态。而如果输入 1024,则成功读取,cin将处于正确的无错误状态。

流必须处于无错误状态,才能用于输入或输出。检测流是否用的最简单的方法是检查其真值:

if (cin)
// ok to use cin, it is in a valid state
while (cin >> word)
// ok: read operation successful ...

if 语句直接检查流的状态,而 while 语句则检测条件表达式返回的流,从而间接地检查了流的状态。如果成功输入,则条件检测为 true。

条件状态

许多程序只需知道是否有效。而某些程序则需要更详细地访问或控制流的状态,此时,除了知道流处于错误状态外,还必须了解它遇到了哪种类型的错误。

所有流对象都包含一个条件状态成员,该成员由 setstate 和 clear 操作管理。这个状态成员为 iostate 类型,这是由各个 iostream 类分别定义的机器相关的整型。该状态成员以二进制位(bit)的形式使用。

badbit 标志着系统级的故障,如无法恢复的读写错误。如果出现了这类错误,则该流通常就不能再继续使用了。如果出现的是可恢复的错误,如在希望获得数值型数据时输入了字符, 此时则设置 failbit 标志, 这种导致设置 failbit的问题通常是可以修正的。eofbit 是在遇到文件结束符时设置的,此时同时还设置了 failbit。

流的状态由 bad、fail、eof 和 good 操作提示。如果 bad、fail 或者 eof中的任意一个为 true,则检查流本身将显示该流处于错误状态。类似地,如果这三个条件没有一个为 true,则 good 操作将返回 true。

clear 和 setstate 操作用于改变条件成员的状态。clear 操作将条件重设为有效状态。在流的使用出现了问题并做出补救后,如果我们希望把流重设为有效状态,则可以调用 clear 操作。使用 setstate 操作可打开某个指定的条件,用于表示某个问题的发生。除了添加的标记状态,setstate 将保留其他已存在的状态变量不变。

流状态的查询和控制

可以如下管理输入操作:

int ival;
// read cin and test only for EOF; loop is executed even if there ar
other IO failures
while (cin >> ival, !cin.eof()) {
if (cin.bad()) // input stream is corrupted; bail ou
throw runtime_error("IO stream corrupted");
if (cin.fail()) { // bad input
cerr<< "bad data, try again"; // warn the user
cin.clear(istream::failbit); // reset the stream
continue; // get next input
}
// ok to process ival
}

这个循环不断读入 cin,直到到达文件结束符或者发生不可恢复的读取错误为止。

在循环中,首先检查流是否已破坏。如果是的放,抛出异常并退出循环。如果输入无效,则输出警告并清除 failbit 状态。

条件状态的访问

rdstate 成员函数返回一个 iostate 类型值,该值对应于流当前的整个条件状态:

// remember current state of cin
istream::iostate old_state = cin.rdstate();
cin.clear();
process_input(); // use cin
cin.clear(old_state); // now reset cin to old state

多种状态的处理

常常会出现需要设置或清除多个状态二进制位的情况。此时,可以通过多次调用 setstate 或者 clear 函数实现。另外一种方法则是使用按位或(OR)操作符在一次调用中生成“传递两个或更多状态位”的值。按位或操作使用其操作数的二进制位模式产生一个整型数值。对于结果中的每一个二进制位, 如果其值为 1, 则该操作的两个操作数中至少有一个的对应二进制位是 1。例如:

// sets both the badbit and the failbit
is.setstate(ifstream::badbit | ifstream::failbit);

将对象 is 的 failbit 和 badbit 位同时打开。实参:

is.badbit | is.failbit

生成了一个值,其对应于 badbit 和 failbit 的位都打开了,也就是将这两个位都设置为 1,该值的其他位则都为 0。在调用 setstate 时,使用这个值来开启流条件状态成员中对应的 badbit 和 failbit 位。 

posted @ 2018-05-02 22:44  刘-皇叔  阅读(349)  评论(0)    收藏  举报