IO类

  C++语言不直接处理出入输出,而是通过一族定义在标准库中的类型来处理IO。这些类型支持从设备读取数据、向设备写入数据的IO操作,设备可以是文件控制台窗口 等。还有一些类型允许内存IO ,即从string读取数据,向string写入数据。常见IO库设施如下:

  • istream(输入流)类型,提供输入操作。
  • ostream(输出流)类型,提供输出操作。
  • cin,一个istream对象,从标准输入读取 数据。
  • cout,一个ostream对象,想标准输出写入 数据。
  • cerr, 一个ostream对象,通常用于输出程序错误信息,写入 到标注错误。
  • > > 运算符,用来从一个istream对象读取输入数据
  • < < 运算符,用来从一个ostream对象写入输出数据
  • getline函数,从一个给定的istream读取一行数据存入一个给定的string对象中(遇到换行符结束)。

  IO库类型的头文件:

  IO类型间的关系:

  1、IO对象无拷贝或赋值:

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

  由于不能拷贝IO对象,因此我们也不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。

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



  注意: 一个流一旦发生错误,其上后续的IO操作都会失败。

  确定一个流对象的状态的最简单的方法是将它作为一个条件来使用:

while(cin>>word){
// ok:读操作成功....
}

  查询流的状态: 将流作为条件使用,只能告诉我们流是否有效,而无法告诉我们具体发生了什么。IO库定义了一个iostate 类型,它提供了表达流状态的完整功能。这个类型应作为一个位集合来使用,即通过位运算来使用。IO库定义了4个iostate类型的constexpr 值,表示特定的位模式。这些值用来表示特定类型的IO条件,可以与位运算符一起使用来一次性检测或设置多个标志位。

  管理条件状态: 流对象的rdstate 成员返回一个iostate 值(读取当前条件状态),对应流的当前状态。setstate 操作将给定条件位置位,表示发生了对应错误。clear成员是一个重载的成员,它有一个不接受参数的版本(复位所有错误标志位),而另一个版本接受一个iostate类型的参数。

// 机主cin的当前状态
auto old_state = cin.rdstate(); //记住cin的当前状态
cin.clear(); //使cin有效
process_input(cin); //使用cin
cin,setstate(old_state); //将cin置为原有状态 //复位failbit和badbit,保持其他标志位不变
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

  3、管理输出缓冲: 每个输出流 都管理一个缓冲区 ,用来保存程序读写的数据。导致缓冲刷新(即数据真正写到输出设备或文件)的原因有很多:

  • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
  • 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
  • 我们可以使用操纵符endl、flush、ends 来显示刷新缓冲区。
  • 在每个输出操作之后,我们可以用操纵符unitbuf 设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
  • 一个输出流可能被关联 到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。默认情况下,cin和cerr都被关联到cout,因此读cin或写cerr都会导致cout的缓冲区被刷新。

  刷新输出缓冲区: 除了常见的endl外,IO库还有两个类似的操纵符:flushends 。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函数 ,tie有两个重载的版本:一个版本不带参数,返回指向输出流的指针 ,如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果未关联到流,则返回空指针;**tie的第二个版本接受一个指向ostream的指针,将自己关联到此ostream,即x.tie(& o)将流关联到输出流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间的正常关联

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

文件输入输出

  1、fstream: 除了继承自iostream类型的行为之外,fstream中定义的类型还增加了一些新的成员来管理与流关联的文件:

  2、使用文件流对象: 如果我们定义了一个空文件流对象,可以随后调用open来将它与文件关联起来:

ifstream in(ifile);     //构筑一个ifstream并打开给定文件
ofstream out; //输出文件流未与任何文件相关联
out.open(ifile + ".copy"); //打开指定文件 //如果调用open失败,failbit会被置位。
//因为调用open可能失败,进行open是否成功的检测通常是一个好习惯
if(out) //检查open是否成功
//open成功,我们可以使用文件了

  一旦一个文件流已经打开,它就保持与对应文件的关联。实际上,对一个已经打开的文件流调用open会失败,并且会导致failbit被置位,随后的试图使用文件流的操作都会失败。为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件:

