《C++ Primer》第8章 IO库

参考资料:

  • 《C++ Primer》第5版
  • 《C++ Primer 习题集》第5版

8.1 IO类(P278)

我们目前使用过的 IO 对象(cincout)都是关联到控制台窗口、操纵 char 数据的。有时,我们需要对命名文件或者 string IO 操作。为了支持不同种类的 IO 操作,标准库定义了一些 IO 类型:

4867a8b265d1052cb95a861bed4a234

IO类型间的关系

概念上,设备类型和字符大小不会影响我们要执行的 IO 操作,例如我们可以用 >> 读取数据,这是通过**继承机制(inheritance)**实现的。

8.1.1 IO对象无拷贝或赋值(P279)

我们不能拷贝或对 IO 对象赋值,进行 IO 操作的函数通常以引用的方式传递和返回流。读写 IO 对象会改变其状态,所以传递和返回的引用不能是 const 的。

8.1.2 条件状态(P279)

IO 操作可能发生不同类型的错误,IO 类定义了一些函数和标志,可以帮助我们访问和操纵流的条件状态(condition state)

例如我们使用输入运算符并期待读入一个 int ,而实际上却得到了一个字符 B ,此时输入流将进入错误状态。只有当一个流处于无错状态时,我们才可以向它读写数据。最简单的判断流对象是否处于良好状态的方法:

while(cin >> word){ ... }

查询流的状态

IO 库定义了一个机器无关的 iostate 类型,提供表达流状态的完整功能。iostate 应该作为位集合来使用,IO 库定义了 4 个特定 constexpr 来表示特定的位:

  • badbit 表示系统级错误,通常为不可恢复的读写错误。
  • failbit 表示可恢复错误,如期望读取数值却得到字符。
  • eofbit 表示文件结束,此时 failbit 也会被置位。
  • goodbit0 表示流未发生错误(个人推测,前 3 个位在正常状态下为 0goodbit 就是它们的)。

标准库还定义了一组函数来查询上述标志位的状态:

  • good 在所有错误位均未被置位的情况下返回 true
  • badfaileof 在对应位被置位时返回 true ,此外,failbadbit 被置位时也会返回 true

管理条件状态

auto old_state = cin.rdstate();
cin.clear();
cin.setstate(old_state);
// 将failbit、badbit复位,其他位保持不变
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

上述代码中,rastate 函数返回一个 iostate 值,对应当前流的状态setstate 相当于把输入的 iostate “叠加”到流的原状态上,可以理解为或运算;无参数的 clear 复位所有错误标志位,带参数的 clear 接受一个 iostate 参数,表示流的新状态

8.1.3 管理输出缓冲(P281)

每个输出流都有一个缓冲区,用来保存程序读写的数据。保存在缓冲区中的数据可能随后再打印。

导致缓冲刷新(数据真正写到输出设备或文件)的原因:

  • 程序正常结束,作为 main 函数 return 操作的一部分。
  • 缓冲区满。
  • 使用操纵符(如 endl )显式刷新缓冲区。
  • 使用操纵符 unitbuf 设置流的内部状态。cerr 是默认 unitbuf 的,因此写到 cerr 里的内容是立即刷新的。
  • 和输入流关联的输出流在输入流读取数据前会刷新缓冲区。

刷新输出缓冲区

cout << "hi" << endl;    // 输出hi和一个换行,然后刷新缓冲区
cout << "hi" << ends;    // 输出hi和一个空字符,然后刷新缓冲区
cout << "hi" << flush;    // 输出hi,然后刷新缓冲区

unibuf操纵符

cout << unitbuf;    // 将流设置为:接下来每一次写操作之后都进行一次flush操作
cout << nounitbuf;    // 回到正常的缓冲方式

如果程序异常终止,缓冲区是不会刷新的。所以我们在调试崩溃的程序时,需要检查输出是否停留在缓冲区内。

关联输入和输出流

当一个输入流被关联到一个输出流时,任何试图从输入流中读取数据的操作都会先刷新输出流的缓冲区。标准库将 cincout 关联在一起。

