C++primer第八章 IO库 8.1 IO类

IO库设施

  • istream  (输入流)类型,提供输入操作。
  • ostream (输出流)类型,提供输出操作。
  • cin,—个 istream对象,从标准输入读取数据。
  • cout, 一个ostream对象,向标准输出写入数据。
  • cerr, 一个。stream对象,通常用于输出程序错误消息,写入到标准错误。
  • >>运 算 符 ,用来从一个istream对象读取输入数据。
  • <<运算符,用来向一个stream对象写入输出数据。 
  • getline函数(参见3.3.2节,第 78页),从一个给定的istream读取一行数据, 存入一个给定的string对象中

8.1 IO类

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

  • 为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵wchar_t类型的 数 据 (参见2.1.1节,第 30页)。宽字符版本的类型和函数的名字以一个w 开始。例如,wcin、wcout和 wcerr是分别对应cin、cout和 cerr的宽字符版对象。宽字符版本的类型和对象与其对应的普通char版本的类型定义在同一个头文件中。例如,头文件f stream 定义了 ifstream 和 wif stream 类型

IO类型间的关系

  • 概念上,设备类型和字符大小都不会影响我们要执行的IO 操作。例如,我们可以用>>读取数据,而不用管是从一个控制台窗口,一个磁盘文件,还是一个string 读取。类似的,我们也不用管读取的字符能存入一个char对象内,还是需要一个wchar_t对象来存储。
  • 标准库使我们能忽略这些不同类型的流之间的差异,这是通过继承机制(inheritance) 实现的。利用模板(参见3.3节,第 87页),我们可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。我们将在第15章和18.3节 (第 710页)介绍C++是如何支持继承机制的。简单地说,继承机制使我们可以声明一个特定的类继承自另一个类。我们通常可以将一个派生类(继承类)对象当作其基类(所继承的类)对象来使用
  • 类 型ifstream和istringstream都继承自istream。因此,我们可以像使用istream对象一样来使用ifstream 和istringstream对象。也就是说,我们是如何使 用cin的,就可以同样地使用这些类型的对象。例如,可以对一个ifstream 或istringstream对 象 调 用getline, 也 可 以 使 用>>从 一 个ifstream 或istringstream对象中读取数据。类似的,类型ostringstream和ofstream都继
    承自ostream 。因此,我们是如何使用cout的,就可以同样地使用这些类型的对象。 
  • 本节剩下部分所介绍的标准库流特性都可以无差别地应用于普通流、文件流和string流,以及char或宽字符流版本

 8.1.1  IO对象无拷贝或赋值

  • 如我们在7.1.3节(第234页)所见,我们不能拷贝或对IO对象赋值
  • ofstream outl,out2;
  • outl=out2;//错误:不能对流对象赋值
  • ofstream print(ofstream);//错误:不能初始化ofstream参数
  • out2=print(out2);//错误:不能拷贝流对象
  • 由于不能拷贝IO对象,因此我们也不能将形参或返回类型设置为流类型(参见6.2.1节,第188页)。进行IO操作的函数通常以引用方式传递和返回流读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的

8.1.2条件状态

  • IO操作一个与生俱来的问题是可能发生错误。一些错误是可恢复的,而其他错误则发生在系统深处,已经超出了应用程序可以修正的范围。表8.2列出了IO类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态(conditionstate)

  • 下面是一个IO错误的例子:int ival;cin >> ival;
  • 如果我们在标准输入上键入Boo,读操作就会失败。代码中的输入运算符期待读取一个int,但却得到了一个字符B。这样,cin会进入错误状态。类似的,如果我们输入一个文件结束标识,cin也会进入错误状态。一个流一旦发生错误,其上后续的IO操作都会失败。只有当一个流处于无错状态时,我们才可以从它读取数据,向它写入数据。由于流可能处于错误状态,因此代码通常应该在使用一个流之前检查它是否处于良好状态。确定一个流对象的状态的最简单的方法是将它当作一个条件来使用:
  • while(cin >> word)//ok:读操作成功...
  • while循环检查>>表达式返回的流的状态。如果输入操作成功,流保持有效状态,则条件为真。

