C++语言不直接处理输入输出,而是通过一组定义在标准库中的类型来处理IO。这些类型支持从设备读取数据,向设备写入数据的IO操作,设备可以是文件,控制台窗口等等
- 我们前文已经提到过很多IO库设施,这里再做一个简单的回顾:
- istream(输入流)类型,提供输入操作
- ostream(输出流)类型,提供输出操作
- cin,一个istream对象,从标准输入读取数据
- cout,一个ostream对象,向标准输出写入数据
- cerr,一个ostream对象,通常用于输出错误信息,写入到标准错误
- >>运算符,用来从一个istream对象读取输入数据
- <<运算符,用来向一个ostream对象写入输出数据
- getline函数,从一个给定的istream读取一行数据,存入一个string对象中
- 除了定义了用于读写流的基本类型的iostream头文件外,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型
- ifstream和istringstream都继承自istream(对于输出类型也一样),我们可以像使用istream对象一样来使用前两者。
- IO对象不能被拷贝,进行IO操作的函数通常以引用方式传递和返回流,读写一个IO对象会改变其状态,所以引用不能是const的。
- IO类定义了一些函数和标志来帮助我们访问和操纵流的条件状态,包括状态的查询和设置,此处不赘述。
- 每个输出流都管理一个缓冲区,用来保存读写的数据,从而将程序的多个输出操作组合成单一的系统级写操作。导致缓冲刷新的原因有很多:
- 程序正常结束(main函数return)
- 缓冲区满
- 使用操纵符如endl来显式刷新缓冲区
- 在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态来清空缓冲区。
- 一个输出流可能被关联(tie)到另一个流。当读写主动关联的流时,被关联到的流的缓冲区会被刷新。默认情况下,cin和cerr关联到cout。读cin或写cerr会导致cout的缓冲区被刷新。
- IO库还有两个类似endl的操纵符:flush和ends,flush刷新缓冲区不输出额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区。
- 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵。
nounitbuf则重置流
cout<<unitbuf;
cout<<nounitbuf;
- 程序崩溃后,输出缓冲区是不会刷新的。
- 当一个输入流关联一个输出流,任何试图从输入流读取数据的操作都会先刷新关联的输出流。标准库将cout和cin关联在一起,所以:
cin>>val;
将导致cout的缓冲区被刷新,这对交互式系统而言有重要意义,因为用户输入提示会在读操作之前被打印出来。
11.关联操作通过tie函数实现,具体用法不赘述。每个流同时最多关联一个流,但多个流可以同时关联到同一个ostream。
- 头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,以及fstream可以读写给定文件。这些类型提供的操作与我们之前使用过的对象cin和cout的操作一样,除此以外还增加了一些新的成员来管理与流关联的文件。
- 当我们想要读写一个文件时,可以定义一个文件流对象,并将对象与文件通过open成员函数关联起来。也可以在初始化时指定,此时open自动被调用。
ifstream in(filename);
- 因为在要求使用基类对象的地方,我们可以用继承类型的对象代替。所以,接收一个iostream类型引用或指针参数的函数,可以用一个对应的fstream(sstream)类型来调用。
- 每个流都有一个关联的文件模式,用来指出如何使用文件(包括读,写,追加写入等),此处也不赘述。
- sstream头文件定义了三个类型来支持内存IO,istringstream从string读取数据,ostringstream向string写入数据,stringstream既可读也可写。这些类型在需要对string进行细致的控制的时候(比如制造格式输出)是很有用的,但大体来说使用频率低于前述两种流类型。
网友评论