清除文件流的状态
考虑这样的程序,它有一个 vector 对象,包含一些要打开并读取的文件名,
程序要对每个文件中存储的单词做一些处理。假设该 vector 对象命名为
files,程序也许会有如下循环:

// for each file in the vector
 while (it != files.end()) {
 ifstream input(it->c_str()); // open the file;
 // if the file is ok, read and "process" the input
 if (!input)
 break; // error: bail out!
 while(input >> s) // do the work on this file
 process(s);
 ++it; // increment iterator to get
 next file
 }


每一次循环都构造了名为 input 的 ifstream 对象,打开并读取指定的文
件。构造函数的初始化式使用了箭头操作符(第 5.6 节)对 it 进行解引用,
从而获取 it 当前表示的 string 对象的 c_str 成员。文件由构造函数打开,
并假设打开成功,读取文件直到到达文件结束符或者出现其他的错误条件为止。
在这个点上,input 处于错误状态。任何读 input 的尝试都会失败。因为 input
是 while 循环的局部变量,在每次迭代中创建。这就意味着它在每次循环中都
以干净的状态即 input.good() 为 true,开始使用。
如果希望避免在每次 while 循环过程中创建新流对象,可将 input 的定义
移到 while 之前。这点小小的改动意味着必须更仔细地管理流的状态。如果遇
到文件结束符或其他错误,将设置流的内部状态,以便之后不允许再对该流做读
写操作。关闭流并不能改变流对象的内部状态。如果最后的读写操作失败了,对
象的状态将保持为错误模式,直到执行 clear 操作重新恢复流的状态为止。调
用 clear 后,就像重新创建了该对象一样。
如果打算重用已存在的流对象,那么 while 循环必须在每次循环进记得关
闭(close)和清空(clear)文件流:

393
 ifstream input;
 vector<string>::const_iterator it = files.begin();
 // for each file in the vector
 while (it != files.end()) {
 input.open(it->c_str()); // open the file
 // if the file is ok, read and "process" the input
 if (!input)
 break; // error: bail out!
 while(input >> s) // do the work on this file
 process(s);
 input.close(); // close file when we're done with it
 input.clear(); // reset state to ok
 ++it; // increment iterator to get next file
 }


如果忽略 clear 的调用,则循环只能读入第一个文件。要了解其原因,就
需要考虑在循环中发生了什么:首先打开指定的文件。假设打开成功,则读取文
件直到文件结束或者出现其他错误条件为止。在这个点上,input 处于错误状态。
如果在关闭(close)该流前没有调用 clear 清除流的状态,接着在 input 上
做的任何输入运算都会失败。一旦关闭该文件,再打开 下一个文件时,在内层
while 循环上读 input 仍然会失败——毕竟最后一次对流的读操作到达了文件
结束符,事实上该文件结束符对应的是另一个与本文件无关的其他文件。
如果程序员需要重用文件流读写多个文件,必须在读另一个文
件之前调用 clear 清除该流的状态。