当前位置: 首页 > news >正文

【C++】IO库(一):IO类

IO 库

C++ 不直接处理输入输出,而是通过定义一族定义在标准库当中的类型来处理IO。

8.1 IO 类

为了支持不同种类的 IO 处理操作,除了 istream 和 ostream 之外,标准库还定义了其它 IO 类型。这些类型分别定义在三个独立的头文件当中:

  • iostream 定义了用于读写流的基本类型;
  • fstream 定义了读写命名文件的类型;
  • sstream 定义了读写内存 string 对象的类型;

IO 类型间的关系

设备类型和字符大小不会影响我们要执行的 IO 操作。例如,我们可以使用 >> 读取数据,不用管数据的来源是来自于控制台窗口,还是来自于磁盘文件或 string 读取。

标准库是我们可以忽略这些不同类型的流之间的差异,这是通过**继承机制(inheritance)**来实现的。

利用模板,可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。

8.1.1 IO 对象无拷贝或赋值

我们不能拷贝或对 IO 对象赋值:

ofstream out1, out2;
out1 = out2;				// 错误❌: 不能对流对象赋值
ofstream print(ofstream);	// 错误❌: 不能初始化 ofstream 参数
out2 = print(out2);			// 错误❌: 不能拷贝流对象 

由于不能拷贝 IO 对象,因此不能将形参或返回类型设置为流类型。进行 IO 操作的函数通常以引用方式传递和返回流(其中,以引用的方式传递和返回流已经在之前的章节当中出现过多次,比如实现一个 read 函数作为 Sales_item 类的接口,从标准输入流读取数据,来对 Sales_item 类进行初始化。read 函数的实现部分正是将输入流作为引用进行参数传递和返回)。

读写一个 IO 对象会改变其状态,因此传递和返回的引用不能是 const 的。

8.1.2 条件状态

IO 操作的一个根本问题是,它是有可能发生错误的。某些错误是可恢复的,而有一些错误可能发生在系统深处,超出了应用程序自身的修正范围。

以下是一个 IO 错误的例子:

int ival;
cin >> ival;

如果我们从标准输入键入Boo,读操作就会失败,因为输入运算符期待的是int类型的输入,以和ival匹配。一个流一旦发生错误,其上后续的 IO 操作都会失败

查询流的状态

有时我们需要直到流为什么会失败,而不仅仅需要知道流是否有效。

IO 库定义了一个与机器无关的 iostate 类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用。IO 库定义了 4 个 iostate 类型的 constexpr 值,表示特定的位模式。这些值用来表示特定类型的 IO 条件,可以与位运算符一起使用来一次性检测或设置多个标志位

badbit 表示系统级错误,如不可恢复的读写错误。通常,一旦 badbit 被置位,则流就无法使用了。

在发生可恢复错误后,failbit 被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可修复的,流还可以继续使用。

如果到达文件结束位置,eofbit 和 failbit 都会被置为。

goodbit 的值为 0,表示流未发生错误。如果 badbit、failbit 和 eofbit 任意一个被置位,则检测流状态的条件会失败。

标准库还定义了一组函数来查询这些标志位的状态。操作 good 在所有错误均为被置位的情况下返回 true,而 bad、fail 和 eof 则在对应错误位置被置位时返回 true。

管理条件状态

8.1.3 管理输出缓冲

每个输出流都管理一个缓冲区,用来保存程序读写的数据。有了缓冲机制,操作系统就可以将程序的多个输出操作组合成单一的系统级写操作。

刷新输出缓冲区

操作符 endl 可以完成换行并刷新缓冲区。

IO 库中还有另外两个相似的操作符,分别是 flush 和 ends。

flush 刷新缓冲区,但不输出任何额外的字符。

ends 向缓冲区插入一个空字符,然后刷新缓冲区。

unitbuf 操作符

如果想要在每一个输出操作后都刷新缓冲区,可以使用 unitbuf 操作符。它将会告诉输出流,接下来的每次写操作之后都进行一次 flush 操作。而 nounitbuf 会重置流:

cout << unitbuf;	// 后续的所有输出操作会立即刷新缓冲区
cout << nounitbuf;	// 重置

关联输入和输出流

当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。标准库直接将 cout 和 cin 关联在一起,因此cin >> ival;这条语句将导致 cout 的缓冲区被刷新。

交互式系统通常应该关联输入流和输出流。这意味着所有输出,包括用户提示信息,都会在读操作之前被打印出来。

tie 有两个重载的版本:一个版本不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针;如果对象未关联到流,则返回空指针。

tie 的第二个版本接受一个指向 ostream 的指针,将自己关联到此 ostream。即:x.tie(&o)x关联到输出流o

我们既可以将 istream 对象关联到另一个 ostream,也可以将一个 ostream 关联到另一个 ostream

cin.tie(&cout);
ostream *old_tie = cin.tie(nullptr);	// cin 不再与其它流关联
cin.tie(&cerr);							// 读取 cin 会刷新 cerr, 而非 cout
cin.tie(old_tie);						// 重建 cin 和 cout 的正常关联

每个流同时最多关联到一个流,但多个流可以同时关联到同一个 ostream。

http://www.lryc.cn/news/491508.html

相关文章:

  • uniapp介入极光推送教程 超级详细
  • 阿里云整理(一)
  • 论文笔记 网络安全图谱以及溯源算法
  • 室内定位论文速递(11.23-11.25)
  • 英伟达推出了全新的小型语言模型家族——Hymba 1.5B
  • 云网络基础- TCP/IP 协议
  • android 音效可视化--Visualizer
  • Python人工智能项目报告
  • DockerFile 构建基础镜像
  • 卷积神经网络学习记录
  • 5种常见的k8s云原生数据管理方案详解
  • [C++]了解内置类型升级
  • docker镜像源配置、换源、dockerhub国内镜像最新可用加速源(仓库)
  • 什么是 WPF 中的依赖属性?有什么作用?
  • 241125学习日志——[CSDIY] [ByteDance] 后端训练营 [16]
  • 如何优化 PHP 性能?
  • 【Linux服务器】内存问题排查
  • ModuleNotFoundError: No module named ‘simple_knn‘
  • 【论文分享】采用现场测量、卫星影像和机器学习方法研究空气温度与城市发展强度之间的关系
  • Linux -初识 与基础指令1
  • 页的初步认识
  • [C++]:IO流
  • Excel如何批量导入图片
  • TCP socket api详解
  • 《C++搭建神经网络基石:开启智能编程新征程》
  • if (条件) { return true; } return false; 简写为 return 条件 详解
  • Pytorch使用手册-Datasets DataLoaders(专题三)
  • 【数据结构】双向链表、单向循环链表、双向循环链表、栈、链栈
  • (动画)Qt控件 QProgressBar
  • 【AI】基础原理