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
#include<iostream>
#include<string>
using namespace std; istream& func(istream& is)
{
int v;
while (is >> v, !is.eof()) // 直到遇到文件结束符才停止读取
{ if (is.bad())
{
cerr << "Bad Error!\n";
break;
}
else if (is.fail())
{
cerr << "Wrong Data! Please try again!\n";
is.clear();
is.ignore(1024, '\n');
continue;
}
cout << v << endl;
}
is.clear();
return is;
} int main()
{
func(cin);
return 0;
}
  1. badbit表示系统级错误,如不可恢复的读写错误。通常情况下,一旦badbit被置位,流就无法再使用了。在发生可恢复错误后,failbit被置位,如期望读取数值却读出一个字符等错误。这种问题通常是可以修正的,流还可以继续使用。如果到达文件结束位置,eofbit和failbit都会被置位。goodbit的值为0,表示流未发生错误。如果badbit、failbit和eofbit任一个被置位,则检测流状态的条件会失败。
  2. 在badbit被置位时,fail也会返回true。这意味着,使用good或fail是确定流的总体状态的正确方法。实际上,我们将流当作条件使用的代码就等价于!fail()。而eof和bad操作只能表示特定的错误。
  3. 下面的代码将failbitbadbit复位,但保持eofbit不变:
      // 复位failbit和badbit,保持其他标志位不变
    cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit); /*
    * clear和setstate的区别:
    * clear用实参值强制覆盖当前流的条件状态(不论是0还是1)
    * setstate将实参值(置1的位)叠加到当前流的条件状态
    */
  4. 导致缓冲刷新的原因:
    • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
    • 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
    • 我们可以使用操纵符endl来显式刷新缓冲区
    • 在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
    • 一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout,因此,读cin或写cerr都会导致cout的缓冲区被刷新。
  5. 操纵符endl完成换行并刷新缓冲区的工作。flush刷新缓冲区,但不输出任何额外的字符。ends向缓冲区插入一个空字符('\0'),然后刷新缓冲区。
  6. 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制:
      cout << unitbuf; // 所有输出操作后都会立即刷新缓冲区
    // 任何输出都立即刷新,无缓冲
    cout << nounitbuf; // 回到正常的缓冲方式
  7. 如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
  8. 当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。
  9. 交互式系统通常应该关联输入流和输出流。这意味着所有输出,包括用户提示信息,都会在读操作之前被打印出来。
  10. tie有两个重载的版本:一个版本不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie的第二个版本接受一个指向ostream的指针,将自己关连到此ostream,并返回上一个绑定的输出流指针。
  11. 我们既可以将一个istream对象关联到另一个ostream,也可以将一个ostream关联到另一个ostream。每个流同时最多关联到一个流,但多个流可以同时关联到同一个ostream
      cin.tie(&cout); // 仅仅是用来展示:标准库将cin和cout关联在一起
    // old_tie指向当前关联到cin的流(如果有的话)
    ostream *old_tie = cin.tie(nullptr); // cin不再与其他流关联
    // 将cin与cerr关联;这不是一个好主意,因为cin应该关联到cout
    cin.tie(&cerr); // 读取cin会刷新cerr而不是cout
    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是否成功的检测通常是一个好习惯。
      if (out) // 检查open是否成功
    // open成功,我们可以使用文件了
  3. 一旦一个文件流已经打开,它就保持与对应文件的关联。为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件。一旦文件成功关闭,我们可以打开新的文件。
      in.close() // 关闭文件
    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
#include<iostream>
#include<sstream>
#include<string>
#include<vector> using namespace std; struct PersonInfo
{
string name;
vector<string> phones;
};
int main()
{
string line, word; // 分别保存来自输入的一行和单词
vector<PersonInfo> people; // 保存来自输入的所有记录
istringstream record; while (getline(cin, line))
{
PersonInfo info; // 创建一个保存此记录数据的对象
record.clear(); // 重复使用字符串流时,每次都要调用clear
record.str(line); // 将记录绑定到刚读入的行
record >> info.name; // 读取名字
while (record >> word) // 读取电话号码
info.phones.push_back(word); // 保持它们
people.push_back(info); // 将此记录追加到people末尾
} return 0;
}

