概述
先不要急着知道怎么用这个玩意,让我们一起先来看一看C++标准IO库的框架,其实挺有意思的!那就开始吧!
C++的输入输出由标准库提供,标准库提供了一族类型,支持对文件、string对象、和控制窗口等设备的读写。一方面,这些IO类型都定义了如何读写内置类型的的值,另一方面,用户在设计类时可以仿照IO标准库设施读写内置类型的方式设计自己的输入输出操作。
1. 面向对象的IO库
面向对象是C++的一大特色,他的标准库自然也不例外,统统都是面向对象设计的。标准库使用了继承(inheritance)来定义一组面向对象(object-oriented)类。IO类型定义在三个独立的头文件中:iostream定义读写控制窗口的类型;fstream定义读写已命名文件的类型;sstream定义读写存储在内存中的string对象的类型。各头文件包含的类型及其含义以及各类型之间的继承关系如下图:
注意:
- 以上所讲的流类型(stream class)读写的是由char类型组成的流。除此之外,标准库还定义了一组相关的类型,支持wchar_t类型。即,每个类名前都加上“w”前缀,以此与char类型的版本区别开来。
- IO对象不允许复制和赋值:因此流对象不可以存储在vector或其他容器里;函数形参和返回类型也不可以是流类型。
2. 标准IO库定义的------条件状态
标准IO 库管理一系列条件状态(condition state)成员,用来标记给定的 IO 对象是否处于可用状态,或者碰到了哪种特定的错误。如下列出了标准库定义的一组函数和标记,提供访问和操纵流状态的手段。
strm::iostate 这是机器相关的整型别名,代表一种类型,由各个io类定义,用于定义条件状态(strm在这里代表各个流类型)。
strm::badbit strm::iostate类型的值,用于指出被破坏的流。
strm::failbit strm::iostate类型的值,用于指出失败的 IO 操作。
strm::eofbit strm::iostate类型的值,用于指出流已经到达文件结束符。
s.eof() 返回eof标志位的值,真或假。
s.fail() 返回fail标志位的值,真或假。
s.bad() 返回bad标志位的值,真或假。
s.good() 检测流s的有效性,当eof,fail,bad都不为真时good标志位有效,调用good()函数返回真值。
s.clear() 将流s中的所有状态值都重设为有效状态。
s.clear(flag) 将流s中的某个指定条件状态置为有效,flag是strm::iostate类型的条件状态,若括号内不写具体条件状态则将所有条件状态全部设置有效。
s.setstate(flag) 给流添加指定条件,设置flag位为触发状态,flag是strm::iostate类型对象。
s.rdstate() 返回流s的当前条件,返回值类型为strm::iostate。
总结-----条件状态:
- 所有流对象都包含一个条件状态成员,他是strm::iostate类型的对象,以二进制位的形式使用。
- failbit, eofbit, badbit和goodbit是四个strm::iostate类型的常量值,他们本身分别表示一种条件状态,具体如下表:
常量 含义 fail标志位 oef标志位 bad标志位 ios::badbit 输入(输出)流出现致命错误,不可挽回 0 0 1 ios::eofbit 已达到文件结束 0 1 0 ios::failbit 输入(输出)流出现非致命错误,可挽回 1 0 0 ios::goodbit 流状态完全正常 0 0 0
- badbit, eofbit, failbit,goodbit构成了四个基本流状态。
- 用cout检测goodbit, badbit, eofbit, failbit的值分别是0,1,2,4,这与上面的表格不是正好完全对应着吗,呵呵(goodbit:0000 0000; badbit:0000 0001;eofbit:0000 0010; failbit:0000 0100)。
- 可使用clear和setstate来操作和管理条件状态成员,他们常与badbit,eofbit,failbit,goodbit以及位或“|”结合起来使用。
- 用bad(), fail(), eof()和good()操作可以检测流状态是否属于,还可以用rdstate()来返回整个条件状态成员。
2.1 rdstate的使用:
rdstate成员函数返回一个iostate类型的值,前面已经说过,这是一个与机器相关的整型,该值对应于流的整个条件状态。如下代码:(摘自cplusplus.com)
// getting state of stream object
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
ifstream is;
is.open ("test.txt");
if ( (is.rdstate() & ifstream::failbit ) != 0 ) //检测fail标志位是否被设置,即是否遇到错误
cerr << "Error opening ‘test.txt‘\n"; return 0;
}
2.2 clear的使用:
clear用于设置标志位而不是清除标志位,即按照实参设置流状态,强制覆盖原有状态,其工作方式有两种:
- 带有failbit, eofbit, badbit,goodbit中的一个或多个作为参数,按照具体实参设置流对象,例如goodbit作实参时就设置流状态各位为0。
- 不带参数,即默认状态,效果如同带goodbit作为参数,会将所有标志位设置为有效。
// clearing errors #include <iostream> #include <fstream> using namespace std; int main () { char buffer [80]; fstream myfile; myfile.open ("test.txt",fstream::in); myfile << "test"; if (myfile.fail()) { cout << "Error writing to test.txt\n"; myfile.clear(); } myfile.getline (buffer,80); cout << buffer << " successfully read from file.\n"; return 0; }
2.3 setstate的使用:
setstate用于设置标志位状态,与clear的区别在于它只是在原有状态的基础上以叠加的方式更新实参对应状态标志,而不会强制覆盖原有状态,使用方式:
- 传递一个strm::iosatate类型的参数(可以是单个的,也可以是用“位或”连接的多个iostate对象)
3. 输出缓冲区的管理-----关键在于控制如何刷新缓冲区
每一个IO对象管理一个缓冲区,用于存储程序读写的数据。缓冲区的刷新会使其中的内容写入到真实的输出设备或文件中。以下情况都会导致缓冲区被刷新:
- 程序正常结速时,将清空所有输出缓冲区。
- 在一些不确定的时候,缓冲区可能已经满了,这种情况下,缓冲区将会在写入下一个值之前刷新缓冲区。
- 用操纵符(endl, ends,flush)显式地刷新缓冲区:
cout<<"Hi!"<<endl; //插入换行符,并刷新缓冲区
cout<<"Hi!"<<ends; //插入空格字符null,并刷新缓冲区
cout<<"Hi!"<<flush; //仅仅刷新缓冲区,不插入任何其他字符
- 用unitbuf操纵符设置流的内部状态,使得流在每次输出操作执行完都清空缓冲区,恢复系统默认管理方式用nounitbuf。
cout<<unitbuf<<"first"<<"second"<<"third"<<nounitbuf; //等价于cout<<"first"<<flush<<"second"<<flush<<"third"<<flush;
- 使用tie函数将输出流与输入流关联起来,当输入流与输出流绑定在一起的时候,任何输入操作都将首先刷新其输出流关联的缓冲区。
补充------------tie函数的使用:
tie函数可以由istream或ostream对象调用,使用一个ostream流对象的指针做形参。
- cin.tie(&cout);//将cin和cout绑定在一起,cin>>ival;时将导致cout所关联的缓冲区被刷新。
- ostream *old_tie=cin.tie(); //不传递参数时,返回当前绑定的对象
- cin.tie(0); 接受0作为参数时,解除当前绑定
本文只作为C++标准IO库的基础概括,文件、string对象、和控制窗口的具体IO操作方法,将另外撰文,链接如下:
C++中的文件输入输出:http://blog.csdn.net/miss_acha/article/details/7194695
原文地址:https://www.cnblogs.com/daniumeng/p/9302489.html