[笔记索引]
第8章 标准IO库
⒈ IO标准库类型
类名 派生自 头文件 描述
istream ios iostream 输入流
ostream ios iostream 输出流
iostream istream和ostream iostream 输入/输出流
ifstream istream fstream 输入文件流
ofstream ostream fstream 输出文件流
fstream iostream fstream 输入/输出文件流
istringstream istream sstream 输入字符串流
ostringstream ostream sstream 输出字符串流
stringstream iostream sstream 输入/输出字符串流
⑴ 标准库分别实现了以上继承层次的的两个版本,分别面向 char 类型(如上)和 wchar_t 类型
后者采用和前者一样的命名规则,仅在每个类和对象名前加上字母w以示区别
⑵ IO对象不可赋值或赋值
⒉ 标准输入输出对象
extern istream cin; 标准输入流
extern ostream cout; 标准输出流
extern ostream cerr; 标准错误输出流
extern ostream clog; 标准日志输出流
⒊ 文件输入输出流
⑴ 使用 ifstream, ofstream 和 fstream 型对象可以实现对文件的读写
⑵ 可以调用公共成员函数 open 或在创建时使用构造函数使流对象关联到一个文件
二者都接受两个参数:一个C风格字符串表示文件名,一个可选的 ios_base::openmode 型值表示流打开模式
① openmode 是用以表示流打开模式标识的位掩码类型,支持位操作符
该类型对象的值可以是以下打开模式标识或它们之间进行位操作所得的结果
和以下(openmode 型)模式标志均为 ios_base 的公共成员
Ⅰ app (append)每次执行输出操作前都定位到流的末尾
Ⅱ ate (at end)打开时定位到流末尾
Ⅲ binary 在二进制(而非文本)模式下操作
Ⅳ in (input)允许输入操作
Ⅴ out (output)允许输出操作
Ⅵ trunc (truncate)抛弃流中现存的所有内容,打开时假定长度为0
(openmode 和上述标识分别是 ios_base 的公共成员类型和公共成员常量)
② fstream 默认使用 in | out 模式
ifstream 自动使用 in 模式
ofstream 自动使用 out 模式(效果上等同于 out | trunc)
⑶ 完成文件操作后可以使用公共成员函数 void close() 关闭
关闭后可以再次 open 新文件,但之前应调用 clear 清除该流的状态
流对象被析构时也会自动调用 close()
⒋ 字符串流
⑴ 常用于特定数据类型和格式化的字符串之间的相互转换
⑵ 3个类的构造函数各有带或不带 string 形参的两个不同版本
使用带 string 参数的版本,则创建储存该实参副本的字符串流对象
⑶ 3个类的都有公共成员函数 str,它的两个版本分别返回和设置与该流对象相关的 string 对象
string str() const;
返回与该流对象相关的 string 对象
string str(const string&);
将该流对象相关的 string 对象设置为实参的副本
⒌ 条件状态
⑴ 流对象内都用一个 iostate 型值表示条件状态
· iostate 是用以表示流错误状态标志的位掩码类型,支持位操作符
该类型对象的值可以是以下条件状态标识或它们之间进行位操作所得的结果
Ⅰ eofbit 输入操作中遇到文件结束符(同时会设置failbit)
Ⅱ failbit 输入操作失败(通常可恢复)
Ⅲ badbit 流被损坏(通常不可恢复)
Ⅳ goodbit 没有错误,值为0
(iostate 和上述标识分别是 ios_base 的公共成员类型和公共成员常量)
⑵ 查询条件状态
bool ios::eof() const;
eofbit位被设置则返回 true, 否则返回 false
bool ios::fail() const;
failbit 或 badbit 位被设置则返回 true, 否则返回 false
bool ios::bad() const;
badbit 位被设置则返回 true, 否则返回 false
bool ios::good() const;
流对象有效则返回 true, 否则返回 false
ios_base::iostate rdstate() const;
返回当前条件状态
⑶ 控制条件状态
void ios::clear( ios_base::iostate = goodbit);
使用参数值替换当前条件状态
void ios::setstate( ios_base::iostate );
将参数状态加入当前状态(如同使用了位或操作符|)
⑷ 可以直接检查流对象的真值来确认是否可用
⒍ 输出缓冲区的管理
每个IO对象都管理一个缓冲区,作为流和写入目标间的媒介
下面几种情况将导致输出流被刷新(即写入到真实的输出设备或者文件)
⑴ 程序正常结束或目标文件被关闭
注: 程序崩溃不会刷新缓冲区
调试崩溃的程序时如果用最后的输出定义错误位置,应确保缓冲区已刷新
因此输出时应多使用endl而非‘\n’
⑵ 当缓冲区满时会自动刷新
⑶ 使用操纵符显式刷新缓冲区
(以下均定义在<ostream>中)
① endl 输出换行符并刷新缓冲区
② flush 刷新缓冲区(不添加任何字符)
③ ends 输出空字符‘\0′并刷新缓冲区
注:cplusplus.com,cppreference.com和msdn上都没有表示ends会刷新缓冲区,存疑
⑷ 使用 unitbuf 操纵符可以设置流对象的相关格式状态标志,使缓冲区在每次插入操作后都刷新
使用 nounitbuf 操纵符可以恢复为正常的、系统控制的缓冲区刷新方式
⑸ 可以把流对象绑定到一个输出流对象,前者进行任何I/O操作都会刷新后者
① 可以使用 ios::tie 公共成员函数查询、修改绑定状态
ostream* ios::tie() const;
返回指向所绑定到的输出流对象的指针
ostream* ios::tie( ostream* );
绑定到参数中指针指向的输出流对象(实参为0则解除绑定),并返回指向原绑定对象的指针
② cin, cerr, clog 默认绑定到 cout, 而它们的宽字符版本则默认绑定到 wcout
⒎ 控制格式状态
istream/ostream(及它们的派生类)对象都支持使用提取操作符(>>)/插入操作符(<<),从流中提取/向流中插入格式化的对象数据
把提取/插入操作符和一些操纵符(manipulator)一起使用,可以改变流对象的特性或格式设置
其中除setbase,setprecision,setw,setfill定义在头文件<iomanip>中外,其余操纵符均定义在<ios>中
⑴ 布尔值格式
从流中提取/向流中插入布尔值时形式使用 0, 1(默认) 还是 false, true
· 使用操纵符 boolalpha noboolalpha
⑵ 整数格式
① 基数设置
从流中提取/向流中插入整数时使用八进制、十进制(默认)还是十六进制
· 使用操纵符 oct dec hex
· 使用操纵符 setbase(int) (实参只能是8,10或16)
② 基数前缀设置
向流中插入整数时是否显示基数前缀(八进制的0和十六进制的0x)(默认不显示)
· 使用操纵符 showbase noshowbase
③ 十六进制和科学计数法中字母的大小写设置
向流中插入整数时若使用十六进制或科学计数法,出现的字母使用小写(默认)还是大写
· 使用操纵符 uppercase nouppercase
⑶ 浮点数格式
① 精度设置
向流中插入浮点数精度为多少(默认为6)
· 使用 ios_base 的公共成员函数 precision 可以获得和设置流的浮点数精度
streamsize precision() const;
返回流对象的浮点数精度
streamsize precision( streamsize );
设置流的浮点数精度为实参值并返回先前的精度值
· 使用操纵符 setprecision( streamsize )
以上 streamsize 为表示流中大小的实现类型,是一个带符号基本整型的别名
注: 精度的解释在使用不同情况下不同
· 默认情况下解释为最大有效数字(位数不足不用小数末尾的零补齐)
· 在强制使用fixed,scientific或showpoint时解释为小数点后的确切位数(位数不足则用小数末尾的零补齐)
② 计数法设置
向流中插入浮点数时,让系统自动选择计数法(默认),还是强制指定为定点计数法或科学计数法
· 使用操纵符 fixed scientific
· 计数法不存在恢复默认的操纵符,但可以通过给成员函数 unsetf 传入常量 floatfield 达到目的
(unsetf 和 floatfield 均为 ios_base 的公共成员)
③ 小数点显示设置
向流中插入浮点数时,若小数部分为0,是否显示小数点和小数部分的0(默认不显示)
· 使用操纵符 showpoint noshowpoint
④ 非负数(整数和浮点数)正号设置
向流中插入非负数(包括0)时是否显示正号+ (默认不显示)
· 使用操纵符 showpos noshowpos
⑷ 对齐和填充格式
① 使用操纵符 setw( streamsize ) 可指定下次对流的插入操作的最小字段长度
注: 和endl一样,它不改变流的内部状态,只影响下一个输出
② 使用操纵符 setfill( char ) 设置向流中插入对象时用来填充字段的字符(默认为空格)
③ 字段内对齐方式设置(默认左对齐)
· 使用操纵符left right internal
关于internal:
- 对数值表示左对齐前缀(正负号和十六进制的0x)右对齐数值
- 对非数值则与 right 等效
⑸ 空白字符的处理
· 使用操纵符 skipws noskipws 设置从流中提取对象时是否忽略空白字符(默认忽略)
· 使用操纵符 ws 忽略输入序列中从当前位置开始尽可能多的空白字符,直到遇到非空白字符才停止
当然,如果已经(默认)设置了 skipws 则没有必要使用 ws
⒏ 无格式I/O操作
⑴ 单字节操作
① istream& get ( char& );
istream 的公共成员函数,从流中提取一个字符存入实参中
int get( );
无参数版本从流中提取一个字符并返回其值
② ostream& put ( char );
ostream 的公共成员函数,将字符参数值写入输出缓冲区并返回*this
③ istream& putback ( char );
istream 的公共成员函数,将字符参数值放回流中并返回*this
④ istream& unget ( );
istream 的公共成员函数,将流退回1字节并返回*this
⑤ int peek ( );
istream 的公共成员函数,读取并返回流中的下一个字符,但不提取它
注: 为允许返回EOF,put(无参数版本)和peek的返回值都为 int
⑵ 多字节操作
① istream& get (char* s, streamsize n, char delim );
istream 的公共成员函数,不断从流中提取字符并以字符串形式存入s指向首地址的数组,
直到出现以下情况之一:
- 已经提取了(n-1)个字符;
- 遇到了定界字符delim(如果不提供此参数则为‘\n’);
(被找到的定界字符不会被提取,而是继续留在流中作为下一个要被提取的字符)
- 到达文件末尾;
- 提取过程中发生错误;
最后返回*this.
注: 提取的字符以字符串的形式储存,故将自动添加结尾的‘\0′,而被提取的最大字符数也为(n-1)而非n
② istream& getline (char* s, streamsize n, char delim );
istream 的公共成员函数,与上面参数表相同的get版本类似,唯一区别在于定界字符会被提取并丢弃
③ istream& read ( char* s, streamsize n );
istream 的公共成员函数,从流中提取n个字符存入s指向首地址的数组,
直到出现以下情况之一:
- 已经提取了n个字符
- 到达文件末尾(eofbit和failbit会被设置)
- 提取过程中发生错误
最后返回*this.
注: 与get和getline不同,read不把提取的字符保存为字符串,故不会自动加上‘\0′
④ streamsize gcount ( ) const;
istream 的公共成员函数,返回上次无格式输入操作提取的字符个数
(peek, putback, unget不提取字符,故对此gcount返回0)
⑤ ostream& write ( const char* s , streamsize n );
ostream 的公共成员函数,把s指向首地址的数组的前n个字符写入输出流缓冲区
⑥ istream& ignore ( streamsize n = 1, int delim = EOF );
istream 的公共成员函数,从流中提取并抛弃字符,直到:
- 已经提取了n个字符或遇到了定界字符delim(该字符不会被提取)
最后返回*this.
⒐ 流的随机访问
⑴ 用于随机访问的成员函数
· pos_type tellg ();
pos_type tellp ();
返回输入/输出流中的标记当前的绝对位置
· istream& seekg ( pos_type pos );
ostream& seekp ( pos_type pos );
将输入/输出流中的标记重新定位至参数值表示的位置
· istream& seekg ( off_type off, ios_base::seekdir dir );
ostream& seekp ( off_type off, ios_base::seekdir dir );
将输入/输出流中的标记重新定位至距离dir偏移量为off的位置
⑵ 关于上述函数参数和返回值的类型
① pos_type和off_type都是类的成员类型,分别表示流中的标记位置和偏移量
后者可正可负,分别表示向前和向后偏移
② seekdir类型用来表示偏移的启示位置,其可能值如下
beg 流的开头
cur 流的当前位置
end 流的末尾
⑶ 以上tell和seek版本分别有两个版本g(get)和p(put)
其区别在于g版是istream类的成员,而p版是ostream类的成员
对于iostream对象,而者都适用,它们都操作同一个标记(而非输入输出各一个)
⑷ 普通iostream对象一般不允许随机访问,以上内容主要适用fstream和sstream
Tags:
cpp,
读书笔记