IO 库类型和头文件:
头文件 类型
iostream istream,wistream 从流读取数据
ostream,wostream 向流写入数据
iostream,wiostream 读写流
fstream ifstream,wifstream 从文件读取数据
ofstream,wofstream 向文件写入数据
fstream,wfstream 读写文件
sstream istringstream,wistringstream 从 string 读取数据
ostringstream,wostringstream 向 string 写入数据
stringstream,wstringstream 读写 string
条件状态:
strm::iostate strm是指一种IO类型,iostate是一种机器相关的类型,提供表达条件状态的完整功能。
strm::badbit 标志流已崩溃,致命的输入/输出错误,无法挽回
strm::failbit 标志IO操作失败了,非致命的输入/输出错误,可挽回
strm::eofbit 标志达到文件结尾
strm::goodbit 流未出现错误状态,此值保证为0
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit或badbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear() 将流的所有条件复位,状态设置为有效,返回void
s.clear(flags) 根据flags标志位,将s中对应条件状态复位,flags类型为strm::iostate。返回void
s.setstate(flags) 根据flags标志位,将s中对应条件状态置位,flags类型为strm::iostate。返回void
s.rdstate() 返回流的当前条件状态,返回类型为strm::iostate
状态位
1.4种条件状态
badbit 用来指出流已经崩溃,属于系统级错误,如不可恢复的读写错误。
failbit 表示一个io操作失败了,比如读取数字却读取的是字符,这是可以恢复的
eofbit 用来表示文件达到文件结尾,这也是可以恢复的
goodbit 表示流的状态正常
注意的是,一但流发生错误,其上后续的io操作都会失败,只有流属于无错状态时,我们才可以用来读取数据,写入数据。
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a;
cout<<cin.good()<<endl;//如果流正常返回1
cout<<cin.fail()<<endl; //failbit(输入错误,可以恢复)或者badbit(系统崩溃),则被置位。
cout<<cin.rdstate()<<endl;//流正常返回1
getchar();
cin>>b;//如果上次输入失常,这里就不能使用了。
return 0;
}
管理流当前状态
#include<bits/stdc++.h>
using namespace std;
int main(){
auto x=cin.rdstate();//rdstate返回当前状态,
cin.clear();//将状态恢复(可以在发生了可恢复错误的时候使用)
int a;
cin>>a;
cin.setstate(x);//将cin变成原来状态
return 0;
}
检查输入流当前的状态
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b=3;
cin>>a;
cin>>b;//不可用
if(cin.rdstate() == ios::goodbit)cout<<"this input is true"<<endl;
else if(cin.rdstate() == ios::failbit)cout<<"输入类型错误,可以通过清除缓冲区挽回、"<<endl;
cout<<b<<endl;
cin>>b;
cout<<b<<endl;
return 0;
}
#include <iostream>
using namespace std;
int main(void){
int a;
cin >> a;
cout << cin.rdstate() << endl;
cin.clear(ios::goodbit);//使cin有效
cout << cin.rdstate() << endl;
return 0;
}
管理输出缓冲:
每个输出流都管理一个缓冲区,用来保存程序读写的数据:
os << "please enter a value: ";
文本串可能立即打印出来,也有可能被操作系统保存在缓冲区,随后再打印。
会导致刷新缓冲区的原因:
- 程序正常结束,作为 main 函数的 return 的一部分,缓冲刷新被执行。
- 缓冲区满,需要刷新缓冲区,而后新的数据才能写入。
- 使用操纵符:endl 来显示刷新缓冲区。
- 每个输出操作后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,cerr 是设置 unitbuf 的,因此写到 cerr 中的数据都是立即刷新的。
- 一个输出流被关联到另一个流,此时,当读写被关联的流时,关联到流的缓冲区会被刷新。默认cin 和 cerr 都关联到 cout,因此读 cin 或写 cerr 都会导致 cout 的缓冲区被刷新。
endl 换行并刷新缓冲区;
ends 插入一个空字符并刷新缓冲区;
flush 仅刷新缓冲区;
#include <iostream>
using namespace std;
int main(void){
cout << unitbuf;//所有输出操作后都会立即刷新缓冲区
//任何输出都立即刷新,无缓冲
for(int i=1;i<=50000;i++)cout<<i;
cout << nounitbuf;//回到正常的缓冲方式
for(int i=1;i<=50000;i++)cout<<i;
//令人疑惑的是为什么两种方式的时间差不多,有时候正常的换缓冲方式更慢。
return 0;
}
刷新缓冲区的方式
#include <iostream>
using namespace std;
int main(void){
cout<<"ghq"<<ends;//输出空格并刷新缓冲区
cout<<"ghq"<<endl;//输出换行并刷新缓冲区
cout<<"ghq"<<flush;//刷新缓冲
return 0;
}
关联输入和输出流:
当一个输入流关联到一个输出流时,任何试图从输入流读取数据的操纵都会先刷新关联的输出流。标准库将 cout 和 cin 关联到一起,因此:cin >> val;导致 cout 的缓冲区被刷新。
- tie是将流关联到另一个流的函数,C++中定义如下:
tie 有两个重载版本:一个版本不带参数,返回指向输出流的指针。如果本对象关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie 的第二个版本接受一个指向 ostream 的指针,将自己关联到 ostream。即,x.tie(&o) 将流 x 关联到输出流 o。
我们既可以将一个 istream 对象关联到另一个 ostream,也可以将一个 ostream 关联到另一个 ostream:
#include <iostream>
using namespace std;
int main(void)
{
cin.tie(&cerr);//直接将cin由和cout关联改成和cerr关联
cin.tie(&cout);//将输入流cin关联到输出流cout
ostream *old_tie = cin.tie(nullptr);//cin不再与其他流关联
cin.tie(&cerr);//将cin关联到cerr,读取cin会刷新cerr而非cout
cin.tie(old_tie);//重建cin和cout之间的关联
return 0;
}
注意:每个流同时最多关联到一个流,但多个流可以同时关联到一个 ostream。
·
·
·
·
·
靡不有初鲜克有终。