IO类的条件状态
IO库定义了:
- iostate类型,提供表达流状态的完整功能
- 4个 iostate类型的constexpr 值,用来表达特定的位模式。
常量 | 含义 | failbit标记位的值 | eofbit标记位的值 | badbit标记位的值 | 转化为10进制 |
---|---|---|---|---|---|
failbit | 输入(输出)流出现非致命错误,可挽回 | 1 | 0 | 0 | 4 |
eofbit | 已到达文件尾 | 0 | 1 | 0 | 2 |
badbit | 输入(输出)出现致命错误,不可挽回 | 0 | 0 | 1 | 1 |
goodgit | 流状态完全正常 | 0 | 0 | 0 | 0 |
转化为10进制
如果到达文件的末尾,eofbit和failbit都会被置位。
bad、fail、eof任意一个被置位,检测流状态的条件会失败。
- iostate 类型constexpr值的返回值:
good 在所有错误均为置位返回 true
bad、eof、fail 则在对应错误被置位时返回true
bad被置位时,fail也会返回true;
所以使用fail、good用于确定流状态的正确方法,eof和bad只用于表示特定错误。
- 管理条件状态
流对象中定义了一些成员函数。
- rdstate(),返回一个iostate值,对应流的当前状态。
- setstate():将给定条件位置位,表示发生了相应的错误。
- clear():是一个重载函数,有不接受参数和接收参数两个版本。
不接受参数的版本:清除(复位)所有的错误标志位,执行clear()后,good返回true
含参数的clear接受一个iostate值,表示流的状态。表示新的流状态。
int main() {
//cin>>1;输出 0;
//cin>>q;输出 2;
int a; cin >> a;
auto old_state = cin.rdstate();
cout << old_state;
return 0;
}
管理输出缓冲区
每个输出流都管理者一个缓冲区,用来保存程序读写的数据。
- 什么是缓冲区?
cout通过ostream连接到输出设备上(显示器等)。
当有数据要输出的时,cout先通过ostream将数据写入缓冲区,当缓冲区写满或流关闭的时候,数据将被发送到输出设备上(被显示)。而刷新缓冲区,不管缓冲区有没有被写满,数据直接被发往输出设备。
通过缓冲机制,操作系统可以将程序的多个输出操作组合成单一的系统级写操作。由于设备的写操作可能很耗时,允许操作系统将多个输出程序组合为单一的设备写操作可以带来很大的性能提升。
- 导致缓冲刷新(数据真正写道输出设备或文件)的原因有很多。
- 程序正常结束,作为main函数的renturn操作的一部分,缓冲刷新被执行。
- 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区
- 可以使用操纵符如endl来显示地刷新缓冲区
- 在每个输出操作之后,可以用unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对
cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的- 一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout。因此,读cin或写cerr都会导致cout的缓冲区被刷新
————————————————————————————————————————————
摘自C++primer 5th p281
- 刷新输出缓冲区
可以使用操作符endl、ends、flush
符号 | 功能 |
---|---|
endl | 输出换行,然后刷新缓冲区 |
flush | 刷新缓冲区,不附加任何字符 |
ends | 输出一个空字符,然后刷新缓冲区 |
如果想在每次输出操作之后都刷新缓冲区,我们可以使用unitbuf操纵符,它表示接下来每次写操作之后都执行一次flush(写操作就是写到输出设备中)。
- 关联输入和输出流
当一个输入流被关联到一个输出流的时候,任何试图从输入流读取数据的操作都会先刷新关联的输出流,**标准库将cout与cin关联在一起。
语句cin>>ival
语句会先刷新cout的缓冲区,再进行cin的输入。
文件输入输出
语句 | 作用 |
---|---|
fstreaam fstrm; | 创建一个未绑定的文件流,fstream是一个类型 |
fstream fstrm(s); | 创建一个fstream,并打开名为s的文件。s可以是string字符串也可以是指向C风格字符串的指针。构造函数为explicit,mode依赖于fstream类型 |
fstream fstrm(s,mode)’ | 与上面相似,按照mode打开文件 |
fstrm.open(s) | 打开名为s的文件,并于fstrm绑定。返回void |
fstrm.close() | 关闭与fstrm绑定的文件 |
fstrm.is_open() | 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭 |
- getline()函数的使用
getline(cin,StringName);
cin是输入流,之后的StringName是接收输入流的容器。
在输入文件的时候,要记得使用if语句检查文件是否成功读取的好习惯。
string infile;
fstream in(infile);
if(in){...;}//养成检查文件是否读入的好习惯!!
else
cout<<"something wrong happened"<<endl;
- 文件模式
名称 | 含义 |
---|---|
in | 以读方式打开 |
out | 以写方式打开 |
app | 每次写操作前军定义到文件末尾 |
ate | 代开文件后立刻定位到文件末尾 |
trunc | 截断文件 |
binary | 以二进制进行IO |
以out代开文件会丢弃已有数据
默认情况下打开ofstream时文件会被清空(覆盖然后填充新内容)。阻止其清空的方式是同时指定app模式。
ofstream app("file.1",ofstream::app);