第八章 IO库
c++语言不直接处理输入输出,而是通过一组定义在标准库中的类型来处理IO。这些类型支持从设备读取数据和写入数据的IO操作,设备可以是文件,控制台窗口等。
例如istream是输入流类型,cin是istream的一个对象,>>是从istream对象读取输入数据的运算符。
1.IO类
iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。
标准库使我们能忽略不同类型流之间的差异(普通流,文件流,string流,以及char或者宽字符流版本),是通过继承来实现的。通常我们可以将一个派生类对象当作其基类对象来使用。
1.IO对象无拷贝或赋值
**不能对IO对象拷贝或者赋值,**因此也不能将形参或者返回值类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写流会改变其状态,因此传递和引用不能是const的。
2.条件状态
IO操作可能会发生错误。确定一个流对象的状态的最简单的方法是将它当作一个条件来使用。
while (cin>>word) //检查>>表达式返回的流的状态,如果输入操作成功,流保持有效状态,则条件为真。
ok;
上述只能告诉我们流是否有效,我们也可以查询和管理流的状态。
3.管理输出缓冲
每个输出流都有一个缓冲区,所以操作系统可以将程序的多个输出操作组合成单一的系统级写操作,这样可以提升写操作的效率。
刷新输出缓冲区:
cout<<"hi"<<endl; //输出一个hi和换行,然后刷新缓冲区
cout<<"hi"<<flush; //输出一个hi,然后刷新缓冲区,不额外附加字符
cout<<"hi"<<ends; //输出一个hi和空字符,然后刷新缓冲区
如果想在每次输出操作后都刷新缓冲区,可以使用unitbuf操作符。
cout<<unitbuf; //所有输出操作后都会立即刷新缓冲区
cout<<unonitbuf; //回到正常
程序崩溃后,它所输出的数据可能停留在输出缓冲区等待打印。调试崩溃程序时要确认那些你认为已经输出的数据缺失已经刷新了。
关联输入和输出
当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。标准库将cin和cout关联在一起。
不带参数的tie函数返回指向输出流的指针(可以为空);
带参数的tie函数接受一个指向ostream的指针,将自己关联到ostream。
cin.tie(&cout); //仅仅用来展示标准可将cin和cout关联到一起
ostream *old=cin.tie(nullptr); //cin不再与其它流关联
cin.tie(old); //重建cin和cout的关联
2.文件输入输出
1.使用文件流对象
头文件ifstream定义了ifstream类型(读),ofstream类型(写)以及fstream类型操作文件IO。拥有继承自iostream的行为。
由于继承的关系,可以将一个派生类对象当作其基类对象来使用,接受一个iostream&类型引用(指针)参数的函数可以用一个对应的fstream类型来调用。
每个文件流都有名为open和close的的成员函数。
ofstream out;
out.open(" "); //调用open可能会失败
if(out) //检查调用open是否失败
一般对一个已经打开的文件流调用open会失败,所以必须先关闭(.close)。
如果文件流对象是循环中的局部变量,那么它在每一个循环步都要创建和销毁一次,当文件流被销毁的时候,close会自动调用。
2.文件模式
包括以读方式打开(out),以写方式打开(in),每次写操作前均定义在文件末尾(app),打开文件后立即定位到文件末尾(ate),截断问文件(trunc),以二进制方式运行IO(binary),未指定则以默认方式。
通常以out模式打开的文件会舍弃已有的数据,所以要指定app模式。
ofstream out1(“file1”,ofstream::app);
调用open的时候也要注意指定文件模式,不然为默认。
3.string流
头文件sstream定义了istringstream类型(读),ostringstream类型(写)以及stringstream类型操作文件IO。拥有继承自iostream的行为。
1.使用istringstream
如果我们某些工作是对整行文本进行处理,而其它工作是处理行内的单个单词时,可以用这个。
2.使用ostringstream
这一部分直接看书上栗子⑧,书上咋那么聪明QAQ