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. hdu3506 Monkey Party

    Problem Description Far away from our world, there is a banana forest. And many lovely monkeys live ...

  2. Codeforces Round #644 (Div. 3) D. Buying Shovels (数学)

    题意:商店里有\(k\)个包裹,第\(i\)个包裹中含有\(i\)个物品,现在想要买\(n\)物品,你可以选择某一个包裹购买任意次,使得物品数刚好等于\(n\),求最少的购买次数. 题解:首先,假如\ ...

  3. 通过js正则表达式实例学习正则表达式基本语法

    正则表达式又叫规则表达式,一般用来检查字符串中是否有与规则相匹配的子串,达到可以对匹配的子串进行提取.删除.替换等操作的目的.先了解有哪些方法可以使用正则对字符串来实现这些操作: RegExpObje ...

  4. 考研最路径dijkstra和floyd

    先来讲个段子:为什么 Dijkstra 不能提出 floyd 算法?因为他的名字是 ijk 而不是 kij. get不到点没有关系.我们今天的任务是看懂这个笑话. dijkstra 的效率是n^2.处 ...

  5. Java开发工程师最新面试题库系列——Java基础部分

    JAVA基础 面向对象有哪些特征? 答:继承.封装.多态 JDK与JRE的区别是什么? 答:JDK是java开发时所需环境,它包含了Java开发时需要用到的API,JRE是Java的运行时环境,JDK ...

  6. sentry can not delete release bug

    sentry can not delete release bug bug $ ./node_modules/@sentry/cli/bin/sentry-cli releases list $ ./ ...

  7. Linux Schedule Cron All In One

    Linux Schedule Cron All In One 定时任务 / 定时器 GitHub Actions Scheduled events Cron syntax has five field ...

  8. Flutter Widgets

    Flutter Widgets Flutter 组件 Syncfusion Flutter Widgets 所有组件均支持即装即用的 Android,iOS和 Web not free https:/ ...

  9. Android vs iOS vs Web

    Android vs iOS vs Web UI view Android ViewGroup ImageView TextView iOS UIView ImageView TextView Web ...

  10. Android APP 多端适配

    Android APP 多端适配 传统的多终端适配方案,是为大尺寸 Pad开发一个特定的 HD版本. 但是目前支持 Android 系统的设备类型越来越丰富,不同类型的设备尺寸也越来越多样化,特定的H ...