操纵符 是一个函数或一个对象,会影响流的状态,并能用作输入或输出的运算符的 运算对象(操作数)(a manipulator is a function or object that can be used as an operand to an input or output operator.)
第8章 标准IO库
8.1 面向对象的标准库
sstream所定义的类型用于读写 存储在内存中 的string对象,如果函数有 基类的引用形参 时,可以给函数传递其派生类型的对象,IO类型通过继承关联,所以可以只编写一个函数,将它应用到三种类型的流上:控制台、磁盘文件或字符串流
流类(stream class)读写的是由char类型组成的流,标准库还定义了一组相关的类型,支持wchar_t类型,每个类都加上w前缀,以此与char类型的版本区分,基于流的wchar_t类型的类和对象在iostream中定义,宽字符文件流类型在fstream中定义,宽字符stringstream在sstream中定义
标准库类型不允许做复制或赋值操作:只有支持复制的元素类型可以存储在vector或其他容器类型里,不存在存储流对象的容器,形参或返回类型也不能为流类型,如果需要传递或返回IO对象,必须传递或返回指向该对象的指针或引用
8.2 条件状态
IO标准库管理一系列条件状态成员,来标记给定的IO对象是否处于可用状态,或者碰到了哪种特定的错误,流必须处于无错误状态,才能用于输入或输出,检测流是否可用的最简单的方法是检查其真值
所有流对象都包含一个条件状态成员,由setstate和clear操作管理,这个状态成员为iostate类型,是由各个iostream类分别定义的机器相关的整形,该状态成员以二进制位的形式使用,每个IO类还定义了三个iostate类型的常量值,分别表示特定的位模式 (按位或操作使用其操作数的二进制位模式产生一个整形数值),badbit标志着系统级的故障,如无法恢复的读写错误
流状态的查询和控制:
#include <iostream> using namespace std; int main() { int ival; //循环不断读入cin,直到到达文件结束符或者发生不可恢复的读取错误为止 while( cin>> ival, !cin.eof() ){ if( cin.bad()) //input stream is corrupted throw runtime_error("IO stream corrupted"); if( cin.fail()){ //bad input cerr << "bad data, try again"; cin.clear(istream::failbit); //reset the stream continue; //get next input } cout << ival; } return 0; }
8.3 输出缓冲区的管理
每个IO对象管理一个缓冲区,用于存储程序读写的数据,下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或文件:1、程序正常结束;2、在一些不确定的时候,缓冲区可能已经满了,在这种情况下,缓冲区会在写下一个值之前刷新;3、用操纵符显式地刷新缓冲区,如:endl;4、在每次输出操作执行完后,用unitbuf操纵符设置流的内部状态,从而清空缓冲区;5、可将输出流与输入流关联起来,在这种情况下,在读输入流时,将刷新其关联的输出缓冲区
8.4 文件的输入和输出
fstream头文件定义了三种支持文件IO的类型:ifstream、ofstream、fstream
#include <iostream> #include <fstream> //ifstream ofstream #include <string> //string using namespace std; ifstream& open_file( ifstream& in, const string& file) { in.close(); //不清楚流in的当前状态,首先调用close和clear将这个流设置为有效状态 in.clear(); in.open( file.c_str() ); //打开文件 return in; //已经与指定文件绑定,或处于错误条件状态 } int main() { ifstream in; open_file( in, "d:/1.txt" ); //函数调用 string line; while( in >> line) //每次读取,空白符为结束标志 cout << line << " "; /* while( getline(in,line) ) cout << line << " "; */ in.close(); return 0; }
文件模式:in out app ate trunc binary ,ate模式只在打开时有效(in 与 ate 合用,ios::ate | ios:: in),文件打开后将定位在文件尾,以out模式打开的文件会被清空:丢失该文件存储的所有数据,等效于同时指定了out和trunc模式
#include <iostream> #include <fstream> //ifstream ofstream #include <string> //string using namespace std; int main() { ofstream ofs; ofs.open( "d:/1.txt", ofstream::app ); //文件模式 in out app ate trunc binary string line; while( getline(cin,line) ){ ofs << line; } ofs.close(); return 0; }
8.5 字符串流
iostream标准库支持内存中的输入输出,只要将流与存储在程序内存中的string对象捆绑起来即可,标准库定义了三种类型的字符串流istringstream ostringstream stringstream
#include <iostream> #include <sstream> //istringstream ostringstream stringstream(读写) #include <string> //string using namespace std; int main() { //------------------写----------------------// string line; int val1 = 512, val2 = 1024; ostringstream format_message; //写 format_message << "val1: " << val1 << "\n" << "val2: " << val2 << "\n"; //将指定内容插入到ostringstream对象,重点在于int型值自动转换为等价的可打印字符串 line = format_message.str(); //返回ostringstream对象format_message中存储的string类型对象 cout << line; //------------------读-----------------------// int val3, val4; string dump; istringstream input_istring ( format_message.str()); //读 input_istring >> dump >> val3 >> dump >> val4; cout << val3 << " " << val4 << endl; return 0; }
#include <iostream> #include <sstream> //istringstream ostringstream stringstream(读写) #include <string> //string using namespace std; int main() { string line = "123a 456b 789c", word; istringstream stream( line ); //istringstream由 istream 派生读 string while(stream >> word ){ int x = atoi( word.c_str() ); cout << x << endl; } return 0; }