查询流的状态

  • 将流作为条件使用,只能告诉我们流是否有效,而无法告诉我们具体发生了什么。有时我们也需要知道流为什么失败。例如,在键入文件结束标识后我们的应对措施,可能与遇到一个IO设备错误的处理方式是不同的。
  • IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用,使用方式与我们在4.8节中(第137页)使用quizl的方式一样。IO库定义了4个iostate类型的const expr值(参见2.4.4节,第58页),表示特定的位模式。这些值用来表示特定类型的IO条件,可以与位运算符(参见4.8节,第137页)一起使用来一次性检测或设置多个标志位。
  • 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成员是一个重载的成员(参见6.4节,第206页):它有一个不接受参数的版本,而另一个版本接受一个iostate类型的参数。clear不接受参数的版本清除(复位)所有错误标志位。执行clear()后,调用good会返回true。我们可以这样使用这些成员:
  • //记住cin的当前状态
  • auto old_state=cin.rdstate();//记住cin的当前状态
  • cin.clear();//使cin有效
  • process_input(cin);//使用cin
  • cin.setstate(old_state);//将cin置为原有状态
  • 带参数的clear版本接受一个iostate值,表示流的新状态。为了复位单一的条件状态位,我们首先用rdstate读出当前条件状态,然后用位操作将所需位复位来生成新的状态。例如,下面的代码将failbit和badbit复位,但保持eofbit不变:
  • //复位failbit和badbit,保持其他标志位不变
  • cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

 

8 .1 .3 管理输出缓冲

  • 每个输出流都管理一个缓冲区,用来保存程序读写的数据。例如,如果执行下面的代码
  • os << "please enter a value: **;
  • 文本串可能立即打印出来,但也有可能被操作系统保存在缓冲区中,随后再打印。有了缓冲机制,操作系统就可以将程序的多个输出操作组合成单一的系统级写操作。由于设备的写操作可能很耗时,允许操作系统将多个输出操作组合为单一的设备写操作可以带来很大的性能提升。缓冲区只有被数据填满,才会刷新缓冲区,将数据写到指定的文件中
  • 导致缓冲刷新(即,数据真正写到输出设备或文件)的原因有很多:
  • 1,程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行
  • 2,缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
  • 3,我们可以使用操纵符如endl(参见1.2节,第6页)来显式刷新缓冲区
  • 4,在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
  • 5,一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout。因此,读cin或写cerr都会导致cout的缓冲区被刷新。

刷新输出缓冲区

  • 我们己经使用过操纵符endl,它完成换行并刷新缓冲区的工作。IO库中还有两个类似的操纵符:flush和ends。flush刷新缓冲区,但不输出任何额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区
  • cout<<"hi!”<<endl;//输出hi和一个换行,然后刷新缓冲区
  • cout<<“hi!”<<flush;//输出hi,然后刷新缓冲区,不附加任何额外字符
  • cout<<"hi!"<<ends;//输出hi和一个空字符,然后刷新缓冲区

unitbuf操纵符

  • 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制
  • cout<<unitbuf;//所有输出操作后都会立即刷新缓冲区
  • //任何输出都立即刷新,无缓冲
  • cout<<nounitbuf;//回到正常的缓冲方式

警告:如果程序崩溃,输出缓冲区不会被刷新

  • 如果程序异常终止,输出缓冲区是不会被刷新的,,当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
  • 当调试一个已经崩溃的程序时,需要确认那些你认为已经输出的数据确实已经刷新了。否则,可能将大量时间浪费在追踪代码为什么没有执行上,而实际上代码已经执行了,只是程序崩溃后缓冲区没有被刷新,输出数据被挂起没有打印而已

