经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
《C++ Primer》笔记 第8章 IO库
来源:cnblogs  作者:橘崽崽啊  时间:2021/1/25 11:23:25  对本文有异议
  1. iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。
  2. 标准库使我们能忽略这些不同类型的流之间的差异,这是通过继承机制实现的。
  3. 由于不能拷贝IO对象,因此我们也不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的
  4. IO库条件状态
状态 解释
strm::iostate strm是一种IO类型,iostate是一种机器相关的类型,提供了表达条件状态的完整功能。IO库定义了4个iostate类型的constexpr值,表示特定的位模式。
strm::badbit 二进制值为100,用来指出流已崩溃
strm::failbit 二进制值为010,用来指出一个IO操作失败了
strm::eofbit 二进制值为001,用来指出流已到达了文件结束
strm::goodbit 用来指出流未处于错误状态。此值保证为零
s.eof() 若流s的eofbit置位(置1),则返回true
s.fail() 若流s的failbitbadbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear() 将流s中所有条件状态位复位(置0),将流的状态设置为有效。返回void
s.clear(flags) 根据给定的flags标志位,将流s中对应条件状态位置位。flags的类型为strm::iostate。返回void
s.setstate(flags) 根据给定的flags标志位,将流s中对应条件状态位置位。flags的类型为strm::iostate。返回void
s.rdstate() 返回流s的当前条件状态,返回值类型为strm::iostate
  1. #include<iostream>
  2. #include<string>
  3. using namespace std;
  4. istream& func(istream& is)
  5. {
  6. int v;
  7. while (is >> v, !is.eof()) // 直到遇到文件结束符才停止读取
  8. {
  9. if (is.bad())
  10. {
  11. cerr << "Bad Error!\n";
  12. break;
  13. }
  14. else if (is.fail())
  15. {
  16. cerr << "Wrong Data! Please try again!\n";
  17. is.clear();
  18. is.ignore(1024, '\n');
  19. continue;
  20. }
  21. cout << v << endl;
  22. }
  23. is.clear();
  24. return is;
  25. }
  26. int main()
  27. {
  28. func(cin);
  29. return 0;
  30. }
  1. badbit表示系统级错误,如不可恢复的读写错误。通常情况下,一旦badbit被置位,流就无法再使用了。在发生可恢复错误后,failbit被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可以修正的,流还可以继续使用。如果到达文件结束位置,eofbit和failbit都会被置位。goodbit的值为0,表示流未发生错误。如果badbit、failbit和eofbit任一个被置位,则检测流状态的条件会失败。
  2. 在badbit被置位时,fail也会返回true。这意味着,使用good或fail是确定流的总体状态的正确方法。实际上,我们将流当作条件使用的代码就等价于!fail()。而eof和bad操作只能表示特定的错误。
  3. 下面的代码将failbitbadbit复位,但保持eofbit不变:
    1. // 复位failbit和badbit,保持其他标志位不变
    2. cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);
    3. /*
    4. * clear和setstate的区别:
    5. * clear用实参值强制覆盖当前流的条件状态(不论是0还是1)
    6. * setstate将实参值(置1的位)叠加到当前流的条件状态
    7. */
  4. 导致缓冲刷新的原因:
    • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
    • 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
    • 我们可以使用操纵符endl来显式刷新缓冲区
    • 在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
    • 一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout,因此,读cin或写cerr都会导致cout的缓冲区被刷新。
  5. 操纵符endl完成换行并刷新缓冲区的工作。flush刷新缓冲区,但不输出任何额外的字符。ends向缓冲区插入一个空字符('\0'),然后刷新缓冲区。
  6. 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制:
    1. cout << unitbuf; // 所有输出操作后都会立即刷新缓冲区
    2. // 任何输出都立即刷新,无缓冲
    3. cout << nounitbuf; // 回到正常的缓冲方式
  7. 如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
  8. 当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。
  9. 交互式系统通常应该关联输入流和输出流。这意味着所有输出,包括用户提示信息,都会在读操作之前被打印出来。
  10. tie有两个重载的版本:一个版本不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie的第二个版本接受一个指向ostream的指针,将自己关连到此ostream,并返回上一个绑定的输出流指针。
  11. 我们既可以将一个istream对象关联到另一个ostream,也可以将一个ostream关联到另一个ostream。每个流同时最多关联到一个流,但多个流可以同时关联到同一个ostream
    1. cin.tie(&cout); // 仅仅是用来展示:标准库将cin和cout关联在一起
    2. // old_tie指向当前关联到cin的流(如果有的话)
    3. ostream *old_tie = cin.tie(nullptr); // cin不再与其他流关联
    4. // 将cin与cerr关联;这不是一个好主意,因为cin应该关联到cout
    5. cin.tie(&cerr); // 读取cin会刷新cerr而不是cout
    6. cin.tie(old_tie); // 重建cin和cout间的正常关联
  12. fstream特有的操作
