文章目录
八、IO 库
C++
语言不直接处理输出输出,而是通过一组定义在标准库中的类型来处理 IO
。这些类型支持从设备读取数据,向设备写入数据的 IO
操作,设备可以是文件、控制台窗口等。还有一些类型允许内存 IO
,即从 string
读取数据,向 string
写入数据。
IO
库定义了读写内置类型值的操作。此外,一些类,如 string
,通常也会定义类似的 IO
操作来读写自己的对象。
目前已经介绍过的 IO
库设施:
istream
:输入流类型,提供输入操作ostream
:输出流类型,提供输出操作cin
:一个istream
对象,从标准输入读取数据cout
:一个ostream
对象,向标准输出写入数据cerr
:一个ostream
对象,通常用于输出程序错误消息,写入到标准错误>>
运算符:用来从一个istream
对象读取输入数据<<
运算符:用来向一个ostream
对象写入输出数据getline
函数:从一个给定的istream
读取一行数据,存入一个给定的string
对象中
8.1 IO 类
到目前为止,我们已经使用过的 IO
类型和对象都是操纵 char
数据的。默认情况下,这些对象都是关联到用户的控制台窗口的。当然,我们不能限制实际应用程序从控制台窗口进行 IO
操作,应用程序常常需要读写命名文件。而且,使用 IO
操作处理 string
中的字符会很方便。此外,应用程序还可能读写需要宽字符支持的语言。
为了支持这些不同种类的 IO
处理操作,标准库还定义了一些其他 IO
类型,分别定义在三个独立的头文件中:
iostream
:定义了用于读写流的基本类型fstream
:定义了读写命名文件的类型sstream
:定义了读写内存string
对象的类型
头文件 | 类型 | 说明 |
---|---|---|
iostream |
istream 、wistream |
从流读取数据 |
ostream 、wostream |
向流写入数据 | |
iostream 、wiostream |
读写流 | |
fstream |
ifstream 、wifstream |
从文件读取数据 |
ofstream 、wofstream |
向文件写入数据 | |
fstream 、wfstream |
读写文件 | |
sstream |
istringstream 、wistingstream |
从 string 读取数据 |
ostringstream 、wostringstream |
向 string 写入数据 |
|
stringstream 、wstringstream |
读写 string |
为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵 wchar_t
类型的数据。宽字符版本的类型和函数的名字以一个 w
开始。
-
IO
类型间的关系:概念上,设备类型和字符大小都不会影响我们要执行的IO
操作。标准库使我们能忽略这些不同类型的流之间的差异,这是通过继承机制实现的。利用模板,我们可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。简单地说,继承机制使我们可以声明一个特定的类继承自另一个类。我们通常可以将一个派生类对象当作基类对象来使用。
例如,类型
ifstream
和istringstream
都继承自istream
。因此,我们可以像使用istream
对象一样来使用ifstream
和istringstream
。
8.1.1 IO 对象无拷贝或赋值
我们不能拷贝或对 IO
对象赋值。由于不能拷贝 IO
对象,因此我们也不能将形参或返回类型设置为流类型。进行 IO
操作的函数通常以引用方式传递和返回流。读写一个 IO
对象会改变其状态,因此传递和返回的引用不能是 const
的。
8.1.2 条件状态
IO
操作一个与生俱来的问题是可能发生错误。一些错误是可恢复的,而其他错误则可能已经超出了应用程序可以修正的范围。下表列出了 IO
类所定义的一些函数和标志,可以帮助我们访问和操作流的条件状态。
注:下表中涉及的 strm
是一种 IO
类型,在 8.1
节中已列出
条件状态 | 说明 |
---|---|
strm::iostate |
iostate 是一种机器无关的类型,提供了表达条件状态的完整功能 |
strm::badbit |
用来指出流已崩溃 |
strm::failbit |
用来指出一个 IO 操作失败了 |
strm::eofbit |
用来指出流到达了文件末尾 |
strm::goodbit |
用来指出流未处于错误状态。此值保证为零 |
s.eof() |
若流 s 的 eofbit 置位,则返回 true |
s.fail() |
若流 s 的 failbit 或 badbit 置位,则返回 true |
s.bad() |
若流 s 的 badbit 置位,则返回 true |
s.good() |
若流 s 处于有效状态,则返回 true |
s.clear() |
将流 s 中所有条件状态位复位,将流的状态设置为有效。返回 void |
s.clear(flags) |
根据给定的 strm::iostate ,将流 s 中对应条件状态位复位。返回 void |
s.setstate(flags) |
根据给定的 strm::iostate ,将流 s 中对应条件状态位置位。返回 void |
s.rdstate() |
返回流 s 的当前状态,返回值类型为 strm::iostate |
确定一个流对象的状态的最简单的方法是将它当作一个条件来使用:
int main() {
int num;
while (std::cin >> num) {
std::cout << "input number = " << num << std::endl;
}
}
-
查询流的状态:
IO
库定义了一个与机器无关的iostate
类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用。IO
库定义了4
个iostate
类型的constexpr
值表示特定的位模式。这些值用来表示特定类型的IO
条件,可以与位运算符一起使用来一次性检测或设置多个标志位。badbit
表示系统级错误,如不可恢复的读写错误。通常情况下,一旦badbit
被置位,流就无法再使用了- 在发生可恢复错误后,
failbit
被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可以修正的,流还可以继续使用 - 如果到达文件结束位置,
eofbit
和failbit
都会被置位 goodbit
的值为0
表示流未发生错误- 如果
badbit
、failbit
和eofbit
任意一个被置位,则检测流状态的条件都会失败
标准库还定义了一组函数来查询这些标志位的状态,如上表所示
- 操作
good()
在所有错误位均未置位的情况下返回true
,而bad()
、fail()
和eof()
则在对应错误位被置位时返回true
- 此外,在
badbit
被置位时,fail()
也会返回true
。这意味着,使用good()
或fail()
是确定流的总体状态的正确方法。实际上,我们将流当作条件使用的代码就等价于!fail()
。而eof()
和bad()
操作只能表示特定的错误
-
管理条件状态:
-
流对象的
rdstate()
成员返回一个iostate
值,对应流的当前状态 -
setstate()
操作将给定条件位置位,表示发生了对应错误 -
clear
成员是一个重载的成员:clear()
不接受参数的版本复位所有错误标志位,执行clear()
后,调用good()
会返回true
。auto oldState = std::cin.rdstate(<
-