《C++ Primer》笔记 第8章 IO库的更多相关文章

  1. C++ Primer 5th 第8章 IO库

    IO类对象不允许进行拷贝操作. IO类中定义后一些函数和标志,可以用于访问和操作流的状态. 一旦流发生错误,后续IO操作都是失败的. 读写IO对象会改变IO对象的状态. 每个输出流都管理一个缓冲区. ...

  2. 第 8 章 IO库

    第 8 章 IO库 标签: C++Primer 学习记录 IO库 第 8 章 IO库 8.1 IO类 8.2 文件输入输出 8.1 string流 8.1 IO类 IO对象无拷贝或赋值,因此不能将形参 ...

  3. 【c++ Prime 学习笔记】第8章 IO库

    C++语言不直接处理输入输出,而是通过标准库中的一组类来处理IO 1.2节介绍的IO库: istream(输入流)类型,提供输入 ostream(输出流)类型,提供输出 cin,是istream对象, ...

  4. C++ Primer 笔记 第三章

    C++ Primer 第三章 标准库类型 3.1using声明 例: using namespace atd; using std::cin; 3.2string类型 初始化方式 string s1 ...

  5. C++ Primer笔记4_静态成员类_IO库

    1.静态成员类 static成员变量与函数 static成员变量:必须在类外初始化.(const或引用类型变量必须在构造函数初始化列表里初始化) static成员函数: 不依赖于类.相当于类里的全局函 ...

  6. 《C++primer》v5 第8章 IO库 读书笔记 习题答案

    8.1.8.2 这一章不咋会啊.. istream &read(istream &is) { int a; auto old_state=is.rdstate(); is.clear( ...

  7. 学习 primer 第8章 IO库 小结

    iostream处理控制台IO fstream处理命名文件IO stringstream完成内存string的IO 非常重要!!!!!!!!!!  ========================== ...

  8. [C++ Primer] 第8章: IO库

    IO类 iostream定义了读写流的基本类型 istream, wistream 从流读取数据 ostream, wostream 向流写入数据 iostream, wiostream 读写流 fs ...

  9. 《C++ Primer 4th》读书笔记 第3章-标准库类型

        原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3911534.html

随机推荐

  1. BZOJ1150 [CTSC2007]数据备份Backup 链表+小根堆

    BZOJ1150 [CTSC2007]数据备份Backup 题意: 给定一个长度为\(n\)的数组,要求选\(k\)个数且两两不相邻,问最小值是多少 题解: 做一个小根堆,把所有值放进去,当选择一个值 ...

  2. hdu4352 XHXJ's LIS (数位dp)

    Problem Description #define xhxj (Xin Hang senior sister(学姐))  If you do not know xhxj, then careful ...

  3. hdu5437 Alisha’s Party

    Problem Description Princess Alisha invites her friends to come to her birthday party. Each of her f ...

  4. Codeforces Round #645 (Div. 2) D. The Best Vacation (贪心,二分)

    题意:一年有\(n\)个月,每月有\(d_{i}\)天,找出连续的\(x\)天,使得这\(x\)天的日期总和最大,任意一年都能选. 题解:首先要先贪心,得到:连续的\(x\)天的最后一天一定是某个月的 ...

  5. B - 来找一找吧 HihoCoder - 1701

    题目: 这次到渣渣问桶桶了... 准备给你n个数a1, a2, ... an,桶桶你能从中找出m个特别的整数吗,我想让任意两个之差都是k的倍数. 请你计算有多少种不同的选法.由于选法可能非常多,你只需 ...

  6. JavaScript——七(继承)

    一. 这个样子这个student的类型是person,这个样子写虽然继承了,但是是把父类的属性继承在了student的原型上 为了使student的类型改成他自己就需要加一句"student ...

  7. Codeforces Round #515 (Div. 3) C. Books Queries (模拟)

    题意:有一个一维的书架,\(L\)表示在最左端放一本书,\(R\)表示在最右端放一本书,\(?\)表示从左数或从右数,最少数多少次才能得到要找的书. 题解:我们开一个稍微大一点的数组,从它的中间开始模 ...

  8. BIM技术基础-Revit2019建筑

    第三章 三维信息建模(中) 3.5 拉伸屋顶的创建 拉伸屋顶→ 在立面中创建,屋顶的形状在垂直截面上一致的 利用参照平面或者已有的墙面或者已有的轴线 3.5.1利用拾取平面创建 画一个参照平面作为屋檐 ...

  9. 基于用户的协同过滤的电影推荐算法(tensorflow)

    数据集: https://grouplens.org/datasets/movielens/ ml-latest-small 协同过滤算法理论基础 https://blog.csdn.net/u012 ...

  10. docker安装CentOS7及JNI使用相关过程记录

    docker pull centos:centos7(拉取镜像) docker run -itd --name centos-test centos:centos7 (运行容器) docker exe ...