Team LiB
Previous Section Next Section

8.2. Condition States

8.2. 条件状态

Before we explore the types defined in fstream and sstream, we need to understand a bit more about how the IO library manages its buffers and the state of a stream. Keep in mind that the material we cover in this section and the next applies equally to plain streams, file streams, or string streams.

在展开讨论 fstreamsstream 头文件中定义的类型之前,需要了解更多 IO 标准库如何管理其缓冲区及其流状态的相关内容。谨记本节和下一节所介绍的内容同样适用于普通流、文件流以及 string 流。

Inherent in doing IO is the fact that errors can occur. Some errors are recoverable; others occur deep within the system and are beyond the scope of a program to correct. The IO library manages a set of condition state members that indicate whether a given IO object is in a usable state or has encountered a particular kind of error. The library also defines a set of functions and flags, listed in Table 8.2, that give us access to and let us manipulate the state of each stream.

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

Table 8.2. IO Library Condition State
表 8.2. IO 标准库的条件状态

strm::iostate

Name of the machine-dependent integral type, defined by each iostream class that is used to define the condition states.

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

strm::badbit

strm::iostate value used to indicate that a stream is corrupted.

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

strm::failbit

strm::iostate value used to indicate that an IO operation failed.

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

strm::eofbit

strm::iostate value used to indicate the a stream hit end-of-file.

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

s.eof()

true if eofbit in the stream s is set.

如果设置了流 seofbit 值,则该函数返回 true

s.fail()

true if failbit in the stream s is set.

如果设置了流 sfailbit 值,则该函数返回 true

s.bad()

true if badbit in the stream s is set.

如果设置了流 sbadbit 值,则该函数返回 true

s.good()

true if the stream s is in a valid state.

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

s.clear()

Reset all condition values in the stream s to valid state.

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

s.clear(flag)

Set specified condition state(s) in s to valid. Type of flag is strm::iostate.

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

s.setstate(flag)

Add specified condition to s. Type of flag is strm::iostate.

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

s.rdstate()

Returns current condition of s as an strm::iostate value.

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


As an example of an IO error, consider the following code:

考虑下面 IO 错误的例子:

     int ival;
     cin >> ival;

If we enter Borges on the standard input, then cin will be put in an error state following the unsuccessful attempt to read a string of characters as an int. Similarly, cin will be in an error state if we enter an end-of-file. Had we entered 1024, then the read would be successful and cin would be in a good, non-error state.

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

To be used for input or output, a stream must be in a non-error state. The easiest way to test whether a stream is okay is to test its truth value:

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

          if (cin)
               // ok to use cin, it is in a valid state

          while (cin >> word)
               // ok: read operation successful ...

The if directly tests the state of the stream. The while does so indirectly by testing the stream returned from the expression in the condition. If that input operation succeeds, then the condition tests true.

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

Condition States

条件状态

Many programs need only know whether a stream is valid. Other programs need more fine-grained access to and control of the state of the stream. Rather than knowing that the stream is in an error state, we might want to know what kind of error was encountered. For example, we might want to distinguish between reaching end-of-file and encountering an error on the IO device.

许多程序只需知道是否有效。而某些程序则需要更详细地访问或控制流的状态,此时,除了知道流处于错误状态外,还必须了解它遇到了哪种类型的错误。例如,程序员也许希望弄清是到达了文件的结尾,还是遇到了 IO 设备上的错误。

Each stream object contains a condition state member that is managed through the setstate and clear operations. This state member has type iostate, which is a machine-dependent integral type defined by each iostream class. It is used as a collection of bits, much the way we used the int_quiz1 variable to represent test scores in the example in Section 5.3.1 (p. 156).

所有流对象都包含一个条件状态成员,该成员由 setstateclear 操作管理。这个状态成员为 iostate 类型,这是由各个 iostream 类分别定义的机器相关的整型。该状态成员以二进制位(bit)的形式使用,类似于第 5.3.1 节的例子中用于记录测验成绩的 int_quiz1 变量。

Each IO class also defines three const values of type iostate that represent particular bit patterns. These const values are used to indicate particular kinds of IO conditions. They can be used with the bitwise operators (Section 5.3, p. 154) to test or set multiple flags in one operation.

每个 IO 类还定义了三个 iostate 类型的常量值,分别表示特定的位模式。这些常量值用于指出特定类型的 IO 条件,可与位操作符(第 5.3 节)一起使用,以便在一次操作中检查或设置多个标志。