关联输入和输出流

  • 当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。标准库将cout和cin关联在一起,因此下面语句
  • cin>>ival;导致cout的缓冲区被刷新。
  • 交互式系统通常应该关联输入流和输出流。这意味着所有输出,包括用户提示信息,都会在读操作之前被打印出来
  • tie有两个重载的版本(参见6.4节,第206页):一个版本不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果
    对象未关联到流,则返回空指针。
  • tie的第二个版本接受一个指向。stream的指针,将自己关联到此ostreamo即,x.tie(&o)将流x关联到输出流O.我们既可以将一个istream对象关联到另一个ostream,也可以将一个ostream关联到另一个ostream:
  • cin.tie(&cout);//仅仅是用来展示:标准库将cin和cout关联在一起
  • //old_tie指向当前关联到cin的流(如果有的话)
  • ostream*old_tie=cin.tie(nullptr);//cin不再与其他流关联
  • //将cin与cerr关联;这不是一个好主意,因为cin应该关联到cout
  • cin.tie(&cerr);//读取cin会刷新cerr而不是cout
  • cin.tie(old_tie);//重建cin和cout间的正常关联
  • 在这段代码中,为了将一个给定的流关联到一个新的输出流,我们将新流的指针传递给了tie。为了彻底解开流的关联,我们传递了一个空指针。每个流同时最多关联到一个流,但多个流可以同时关联到同一个ostream。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2014年英语一作文partB漫画作文

题目 Write an essay of 160-200 words based on the following drawing.In your essay you should describe the drawing brieflyexplain its intended meaning,give your comments 做题点 1.使用三段式,第一段:图片内容;第二段:图片暗示;第三段:写自己的评论 2.描述图片…

Spring Cloud 系列之 Nacos 配置中心

目录一、Nacos简介二、Nacos安装及配置1、环境准备2、安装包下载&#xff08;1&#xff09;源码方式&#xff08;2&#xff09;发行包方式3、启动Nacos服务4、Nacos数据库配置&#xff08;1&#xff09;MySQL数据源&#xff08;2&#xff09;初始化 MySQL 数据库&#xff08;3&…

C++primer第八章 IO库 8.2 文件输入输出

8.2文件输入输出 头文件fstream定义了三个类型来支持文件IO&#xff1a;ifstream从一个给定文件读取数据&#xff0c;ofstream向一个给定文件写入数据&#xff0c;以及fstream可以读写给定文件。在17.5.3节中&#xff08;第676页&#xff09;我们将介绍如何对同一个文件流既读…

codeforces 112A-C语言解题报告

112A题目网址 题目解析 1.输入两行字符串,不区分大小写地使用字典序去比较大小 A<B -1 A>B 1 AB 0 举例: 输入 abcdefg AbCdEfF 输出 1 2.字典序:在遇到第一个不同的字符时,比较的大小,就是字符串的大小 列举法: 1.列出所有情况 1)a[i]是大写,b[i]是小写 a[i]转换为小…

SpringBoot 集成 Nacos

目录一、前言二、Nacos集成1、引入Nacos依赖2、设置Nacos配置3、加载Nacos配置中心配置项4、Nacos集成验证5、Nacos配置中心配置项动态生效Nacos安装详见&#xff1a;Spring Cloud 系列之 Nacos 配置中心 一、前言 上一篇已经讲解了怎样安装安装、启动、配置 Nacos&#xff0c…

C++primer第八章 IO库 8.3string流

8.3string流 sstream头文件定义了三个类型来支持内存IO,这些类型可以向string写入数据,从string读取数据&#xff0c;就像string是一个IO流一样。istringstream从string读取数据&#xff0c;ostringstream向string写入数据&#xff0c;而头文件stringstream既可从string读数据…

英语口语海报演讲--东软

海报 海报上的内容 Nuclear waste water 1.Damage the devastating impact of nuclear radiation on the world 2.Marine life genetically mutated or dead 3.water resources polluted water resources 4.the future of humanity genetic damage/food and environment destr…

Java中 List、Set、Map遍历方式以及性能比较

目录一、简介二、遍历方式1、ArrayList遍历方式&#xff08;1&#xff09;for循环遍历&#xff08;2&#xff09;foreach循环遍历&#xff08;3&#xff09;Iterator迭代器遍历2、LinkedList遍历方式&#xff08;1&#xff09;for循环遍历&#xff08;2&#xff09;foreach循环…

codeforces 263A-C语言解题报告