in.close();            //关闭文件
in.open(ifile+"2"); //打开另一个文件

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

  3、文件模式: 每个流都有一个关联的文件模式,用来指出如何使用文件。

  指定文件模式有如下限制:

  • 只可以对ofstream或fstream对象设定out模式。
  • 只可以对ifstream或fstream对象设定in模式。
  • 只有当out也被设定时才可设定trunc 模式。
  • 只要trunc 没被设定,就可以设定app模式。在app 模式下,即使没有显示指定out 模式,文件也总是以输出方式被打开。
  • 默认情况下,即使我们没有指定trunc ,以out 模式打开的文件也会被截断。为了保留以out 模式打开的文件的内容,我们必须同时指定app 模式,这样只会将数据追加写到文件末尾;或者同时指定in 模式,即打开文件同时进行读写操作。
  • atebinary 模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。

  注意: 每个文件流类型都定义了一个默认的文件模式,当我们未指定文件模式时,就使用此默认模式。与ifstream关联的文件默认以in模式打开;与ofstream关联的文件默认以out模式打开;与fstream关联的文件默认以in和out模式打开。

string 流

  1、sstream: 除了自iostream继承得来的的操作,sstream中定义的类型还增加了一些成员来管理与流相关联的string。

  2、使用istringstream: 当我们的某些工作是对整行文本 进行处理,而其他一些工作是处理行内的单个单词 时,通常可以使用istringstream:

//假如要处理如下数据,个人信息(名字,手机号码)
morgan 2015552368 8625550123
drew 9735550130
lee 6095550132 2015550175 8005550000 struct Personlnfo {
string name;
vector <string> phones;
} string line, word ; // 分别保存未自输入的一行和单饲
vector <PersonInfo> people ; // 保存来自输入的所有记录
// 运行从输入读取数据, 直至cin遇到文件尾(或其他错误)
while (getline(cin , line )){
PersonInfoinfo; // 创建一个保存此记录数据的对象
istringstream record(line) ; // 将记录绑定到刚读入的行
record >> info.name ; // 读取名字
while (record >> word) // 读取电话号码
info.phones . push_back(word); // 保持它们
people.push_back(info); // 将此记录追加到pe o ple 末尾
}

  3、使用ostringstream: 当我们逐步构造输出 ,希望最后一起打印 时,ostringstream是很有用的。比如,对上述的例子,我们可能想要逐个验证电话号码并改变其格式。如果所有号码都是有效的,我们希望输出一个新的文件,包含改变格式后的号码。对于那些无效的号码,我们不会将它们输出到新文件中,而是打印一条包含人名和无效号码的错误信息。

for(const auto &entry : people){    //对people中每一项
ostringstream formatted,badNums; //每个循环创建的对象
for(const auto &nums : entry.phone){
if(!valid(nums)){
badNums<<" "<<nums; //将数的字符串形式存入badNums
}
else{
//将格式化的字符串“写入”formatted
formatted<<" "<<format(nums);
}
}
if(badNums.str().empty()) //没有错误的数
os<<entry.name<<" "<<formatted.str()<<endl;
else //否者,打印名字和错误的数
cerr<<"input error"<<entry.name
<<"incalid numbers"<<badNum.str()<<endl;
}