The badbit indicates a system level failure, such as an unrecoverable read or write error. It is usually not possible to continue using a stream after such an error. The failbit is set after a recoverable error, such as reading a character when numeric data was expected. It is often possible to correct the problem that caused the failbit to be set. The eofbit is set when an end-of-file is encountered. Hitting end-of-file also sets the failbit.

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

The state of the stream is revealed by the bad, fail, eof, and good operations. If any of bad, fail, or eof are true, then testing the stream itself will indicate that the stream is in an error state. Similarly, the good operation returns TRue if none of the other conditions is true.

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

The clear and setstate operations change the state of the condition member. The clear operations put the condition back in its valid state. They are called after we have remedied whatever problem occurred and we want to reset the stream to its valid state. The setstate operation turns on the specified condition to indicate that a problem occurred. setstate leaves the existing state variables unchanged except that it adds the additional indicated state(s).

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

Interrogating and Controlling the State of a Stream

流状态的查询和控制

We might manage an input operation as follows:

可以如下管理输入操作

    int ival;
    // read cin and test only for EOF; loop is executed even if there are other IO failures
    while (cin >> ival, !cin.eof()) {
        if (cin.bad())         // input stream is corrupted; bail out
            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
    }

This loop reads cin until end-of-file or an unrecoverable read error occurs. The condition uses a comma operator (Section 5.9, p. 168). Recall that the comma operator executes by evaluating each operand and returns its rightmost operand as its result. The condition, therefore, reads cin and ignores its result. The result of the condition is the result of !cin.eof(). If cin hit end-of-file, the condition is false and we fall out of the loop. If cin did not hit end-of-file, we enter the loop, regardless of any other error the read might have encountered.

这个循环不断读入 cin,直到到达文件结束符或者发生不可恢复的读取错误为止。循环条件使用了逗号操作符(第 5.9 节)。回顾逗号操作符的求解过程:首先计算它的每一个操作数,然后返回最右边操作数作为整个操作的结果。因此,循环条件只读入 cin 而忽略了其结果。该条件的结果是 !cin.eof() 的值。如果 cin 到达文件结束符,条件则为假,退出循环。如果 cin 没有到达文件结束符,则不管在读取时是否发生了其他可能遇到的错误,都进入循环。

Inside the loop, we first check whether the stream is corrupted. If so, we exit by throwing an exception (Section 6.13, p. 215). If the input was invalid, we print a warning, and clear the failbit state. In this case, we execute a continue (Section 6.11, p. 214) to return to the start of the while to read another value into ival. If there were no errors, the rest of the loop can safely use ival.

在循环中,首先检查流是否已破坏。如果是的放,抛出异常并退出循环。如果输入无效,则输出警告并清除 failbit 状态。在本例中,执行 continue 语句(第 6.11 节)回到 while 的开头,读入另一个值 ival。如果没有出现任何错误,那么循环体中余下的部分则可以很安全地使用 ival

Accessing the Condition State

条件状态的访问

The rdstate member function returns an iostate value that corresponds to the entire current condition state of the stream:

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

Dealing with Multiple States

多种状态的处理

Often we need to set or clear multiple state bits. We could do so by making multiple calls to the setstate or clear functions. Alternatively, we could use the bitwise OR (Section 5.3, p. 154) operator to generate a value to pass two or more state bits in a single call. The bitwise OR generates an integral value using the bit patterns of its operands. For each bit in the result, the bit is 1 if the corresponding bit is 1 in either of its operands. For example:

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

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

tells the object is to turn on both the failbit and the badbit. The argument

将对象 isfailbitbadbit 位同时打开。实参:

     is.badbit | is.failbit

creates a value in which the bits corresponding to the badbit and to the failbit are both turned onthat is they are both set to 1. All other bits in the value are zero. The call to setstate uses this value to turn on the bits corresponding to badbit and failbit in the stream's condition state member.

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

Exercises Section 8.2

Exercise 8.3:

Write a function that takes and returns an istream&. The function should read the stream until it hits end-of-file. The function should print what it reads to the standard output. Reset the stream so that it is valid and return the stream.

编写一个函数,其唯一的形参和返回值都是 istream& 类型。该个函数应一直读取流直到到达文件结束符为止,还应将读到的内容输出到标准输出中。最后,重设流使其有效,并返回该流。

Exercise 8.4:

Test your function by calling it passing cin as an argument.

通过以 cin 为实参实现调用来测试上题编写的函数。

Exercise 8.5:

What causes the following while to terminate?

导致下面的 while 终止的原因是什么?

    while (cin >> i) /* . . . */


Team LiB
Previous Section Next Section