现在,《C++ Primer》的第一部分“The Basics”已经学习完毕。
可以进入第二部分的学习啦!
不同的IO操作之间的一致性,是通过继承来实现的。
ifstream和istringstream继承自istream,getline函数和>>、<<操作符都可以用。
IO对象不可复制,不可赋值,因此它们也不能作为参数或返回值。
要使用它们实现参数或返回值的功能的话,就使用引用。
对IO对象进行读写会改变它们的状态,因此也不能把它们设置为const。
对IO对象的操作天生容易出错,因此IO类提供了函数和标志位,可以访问和操作stream的状态:
strm::iostate
strm::badbit
strm::failbit
strm::eofbit
strm::goodbit
s.eof()
s.fail()
s.bad()
s.good()
s.clear()
s.clear(flags)
s.setstate(flags)
s.rdstate()
如果在期望输入一个int时输入了一个无意义的字符串,或者输入END-OF-FILE,cin都会出错。
一个输入出错之后,其他跟随的输入也会fail。
只有在非错误状态下,stream才能被读写,因此通常在使用它时要测试它的状态:
while (cin >> word)
strm::iostate是标志位的综合,它的某些位代表了特殊的含义,比如:
strm::badbit,系统级的失败,比如不可恢复的读写错误,通常它置位之后stream无法再操作。
strm::failbit,可恢复的错误,比如想读取数字的时候读到了字符,一般可以继续使用。
strm::goodbit,当它为0的时候,意味着没有发生任何错误。
实际使用的时候,调用good()或者bad()函数来获取状态。
----------------
Managing the Output Buffer
一般来说,输出不会立刻刷新,而是会等待几条再一起print,这样节省对设备的操作时间。
什么时候会刷新呢?
• 程序正常结束,输出缓冲会被刷新。
• 缓冲区满了。
• 使用manipulator,比如endl显式的刷新。
• 使用unitbuf manipulator,比如cerr就使用了它,每次写入每次刷新。
• 将outstream绑定到其他stream,比如将cout绑定到cin和cerr上,执行cin或cerr即可。
除了endl之外,我们还可以使用另外两个刷新的manipulator:
cout << "Hi." << flush;
cout << "Hi." << ends;
flush会刷新但不会增加某尾的换行符;
ends会刷新而且会增加一个' '符号。
如何使用unitbuf?
cout << unitbuf;
cout << nounitbuf;
如果程序崩溃的话,输出缓冲是不会被刷新的。
因此如果我们想确保某条信息一定会被打印,就要使用立即刷新的方式。
IO库将cout绑定到了cin上,因此只要执行cin,cout一定会被刷新:
cin >> ival;
一般来说,交互式的系统都会将cin绑定到cout上,这样等待cin的时候,会提前将prompts刷新。
tie有两种可重载的函数:
第一种是没有参数的函数,它返回指向被tie的那个output stream的指针;
第二种是含有参数的函数,它将被tie的作为指针,tie在自身上,比如
cin.tie(&cout); //将cout绑定到cin上
每个stream只能tie到最多一个stream上。
多个streams可以tie到同一个stream上。
----------------
File Input and Output
文件IO继承了前面的标准IO,同时添加了自己独特的内容:
fstream fstrm; //创建一个文件流
fstream fstrm(s); //创建一个名称为s的文件流
fstream fstrm(s, mode); //创建一个名称为s、模式为mode的文件流
fstrm open(s); //打开文件s,并绑定到fstrm流上
fstrm.open(s, mode); //以模式mode打开文件s,并绑定到fstrm流上
fstrm.close(); //关闭fstrm绑定的文件
fstrm.is_open(); //检查现在绑定在fstrm上的文件是否正常打开
创建一个文件流,打开或不打开文件:
ifstream in(ifile);
ofstream out;
当stream对象退出自己的作用域时,文件也会自动关闭。
文件的mode有下面这几种:
in //打开作为输入,仅用做ifstream或fstream
out //打开作为输出,仅用做ofstream或fstream
app //每次写都寻找末尾
ate //打开就寻找末尾
trunc //截短文件truncate,仅用做out
binary //使用二进制来操作文件
输入流是指将文件的内容读到程序中,输出流是指将程序的内容写入文件。
由于打开的时候写在文件头上,因此它本来的内容会丢失。
要避免这种情况,需要显式的指定app mode,文件的mode在每次打开时确定。
----------------
string streams
string streams的声明在文件sstream中,它定义了三种数据类型。
string streams将string当作in-memory的文件。
istringstream读取一个字符串,ostringstream写入一个字符串,
stringstream读取或写入一个字符串。
sstream strm; //一个未绑定的stringstream
sstream strm(s); //strm持有一个string s,这个构造函数是explicit
strm.str(); //返回一个string的copy
strm.str(s); //将string复制进strm,返回void