IO库的更多相关文章

  1. [APUE]标准IO库(下)

    一.标准IO的效率 对比以下四个程序的用户CPU.系统CPU与时钟时间对比 程序1:系统IO 程序2:标准IO getc版本 程序3:标准IO fgets版本 结果: [注:该表截取自APUE,上表中 ...

  2. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  3. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  4. 【转载】C++ IO库

    本篇随笔为转载,原贴地址:<C++ Primer>第8章 IO库 学习笔记. 1.IO类 #include <iostream> istream//从流中读取数据 ostrea ...

  5. 从Decorator,Adapter模式看Java的IO库

    我想任何一本介绍模式的书在讲到Decorator模式的时候不能不提到它的实际应用--在Java/IO库里面的应用,<<Java与模式>>这本书也不例外,有点不一样的是,这本书在 ...

  6. C++ Primer 读书笔记: 第8章 标准IO库

    第8章 标准IO库 8.1 面向对象的标准库 1. IO类型在三个独立的头文件中定义:iostream定义读写控制窗口的类型,fstream定义读写已命名文件的类型,而sstream所定义的类型则用于 ...

  7. 标准模板库——IO库

    IO库设施: . istream(输入流)类型,提供输入操作. . ostream(输出流)类型,提供输出操作. . cin,一个istream对象,从标准输入读取数据. . cout,一个ostre ...

  8. 高级UNIX环境编程5 标准IO库

    标准IO库都围绕流进进行的 <stdio.h><wchar.h> memccpy 一般用汇编写的 ftell/fseek/ftello/fseeko/fgetpos/fsetp ...

  9. 第 8 章 IO库

    第 8 章 IO库 标签: C++Primer 学习记录 IO库 第 8 章 IO库 8.1 IO类 8.2 文件输入输出 8.1 string流 8.1 IO类 IO对象无拷贝或赋值,因此不能将形参 ...

随机推荐

  1. iOS事件响应链(Responder Chain)

    概述 在iOS中,视图的层级一般都是 父视图->添加各种子视图.这时候某个视图(子视图)上有个按钮,需要我们交互.但是有时候我们会发现无论如何都没有反应.这时候可能就是我们对iOS的事件传递响应 ...

  2. linux服务器部署jar包以及shell脚本的书写

    背景:记录在linux环境下部署jar程序的过程 1 部署过程记录 1.1 程序结构 这里的main函数就在DemRest2.java 文件中. 为了部署方便,要做到以下两点: 1 在导出的jar包中 ...

  3. (转)Linux开机启动(bootstrap)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 计算机开机是一个神秘的过程.我们只是按了开机键,就看到屏幕上的进度条或者一行行的输 ...

  4. PHP中使用单双引号的区别

    1,双引号可以解析变量,单引号不可以解析: 2,双引号解析转义字符,单引号不解析转义,但是可以解析 \'  和  \\ ; 3,单双引号不能自己套自己,要嵌套使用,避免混乱: 4,单引号效率更高,能使 ...

  5. C++基本内置类型

    C++基本内置类型 基本内置类型包括算术类型和空类型. 算术类型 算术类型包括整型和浮点型. 类型 含义 最小尺寸 bool 布尔型 - char 字符型 8 bit wchar_t 宽字符型 16 ...

  6. centos7安装docker并安装jdk和tomcat(常用命令)

    阿里专属的镜像加速 在宿主机器编辑文件:vi /etc/docker/daemon.json 阿里专属的镜像加速地址,类似于"https://91cntlkt.mirror.aliyuncs ...

  7. Vue事件处理

    前面的话 Vue事件监听的方式貌似违背了关注点分离(separation of concern)的传统理念.实际上,所有的Vue.js事件处理方法和表达式都严格绑定在当前视图的ViewModel上,它 ...

  8. Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

    这个问题当然是找不到mysql的驱动类,可能是环境CLASSPATH有问题或者就是那个人没有加载jdbc的驱动.我在网上下载mysql-connector-java-5.0.8-bin.jar一个这个 ...

  9. 嵌入式GPIO接口及操作(一)

    GPIO意思就是通用输入输出,一些引脚可以通过他们输出高低电平,或者通过它们读入引脚的状态.对GPIO的操作是对所有硬件的操作最基本的技能.一.通过寄存器来操作GPIO引脚,一个引脚可以用于输入.输出 ...

  10. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...