8.1 IO类


到目前为止,我们已经使用过的IO类型和对象都是操纵char数据的。默认情况下,这些对象都是关联到用户的控制台窗口的。当然,我们不能限制实际应用程序仅从控制台窗口进行I0操作,应用程序常常需要读写命名文件。而且,使用I0操作处理string中的字符会很方便。此外,应用程序还可能读写需要宽字符支持的语言。

为了支持这些不同种类的I0处理操作,在istream和ostream之外,标准库还定义了其他一些I0类型,我们之前都已经使用过了。下表列出了这些类型,分别定义在三个独立的头文件中: iostream 定义了用于读写流的基本类型,fstream 定义了读写命名文件的类型,sstream 定义了读写内存string对象的类型。

头文件类型
iostreamistream、wistream从流读取数据 ostream、wostream从流写入数据 iostream、wiostream 读写流
fstreamifstream、wifstream 从文件读取数据 ofstream、wostream 向文件写入数据 fstream、wfstream读写文件
sstreamistringstream、wistringstream从string读取数据 ostringstream、wostringstream向string写入数据,stringstream、wstringstream读写string

为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵wchar_ t类型的数据。宽字符版本的类型和函数的名字以一个w开始。例如,wcin、wcout和wcerr是分别对应cin、cout和cerr的宽字符版对象。宽字符版本的类型和对象与其对应的普通char版本的类型定义在同一个头文件中。例如,头文件fstream定义了ifstream 和wifstream类型。

IO类型之间的关系

设备类型和字符大小不会影响我们要执行的IO操作,这些操作的操作方法一致。能忽略不同流类型之间差异的原因是继承机制

IO对象无拷贝或赋值

不能拷贝赋值,不能作为形参或返回类型。
可以通过引用方式传递或者返回流,引用不能是const类型。

访问和操纵流的条件状态

状态类型

函数说明
strm::iostate提供表达流状态完整功能,作为一个位集合使用。
strm::badbit流已崩溃,发生系统级错误,流无法被使用,badbit置位时failbit也会置位
strm::failbit一个IO操作失败,可恢复错误
strm::eofbit流达到文件结束,eofbit和failbit同时置位
strm::goodbit流未处于错误状态,此值一直为零

流状态查询函数

函数说明
s.bad()badbit置位,返回true
s.fail()failbit置位,返回true
s.eof()eofbit置位,返回true
s.good()s有效状态,返回true,所有错误均未置位
s.rdstate()返回当前状态条件,返回值类型strm::iostate
  1. badbit表示发生系统级的错误,如不可恢复的读写错误。通常情况下一旦badbit被置位,流就无法再使用了。

  2. failbit 表示发生可恢复的错误,如期望读取一个数值,却读出一个字符等错误。这种问题通常是可以修改的,流还可以继续使用。

  3. 当到达文件的结束位置时,eofbit 和 failbit 都会被置位。(类似于置为true这种感觉由原本的False置为True)

  4. goodbit 被置位表示流未发生错误。如果badbit failbit 和eofbit 任何一个被置位,则检查流状态的条件会失败。

对应的bad(), fail(), eof(), good()能检查对应位是否被置位,返回1表示被置位。但是,badbit被置位时,fail()也会返回1。所以使用good()和fail()是确定流能否使用的正确方法。实际上,流当做条件使用的代码就等价于!fail()。而且eof() 和bad() 操作只能表示特定的错误。

//查询流没有出错的几种方法:
while(cin>>word){}
if(!cin.fail()){}
if(cin.good()){}

管理状态函数

函数说明
s.clear()所有条件状态位复位
s.clear(flags)流中对应条件位复位
s.rdstate()返回当前状态条件

管理输出缓冲

每个输出流关联一个缓冲区,保存程序读写数据。

刷新缓冲区(即数据真正写到输出设备当中)的几种情况:

  1. 程序正常结束,return操作结束时缓冲刷新会被执行。如果程序崩溃,缓冲区不会被刷新,数据可能会停留在输出缓冲区。
  2. 当缓冲区满,需要刷新缓冲。
  3. 使用endl显式刷新缓冲区
cout << 1 << endl;  //换行并刷新缓冲区
cout << 1 << flush;	//刷新缓冲区
cout << 1 << ends;	//插入空字符,刷新缓冲区
  1. 在每个输出操作之后,可以使用操纵符unitbuf设置流的内部状态,刷新缓冲区。默认情况下,cerr内部都设置了unitbuf,所以写道cerr当中的数据都是立即刷新的
cout<<unitbuf; //所有输出操作后会立即刷新缓冲区
cout<<noununitbuf; //回到正常缓冲方式
cerr<<1; //cerr设置为unitbuf,写到cerr的内容是立刻刷新的。
  1. 一个输出流关联到另外一个流。在这种情况下,当读写被关联的流的时候,关联到的流的缓冲区都会直接刷新。标准库将cin和cerr与cout关联在一起,读cin或者写cerr都会导致cout缓冲区刷新。
cin>>ival; //cout缓冲区刷新

通过tie可以将一个流与输出流进行关联,tie有两个重载的版本: 一个版本不带参数,返回指向输出流(绑定的)的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie的第二个版本接受一个指向ostream的指针,将自己关联到此ostream。即x. tie (&o)将流x关联到输出流

cout << &cout << endl;  //&cout
cout << cin.tie() << endl;	//&cout,因为标准库默认将cout绑定给cin,所以输出的是cout的地址。
ostream* oldtie = cin.tie(nullptr);//将空绑定给cin,即解开cout绑定给cin的地址,但值得注意的是此时oldtie不是新的空地址,而是原本的cout
cout << oldtie<< endl;  //&cout
cout << cin.tie() << endl; //nullptr
cin.tie(&cerr);
cout << cin.tie() << endl; //&cerr,并且此时解开cin与cout的绑定
cin.tie(oldtie);
cout << cin.tie() << endl; //&cout

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值