美文网首页
第八章 摘录

第八章 摘录

作者: 带鱼去兜风 | 来源:发表于2018-04-26 11:34 被阅读0次

    第八章 IO库

    8.1 IO类

    IO类型和头文件如下:

    头文件 类型
    iostream istream, wistream
    ostream, wostream
    iostream, wiostream
    fstream ifstream, wifstream
    ofstream, wofstream
    fstream, wfstream
    sstream istringstream, wistringstream
    ostringstream, wostringstream
    stringstream, wstringstream

    如cin就是一个istream对象,用于从标准输入流中读取数据。

    w开头的类型都是为了支持宽字符wchar_t类型的,对应的对象就是wcin,wcout和werr。

    IO类型之间的关系

    fstream和sstream中的类型都继承自iostream中的类型,比如ifstream和istringstream都是继承istream类型的,所以它们使用>>,<<,getline等操作符或方法都是可以的。

    8.1.1 IO对象无拷贝或赋值

    由于不能拷贝IO对象,所以也不能将形参或返回类型设置为流类型,原因是“形参”和“返回类型”都要利用到拷贝操作拷贝创建一个中间对象。

    读写一个io对象是会改变其状态的,所以传递的值或者引用都不能加const。

    8.1.2 条件状态

    IO操作与生俱来的问题:可能发生错误。有的可恢复,有的则不可。

    访问流状态和操纵的函数及标志有:

    状态及函数 介绍
    strm::iostate strm为一种IO类型。iostate则是一种机器相关的类型。
    strm::badbit 指出流已崩溃。通常是系统级的,无法恢复。
    strm::failbit 指出IO操作失败了。但通常可以恢复。
    strm::eofbit 指出流已到达了文件结束
    strm::goodbit 指出流未处于错误状态。此值保证为0
    s.eof() 若流的eofbit置位,则返回true
    s.fail() 若流的failbit或badbit置位,则返回true
    s.bad() 若流的badbit置位,则返回true
    s.good() 若流处于有效状态,则返回true
    s.clear() 将流中所有条件状态复位
    s.clear(flags) 将流中对应条件状态位复位。flags位iostate类型。
    s.rdstate() 返回流的当前状态,返回值为iostate类型。
    s.setstate(flags) 将流中对应条件状态位置位。flags位iostate类型。

    把流当作条件使用是确定一个流对象的状态的最好方法,如while(cin >> word)。

    查询流的状态

    把流当作条件使用,只能知道它是否有效,而没法知道其具体发生了什么。IO库定义了一个与机器无关的iostate类型,提供了表达流状态的完整功能。

    IO库提供了4个iostate类型的constexpr值表示特定的位模式。它们可以与位运算符一起使用来一次性检测或设置多个标志位。

    badbit表示系统级错误,如不可恢复的读写错误。在发生可恢复错误后,failbit被置位,如期望读取数值却读出一个字符等错误,这种错误可以被修正,流仍可使用。

    使用good或fail是确定流的总体状态的正确方法。实际上,把流当作条件就等价于用!fail()。而eof和bad只能表示特定错误。

    管理条件状态

    复位failbit和badbit,保持其他标志位不变:

    cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

    8.1.3 管理输出缓冲

    <u>每个输出流都管理一个缓冲区</u>,用来保存程序读写的数据。

    os << "xxxxxxx"; 文本串可能立即打印出来也可能被操作系统保存在缓冲区中。

    有了缓冲机制,操作系统可以将程序的多个输出操作组合成单一的系统级写操作。这是由于设备的写操作可能很耗时,因此把多个输出组合成一个再一次输出可以带来性能提升。

    导致缓冲刷新的操作有很多:

    • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新执行。

    • 缓冲区满。

    • 用如endl的操纵符来显式刷新缓冲区。

    • 每个输出操作后可以用操纵符unitbuf设置流的内部状态来清空缓冲区。默认对cerr是设置unitbuf的,所以写到cerr的内容都是立即输出。

      cout << 'xx' << unitbuf; // 所有输出操作后都会立即刷新缓冲区

      // 任何输出都立即刷新,无缓冲

      cout << nounitbuf; //回到正常的缓冲方式

    • 被关联到另一个流,此时,当读写被关联的流时,关联到的流的缓冲区都会被刷新。如cin和cerr都被关联到cout,因此读cin或写cerr都会导致cout缓冲区被刷新。

    刷新输出缓冲区

    IO库中还有两个类似的操纵符:flush和ends。flush刷新缓冲区,但不输出任何额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区。

    cout << 'xx' << flush; cout << 'xx' << ends;

    关联输入输出流

    当一个输入流被关联到一个输出流上时,任何试图从输入流读取数据的操作都会刷新关联的输出流。标准库将cin和cout关联了起来,所以 cin >> xx; 时会导致cout的缓冲区被刷新。

    交互式系统通常应该关联输入输出流。

    tie有两个版本:

    1.不带参数,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。

    2.接受一个指向ostream的指针,将自己关联到此ostream。即,x.tie(&o)将流x关联到输出流o。

    cin.tie(&cerr); cin.tie(nullptr);

    8.2 文件输入输出

    8.2.1 使用文件流对象

    在要求使用基类型对象的地方,我们可以用继承类型的对象来替代。如,接受一个iostream类型引用(或指针)参数的函数,可以用一个对应的fstream(或sstream)类型来调用。

    成员函数open和close

    若定义了一个空文件流对象,可以随后再调用open将它与文件关联起来。

    若open失败,failbit会被置位。因为open可能失败,所以进行open是否成功的检查是好习惯。

    一旦一个文件流已经打开,它就保持与对应文件的关联。对一个已经打开的文件流调用open会失败,要先关闭才能关联到另外一个文件。

    如果open成功,则open会设置流的状态,使得good()为true。

    自动构造和析构

    比如在循环内定义一个ifstream对象,每次循环,都会创建和销毁一次。当一个fstream对象离开其作用域时,与之关联的文件会自动关闭。

    fstream对象在销毁时,close会自动被调用。

    8.2.2 文件模式

    每个流都有一个关联的文件模式(file mode),用来指出如何使用文件。

    文件模式
    in 以读方式打开
    out 以写方式打开
    app 每次写操作前均定位到文件末尾
    ate 打开文件后立即定位到文件末尾
    trunc 截断文件
    binary 以二进制方式进行IO

    in只针对ifstream和fstream,out只针对ofstream和fstream。

    只有当out也被设定时才可设定trunc模式;只要trunc没被设定,就可设定app模式。在app模式下,文件总以输出方式被打开。

    默认情况下,没有指定trunc,以out模式打开的文件也会被截断。

    ate和binary可用于任何类型的文件流对象,且可与其他任何文件模式组合使用。

    与fstream关联的文件默认以in和out模式打开,ifstream以in,ofstream以out。

    以out模式打开文件会丢弃已有数据

    ofstream out("file1");  //隐含地以输出模式打开文件并截断文件
    ofstream out1("file1", ofstream::out);  //隐含地截断文件
    ofstream out2("file1", ofstream::out | ofstream::trunc);
    //以上三条代码,file1都被截断
    
    ofstream app("file1", ofstream::app);  //隐含为输出模式
    ofstream app("file1", ofstream::out | ofstream::app);
    

    每次调用open时都会确定文件模式

    8.3 string流

    sstream头文件定义了三个类型来支持内存IO。

    stringstream特有的操作为:

    strm.str()  //返回strm保存的string的拷贝
    
    strm.str(s)  //将string s拷贝到strm中,返回void
    

    8.3.1 使用istringstream

    当我们的某些工作是对整行文本做处理,而其他一些工作是针对行内的单个单词时,就可使用istringstream。

    如从 while (getline(cin, line)) 先从标准输入流中读取行,

    然后istringstream record(line);把这一行绑定到record上,此时要操作行中的每一个单词就很容易了,用record >> word就可以读取其中的单词。istringstream充分利用了输入流读取字符串时遇到空格就结束的特性,所以可以用来方便地读取一行中的单词。

    8.3.2 使用ostringstream

    当我们逐步构造输出,想最后一起打印时,oss是很有用的。

    小结

    • iostream处理控制台IO
    • fstream处理命名文件IO
    • stringstream完成内存string的IO

    输入类都继承自istream,输出类都继承自ostream。因此,可以在istream对象上执行的操作也可以在ifstream或istringstream对象上执行。ostream同理。

    每个IO对象都维护一组条件状态,用来指出此对象上是否可以进行IO操作。

    相关文章

      网友评论

          本文标题:第八章 摘录

          本文链接:https://www.haomeiwen.com/subject/xjyplftx.html