【C++ Primer】第 8 章 IO 类

Spring-_-Bear 的 CSDN 博客导航

八、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 istreamwistream 从流读取数据
ostreamwostream 向流写入数据
iostreamwiostream 读写流
fstream ifstreamwifstream 从文件读取数据
ofstreamwofstream 向文件写入数据
fstreamwfstream 读写文件
sstream istringstreamwistingstream string 读取数据
ostringstreamwostringstream string 写入数据
stringstreamwstringstream 读写 string

为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵 wchar_t 类型的数据。宽字符版本的类型和函数的名字以一个 w 开始。

  1. IO 类型间的关系:概念上,设备类型和字符大小都不会影响我们要执行的 IO 操作。标准库使我们能忽略这些不同类型的流之间的差异,这是通过继承机制实现的。利用模板,我们可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。

    简单地说,继承机制使我们可以声明一个特定的类继承自另一个类。我们通常可以将一个派生类对象当作基类对象来使用。

    例如,类型 ifstreamistringstream 都继承自 istream。因此,我们可以像使用 istream 对象一样来使用 ifstreamistringstream

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() 若流 seofbit 置位,则返回 true
s.fail() 若流 sfailbitbadbit 置位,则返回 true
s.bad() 若流 sbadbit 置位,则返回 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;
    }
}
  1. 查询流的状态:IO 库定义了一个与机器无关的 iostate 类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用。IO 库定义了 4iostate 类型的 constexpr 值表示特定的位模式。这些值用来表示特定类型的 IO 条件,可以与位运算符一起使用来一次性检测或设置多个标志位。

    • badbit 表示系统级错误,如不可恢复的读写错误。通常情况下,一旦 badbit 被置位,流就无法再使用了
    • 在发生可恢复错误后,failbit 被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可以修正的,流还可以继续使用
    • 如果到达文件结束位置,eofbitfailbit 都会被置位
    • goodbit 的值为 0 表示流未发生错误
    • 如果 badbitfailbiteofbit 任意一个被置位,则检测流状态的条件都会失败

    标准库还定义了一组函数来查询这些标志位的状态,如上表所示

    • 操作 good() 在所有错误位均未置位的情况下返回 true,而 bad()fail()eof() 则在对应错误位被置位时返回 true
    • 此外,在 badbit 被置位时,fail() 也会返回 true。这意味着,使用 good()fail() 是确定流的总体状态的正确方法。实际上,我们将流当作条件使用的代码就等价于 !fail()。而 eof()bad() 操作只能表示特定的错误
  2. 管理条件状态:

    • 流对象的 rdstate() 成员返回一个 iostate 值,对应流的当前状态

    • setstate() 操作将给定条件位置位,表示发生了对应错误

    • clear 成员是一个重载的成员:

      clear() 不接受参数的版本复位所有错误标志位,执行 clear() 后,调用 good() 会返回 true

      auto oldState = std::cin.rdstate(<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春天熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值