操作 解释
fstream fstrm; 创建一个未绑定的文件流。fstream是头文件fstream中定义的一个类型
fstream fstrm(s); 创建一个fstream,并打开名为s的文件。s可以是string类型,或者是一个指向C风格字符串的指针。这些构造函数都是explicit的。默认的文件模式mode依赖于fstream的类型。
fstream fstrm(s, mode); 与前一个构造函数类似,但按指定mode打开文件
fstrm.open(s) 打开名为s的文件,并将文件与fstrm绑定。s可以是一个string或一个指向C风格字符串的指针。默认的文件mode依赖于fstream的类型。返回void
fstrm.close() 关闭与fstrm绑定的文件。返回void
fstrm.is_open() 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭
  1. 在要求使用基类型对象的地方,我们可以用继承类型的对象来替代。这意味着,接受一个iostream类型引用(或指针)参数的函数,可以用一个对应的fstream(或sstream)类型来调用。
  2. 如果调用open失败,failbit会被置位。因为调用open可能失败,进行open是否成功的检测通常是一个好习惯。
    1. if (out) // 检查open是否成功
    2. // open成功,我们可以使用文件了
  3. 一旦一个文件流已经打开,它就保持与对应文件的关联。为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件。一旦文件成功关闭,我们可以打开新的文件。
    1. in.close() // 关闭文件
    2. in.open(ifile + "2"); // 打开另一个文件
  4. 当一个fstream对象被销毁时,close会自动被调用。
  5. 每个流都有一个关联的文件模式,用来指出如何使用文件。
模式 解释
in 以读方式打开
out 以写方式打开
app 每次写操作前均定位到文件末尾
ate 打开文件后立即定位到文件末尾
trunc 截断文件
binary 以二进制方式进行IO
  1. 指定文件模式有如下限制:
    • 只可以对ofstream或fstream对象设定out模式
    • 只可以对ifstream或fstream对象设定in模式
    • 只有当out也被设定时才可设定trunc模式
    • 只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显式指定out模式,文件也总是以输出方式被打开
    • 默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断。为了保留以out模式打开的文件的内容,我们必须同时指定app模式,这样只会将数据追加写到文件末尾;或者同时指定in模式,即打开文件同时进行读写操作。
    • ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。
  2. 保留被ofstream打开的文件中已有数据的唯一方法是显式指定app或in模式
  3. 在每次打开文件时,都要设置文件模式,可能是显式地设置,也可能是隐式地设置。当程序未指定模式时,就使用默认值。
  4. stringstream特有的操作
操作 解释
sstream strm; strm是一个未绑定地stringstream对象。sstream是头文件sstream中定义的一个类型
sstream strm(s); strm是一个sstream对象,保存string s的一个拷贝。此构造函数是explicit的
strm.str() 返回strm所保存的string的拷贝
strm.str(s) 将string s拷贝到strm中。返回void
  1. #include<iostream>
  2. #include<sstream>
  3. #include<string>
  4. #include<vector>
  5. using namespace std;
  6. struct PersonInfo
  7. {
  8. string name;
  9. vector<string> phones;
  10. };
  11. int main()
  12. {
  13. string line, word; // 分别保存来自输入的一行和单词
  14. vector<PersonInfo> people; // 保存来自输入的所有记录
  15. istringstream record;
  16. while (getline(cin, line))
  17. {
  18. PersonInfo info; // 创建一个保存此记录数据的对象
  19. record.clear(); // 重复使用字符串流时,每次都要调用clear
  20. record.str(line); // 将记录绑定到刚读入的行
  21. record >> info.name; // 读取名字
  22. while (record >> word) // 读取电话号码
  23. info.phones.push_back(word); // 保持它们
  24. people.push_back(info); // 将此记录追加到people末尾
  25. }
  26. return 0;
  27. }

原文链接:http://www.cnblogs.com/juzaizai/p/14321613.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号