C++ 不直接处理IO,而是通过standard library 中的一些types来handle在files、console windows、及内存中的io。
8.1 IO 类
IO定义了三个独立的头文件 分别用于读写流的基本类型、命名文件、内存,分别是iostream fstream sstream。标准库能通过继承机制使我们忽略这些不同类型的流之间的差异,例如类型ifstream istringstream 都继承自istream。
下面是标准库流的一些特性
8.1.1 IO对象无拷贝或赋值
8.1.2 条件状态
IO类定义了一些函数和标志,来帮助我们访问和操纵流的条件状态(condition state)。
badbit :系统级错误,不可修复,(此时failbit也会被置位)
failbit :可以修复的错误
eofbit :文件结束(此时failbit也会被置位)
管理条件状态
//复位failbit/badbit,其他不变
cin.clear(cin.rdstate()&~cin.failbit&~cin.badbit);
8.1.3管理输出缓冲
缓冲区刷新的原因:
- 程序结束,注意如果是崩溃不会被刷新
- 缓冲区满
- endl等
- unitbuf清空,cerr默认设置unitbuf,如果想要在每次输出都会刷新缓冲区就使用cout<
endl//输出缓冲区+换行
flush//输出缓冲区
ends//输出缓冲区+空格
关联输入和输出流
tie是关联的关键字
cin.tie(&out);//输入与输出关联
ostream *old_tie=cin.tie(nullptr);
每个流同时最多关联到一个流,但是多个流可以同时关联到同一个ostream。
8.2 文件输入和输出
8.2.1 使用文件流对象
ifstream in(ifile);//构造一个ifstream并且打开给定文件
当一个fstream对象被销毁时,close会自动被调用
8.2.2 文件模式
in
out
app
ate
trunc
binary
这些标识符可以被组合使用,中间以”或”操作符(|)间隔。
8.3 string 流
8.3.1 使用istringstream
//P288
string line,word;
vector <PersonInfo> people;
while (getline(cin,line)){
PersonInfo info;
istringstream record(line);//record 是一个istringstream对象 绑定line
record >>info.name;//读取名字
while (record>>word)
info.phones.push_back(word);
people.push_back(info);
8.3.2 使用ostringstream
对每个人,验证完所有的电话号码之后进行输出操作
for (const auto &entry :people){
ostringstream formatted,badNums;
for (const auto &nums:entry.phones){
if (!valid(nums)){
badNums<<""<<nums;//将数的字符串形式存入badNums
}else
formatted<<""<<format(nums);
}
if (badNums.str().empty())
os<<entry.name<<" "
<<formatted.str()<<endl;
else
cerr<<"input error:"<<entry.name
<<"invalid number(s)"<<badNums.str()<<endl;
}
以上的写入操作,实际上是转换为string操作。