263A题目网址 题目解析 1.输入5*5的矩阵(下标从到5),包含24个0和一个1,问如何移动最小的次数(i相邻行或列)可以让1位于3行3列 举例: 输入: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 输出: 3 注意点 1.因为数组是从0开始的,所以减2就行 row-2col-2 2.使用整型二维…

一个DEMO让你彻底理解线程池

目录一、简介二、线程池任务场景场景一&#xff1a;提交5个任务&#xff0c;执行总耗时500ms场景二&#xff1a;提交10个任务&#xff0c;执行总耗时500ms场景三&#xff1a;提交11个任务&#xff0c;执行总耗时1000ms场景四&#xff1a;提交20个任务&#xff0c;执行总耗时100…

C++primer第九章 顺序容器 9.1 顺序容器概述 9.2容器库概览

一个容器就是一些特定类型对象的集合。顺序容器(sequentialcontainer)为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值&#xff0c;而是与元素加入容器时的位置相对应。与之相对的&#xff0c;我们将在第11章介绍的有序和无序关联容器&#xff0c;则根据…

SpringBoot 启动报错:Failed to configure a DataSource: ‘url‘ attribute is not specified and no emb

目录一、报错日志二、原因分析三、问题排查四、解决方案方案一&#xff1a;如果项目不需要数据库相关信息就排除此类的autoconfig方案二&#xff1a;配置文件添加数据库链接信息方案三&#xff1a;配置pom.xml中yml或者properties扫描一、报错日志 **************************…

codeforces 339A-C语言解题报告

339A题目网址 题目解析 1.输入如321的式子,升序排序(从小到大)成123 举例: 输入: 11313 输出: 11133 2.对字符串进行排序采取拍冒泡排序算法 char c0; for(i0;i<strlen(s)-1;i) {for(j0;j<strlen(s)-1;j){if(s[j]>s[j1]){cs[j];s[j]s[j1];s[j1]c;}} }代码 #includ…

C++primer第九章 顺序容器 9.3 顺序容器操作

9.3顺序容器操作 顺序容器和关联容器的不同之处在于两者组织元素的方式。这些不同之处直接关系到了元素如何存储、访问、添加以及删除。上一节介绍了所有容器都支持的操作&#xff08;罗列于表9.2&#xff08;第295页&#xff09;&#xff09;。本章剩余部分将介绍顺序容器所特…

SpringBoot 集成Nacos报错(一)

目录配置信息报错信息解决方案配置信息 <project><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/></parent>…

C++primer第九章 顺序容器 9.4 vector对象是如何增长的

为了支持快速随机访问&#xff0c;vector将元素连续存储&#xff0c;每个元素紧挨着前一个元素存储。通常情况下&#xff0c;我们不必关心一个标准库类型是如何实现的&#xff0c;而只需关心它如何使用。然而&#xff0c;对于vector和string,其部分实现渗透到了接口中。假定容器…

codeforces 281A-C语言解题报告

281A题目网址 题目解析 1.字符串首字母大写 代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int main() {char s[1000]{\0};scanf("%s",s);if(s[0]>A&&s[0]<Z){printf("%s",s…

SpringBoot 配置文件bootstrap和application的区别

目录一、SpringBoot配置文件二、bootstrap和application区别三、bootstrap和application的应用场景一、SpringBoot配置文件 bootstrap&#xff08;.yml 或者 .properties&#xff09; application&#xff08;.yml 或者 .properties&#xff09; 二、bootstrap和application区…

C++primer第九章 顺序容器 9.5 额外的string操作

除了顺序容器共同的操作之外&#xff0c;string类型还提供了一些额外的操作。这些操作中 的大部分要么是提供string类和C 风格字符数组之间的相互转换,要么是增加了允许我们用下标代替迭代器的版本。标准库string类型定义了大量函数。幸运的是&#xff0c;这些函数使用了重复的…

Zookeeper Mac下安装操作

目录一、下载Zookeeper二、修改配置1、设置启动配置文件2、修改配置三、启动Zookeeper服务命令1、bin目录下执行&#xff08;1&#xff09;启动Zookeeper命令&#xff08;2&#xff09;查看Zookeeper状态命令&#xff08;3&#xff09;停止Zookeeper命令2、配置环境变量执行&am…