// 将cin关联到cout(仅仅用来展示,相当于什么都没有做)
cin.tie(&cout);
ostream *old_tie = cin.tie();
// 让cin不与任何流关联
cin.tie(nullptr);
// 将cin关联到cerr
cin.tie(&cerr);
cin.tie(old_tie);

tie 的无参数版本返回指向输出流的指针,如果本对象关联到一个输出流,则返回那个输出流的指针;如果本对象没有关联的输出流,则返回 nullptrtie 的单参数版本接受一个指向输出流的指针,将自己关联到此输出流。

每个流最多与一个流关联,但多个流可以同时关联到一个输出流(单向关联)。

8.2 文件输入输出(P283)

头文件 fstream 定义了三个类型来支持文件 IO :

  • ifstream :从一个给定文件读取数据。
  • ofstream:向一个给定文件写入数据。
  • fstream :读写给定文件。

除了继承自 iostream 的操作外,fstream 中还定义了一些新的成员:

88282ac734807eb1312cf041dd6917f

8.2.1 使用文件流对象(P284)

当我们想要读写一个文件时,可以定义一个文件流对象,并将之与文件关联起来。每个文件流类都定义了名为 open 成员函数来定位并以指定模式打开文件。创建文件流对象时,如果我们提供了文件名,则 open 会自动调用:

ifstream in(ifile);    // 构造一个ifstream并打开文件
ofstream out;

在 C++ 新标准中,文件名可以是 string 对象或 C 风格字符数组,旧版本的标准库只允许 C 风格字符数组。

fstream代替iostream&

在要求使用基类对象的地方,我们可以用继承类对象代替。这意味着一个接受 iostream 类型引用或指针参数的函数,可以用相应的 fstream 对象代替。

成员函数openclose

ifstream in(ifile);    // 构造一个ifstream并打开文件
ofstream out;
out.open(ifile + ".copy");

如果 open 调用失败,fallbit 会被置位。检测 open 是否成功是个好习惯:

if(out)

当一个文件流与对应文件成功关联,我们称文件流已经打开。用一个已经打开的文件流调用 open 会导致 failbit 被置位。所以如果我们将文件流关联到另一个文件,我们必须先使用 close 关闭当前文件:

in.close();

自动构造和析构

当一个 fstream 对象被销毁时,close 会自动调用。

8.2.2 文件模式(P286)

每个流都有一个关联的文件模式(file mode),用来指出如何使用文件:

8dd48df77fd3770cccad59711ee93e0

无论用哪种方式打开文件,我们都可以指定文件模式:

  • 只有 ofstreamfstream 能使用 out 模式。
  • 只有 ifstreamfstream 能使用 in 模式。( VS2022 似乎没这两条限制?这两条似乎与后面的冲突啊 … )
  • 只有当 out 模式被设定时,trunc 模式才能被设定。
  • 只要 trunc 模式没被设定,就可以设定 app 模式。在 app 模式下,文件综艺输出方式打开。
  • 默认情况下,以 out 模式打开的文件会默认被截断,为了保留文件内容,可以同时指定 addin 模式。
  • atebinary 模式可以用于任何类型的文件流对象。

每个文件流类型都有默认的文件模式,如果我们没有指定文件模式,就使用此模式。ifstream 默认使用 in 模式,ofstream 默认使用 out 模式,fstream 默认使用 inout 模式。

out模式打开会丢失数据

默认情况下,我们用 ofstream 对象打开文件时,文件内容的会被丢弃。

每次调用open时会确定文件模式

对于一个给定的流,每当打开文件时都可以改变文件模式。

8.3 string

sstream 头文件定义了三个支持内存 IO :

  • istringstream :从 string 读取数据。
  • ostringstream :向 string 写入数据。
  • stringstream :读写 string 数据。
00ba1c34d964732f0a72393165ce4ad

8.3.1 使用istringstream

假设我们要处理一个文件,文件的内容时人名和他们使用的电话号码:

morgan 2015552368 8625550123
drew 973550130
lee 6095550132 2015550175 800555000

我们首先定义一个类来保存数据:

struct PersonInfo {
	string name;
	vector<string> phones;
};

然后完成程序:

string line, word;
vector<PersonInfo> people;
while (getline(cin, line)) {
    PersonInfo info;
    istringstream record(line);
    record >> info.name;
    while (record >> word) {
        info.phones.push_back(word);
    }
    people.push_back(info);
}

8.3.2 使用ostringstream(P289)

接上面的例子,如果我们希望逐个验证电话号码并改变其格式 ,并将改变格式后的有效代码输出,并打印无效号码的错误信息:

for (const auto &entry : people) {
	ostringstream formatted, badNums;
	for (const auto &nums : entry.phones) {
		if (!valid(nums)) {
			badNums << " " << nums;
		}
		else {
			formatted << " " << format(nums);
		}
		if (badNums.str().empty())
			cout << entry.name << " " << formatted.str() << endl;
		else
			cerr << "input error: " << entry.name << "invalid number(s)" << badNums.str() << endl;
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/125757.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

与set和map相关的OJ题练习

一、两个数组的交集 题目链接&#xff1a; 349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给两个数组&#xff0c;求在数组里面共同出现的部分&#xff0c;就是求两个数组的交集&#xff0c;返回顺序不做要求 解题思路&#xff1a; …

Centos7安装配置中文输入法

Centos7安装配置中文输入法 在安装CentOS时&#xff0c;我们为了方便使用&#xff0c;语言选择了中文&#xff0c;但是我们发现&#xff0c;在Linux命令行或者是浏览器中输入时&#xff0c;我们只能输入英文&#xff0c;无法输入汉字。 来&#xff0c;跟随脚步&#xff0c;设…

第14章,lambda表达式与流处理例题

package 例题;import java.util.List; import java.util.stream.Collectors; import java.util. stream.Stream;public class 例题19 { public static void main(String[] args){List<例题14> list 例题14.get例题14List();//获取公共类的测试数据Stream<例题14>…

GZ038 物联网应用开发赛题第2套

2023年全国职业院校技能大赛 高职组 物联网应用开发 任 务 书 (第2套卷) 工位号:______________ 第一部分 竞赛须知 一、竞赛要求 1、正确使用工具,操作安全规范; 2、竞赛过程中如有异议,可向现场考评人员反映,不得扰乱赛场秩序; 3、遵守赛场纪律,尊重考评人员,…

Flink -- 事件时间 Watermark

1、事件时间&#xff1a; 指的是数据产生的时间或是说是数据发生的时间。 在Flink中有三种时间分别是&#xff1a; Event Time&#xff1a;事件时间&#xff0c;数据产生的时间&#xff0c;可以反应数据真实发生的时间 Infestion Time&#xff1a;事件接收时间 Processing Tim…

AIGC:使用生成对抗网络GAN实现MINST手写数字图像生成

1 生成对抗网络 生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;是一种非常经典的生成式模型&#xff0c;它受到双人零和博弈的启发&#xff0c;让两个神经网络在相互博弈中进行学习&#xff0c;开创了生成式模型的新范式。从 2017 年以后&#x…

【MATLAB源码-第69期】基于matlab的LDPC码,turbo码,卷积码误码率对比,码率均为1/3,BPSK调制。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 本文章介绍了卷积码、Turbo码和LDPC码。以相同的码率仿真这三种编码&#xff0c;并对比其误码率性能 信源输出的数据符号&#xff08;二进制&#xff09;是相互独立和等概率的&#xff1b; 信道是加性白高斯噪声信道&#…

王道考研--》顺序表课后习题C语言代码实现(冲刺)

考研是许多计算机科学专业学生追求高学历、寻求更好就业前景的途径。在考研过程中&#xff0c;数据结构是一个非常重要的科目&#xff0c;而代码实现题更是其中的难点之一。在这篇文章中&#xff0c;我们将探讨如何通过实现数据结构代码问题来提升考研成绩。无论您是否有编程经…

Excel中功能区的存放位置很灵活,可以根据需要隐藏或显示

在这个简短的教程中,你将找到5种快速简单的方法来恢复Excel功能区,以防丢失,并学习如何隐藏功能区,为工作表腾出更多空间。 功能区是Excel中所有操作的中心点,也是大多数可用功能和命令所在的区域。你觉得功能区占用了你太多的屏幕空间吗?没问题,只需单击鼠标,它就被隐…

Apache APISIX Dashboard 未经认证访问导致 RCE(CVE-2021-45232)漏洞复现

漏洞描述 Apache APISIX 是一个动态、实时、高性能的 API 网关&#xff0c;而 Apache APISIX Dashboard 是一个简单易用的前端界面&#xff0c;用于管理 Apache APISIX。 在 2.10.1 之前的 Apache APISIX Dashboard 中&#xff0c;Manager API 使用了两个框架&#xff0c;并在…

本地生活餐饮视频怎么拍摄能有更多流量?如何批量生产呢?

本地生活近几年特别的火&#xff0c;所以到现在各类内容雷同性也比较高&#xff0c;视频缺少新的创意和玩法&#xff0c;像餐饮店的视频&#xff0c;大部分都是拍顾客进门、拍餐饮店座无虚席的实景……作为用户&#xff0c;其实早就已经看腻了。 今天推荐本地生活餐饮店商家拍…

11.9存储器实验总结(单ram,双ram,FIFO)

实验设计 单端口RAM实现 双端口RAM实现 FIFO实现 文件结构为

Linux nohup后台启动/ 后台启动命令中nohup 、、重定向的使用

文章目录 一、前言二、nohup&#xff08;不挂断&#xff09;简介三、nohup使用3.1、nohup启动3.2、nohup与&&#xff0c;后台运行3.3、nohup与>&#xff0c;日志重定向3.4、nohup后台启动-综合使用(推荐)2>&1 3.5、nohup后台启动(不生成日志) 四、查看进程五、知…

IDEA项目下不显示target目录或者target目录不完整没有新添加的资源,idea隐藏target目录

文章目录 一、前言二、idea隐藏target目录2.1、idea隐藏target目录2.2、git提交时隐藏target目录 三、idea下显示target目录3.1、解决idea下不显示target目录问题3.2、target显示目录不完整 一、前言 在idea-2020.1.4版本下讲解idea怎么显示或隐藏target目录。 需要知道:如果…

数据采集代码示例

首先&#xff0c;你需要安装一个 Lua 的爬虫库&#xff0c;例如 Luanode 或者 Lush&#xff1a; lua local ltn12 require("ltn12") local http require("") local response http.request{ host "", port , path "/", …

SSM图书管理系统开发mysql数据库web结构java编程计算机网页源码eclipse项目

一、源码特点 SSM 图书管理系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用SSM框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代码和 数据库&#xff0c;系统主要…

STM32 蜂鸣器介绍 配置 播放音节

蜂鸣器一般被分为两类&#xff1a;有源蜂鸣器和无源蜂鸣器。其中源是振荡源。有源蜂鸣器内部有振荡电路&#xff0c;可以把直流电源转换为一定频率的脉冲信号。因为它一直输出一定的频率&#xff0c;我们无法改变频率&#xff0c;所以声音只有一种&#xff0c;我们只能通过电源…

AJAX 入门笔记

课程地址 AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09; AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部分网页内容 XML…

NSSCTF第11页(3)

[羊城杯 2020]easyphp 源码 发现会在写入文件之前会删除目录下的除了index.php的文件。写入文件的文件名和文件内容也是可控的&#xff0c;只不过存在过滤 stristr函数对文件内容进行过滤&#xff0c;该函数绕过还是简单的&#xff0c;只需要添加一些特殊字符就可以了&#…

微服务-开篇-个人对微服务的理解

从吃饭说起 个人理解新事物的时候喜欢将天上飞的理念转换成平常生活中的实践&#xff0c;对比理解这些高大上的名词&#xff0c;才能让我们减少恐慌的同时加深理解。废话不多说&#xff0c;我们从吃饭开始说起&#xff0c;逐渐类比出微服务的思想。 &#xff08;个人见解&…
最新文章