• C++ Primer- 流的条件状态以及缓冲区管理


    IO标准库提供了一系列条件状态成员,用来标记IO对象是否处于可用状态。使用strm::iostate类型的值来表示条件状态,

    这是一个跟机器有关的整型值,通过判断特定的一些位是否为1来判断流处于什么状态,有三个常量strm::badbit, strm::failbit, strm::eofbit 分别代表流被破坏,失败的IO操作和流已经到达文件尾。那么我们如何判断一个流比如说s处于什么状态呢,s.eof()若为true,表示到达文件尾,s.bad()若为ture,代表流被破坏,而 s.fail()若为true,则代表s遇到了失败的IO操作。

    我们现在可以通过这三个函数来判断流的状态,那么下一步,该如何改变这个流的状态呢,有以下几个函数:

    s.clear()          清除所有不可用的状态,重新使流有效

    s.clear(flag)      设置流的某一个不可用状态,如badbit状态,所以flag是strm::iostate类型的

    s.setstate(flag)   添加流的某一个不可用状态,如failbit状态,同样是strm::iostate类型值

    s.rdstate()        返回流的当前状态,是strm::iostate类型值

    这里我们通过一个例子来练习使用流的条件状态,题目是C++ Primer 练习8.3原题:

    编写一个函数,唯一形参和返回值都是istream&类型,该函数一直读取流直到到达文件结束符,同时把读到的内容输出到标准输出中,最后,重设流使其有效并返回,通过cin为实参实现调用来测试该函数。

    代码和注释如下:

    /**
    * @file    main.cpp
    * @brief   编写一个函数,可以一直读取流直到文件结束 并输出
    * @details
    * @author  jason.mrbourne@gmail.com
    * @date    2014-5-20
    */
    #include <iostream>
    #include <stdexcept>
    using namespace std;
    
    istream& get(istream& in)
    {
        int ival;
    
        //遇到文件结束符前一直读入数据
        while (in >> ival, !in.eof())
        {
            if (in.bad())   //出现系统级故障
                throw runtime_error("IO stream corrupted");
            if (in.fail())  //出现可恢复错误
            {
                cerr << "bad data, try again" << endl; //提示用户
                //有一些编译器不支持in.clear(istream::failbit)语句 所以这里用in.clear()
                in.clear();   //恢复流
                //跳过200个字符或者遇到空格或EOF为止 因此输入时必须以空格为间隔
                in.ignore(200, ' ');
                continue;   //继续读入数据
            }
            //读入正常
            cout << ival << '	';
        }
        in.clear();
        return in;
    }
    
    //在主函数中测试
    int main()
    {
        int ival;
    
        get(cin);       //这里用cin作为我们要读取的流
        cin >> ival;    //重新使用恢复后的流
        cout << ival << endl;
    
        return 0;
    }
    

    输出缓冲区的管理,输出缓冲区中存放着将要输出的数据,当程序结束或缓冲区满或执行一些清空缓冲区的操作时,系统会刷新缓冲区。

    c++提供3个操作符用于刷新流,用法如下:

    cout << “hi” << flush;      //刷新缓冲区,不添加数据

    cout << “hi” << ends;       //刷新缓冲区,并在输出中插入一个null空字符

    cout << “hi” << endl;       //刷新缓冲区,并在输出中插入一个换行符

    也可以用unitbuf操纵符来实现刷新,使用unitbuf会在每一次输出后刷新缓冲区。

    cout << unitbuf << “first” << “second”<< nounitbuf;

    这样在输出first后缓冲区被刷新,输出second后,缓冲区再次被刷新,此时缓冲区里啥也没有。但要最后用nounitbuff把流恢复正常。

    由于程序崩溃时,系统不会自动刷新缓冲区,那么此时想通过输出来找出错误发生的原因就变得异常艰难,基于这个原因,输出时应当尽可能使用endl而非’ ’。

    我们还可以将输入和输出绑在一起,默认标准库是将cout与cin绑在一起,这样在读cin的时候,会导致cout的缓冲区被刷新,我们可以使用tie()来制定需要绑定的流,例如:

    cin.tie(&cout);    //tie的参数为指向ostream对象的指针

    ostream* old_tie = cin.tie();    //返回当前与cin绑定的流指针

    cin.tie(0);        //解除cin的所有绑定,这样在读cin时,cout缓冲区将不会刷新

    cin.tie(&cerr);    //将cin与cerr绑定

    cin.tie(0);        //解除cin与cerr的绑定

    cin.tie(old_tie);  //恢复cin与cout的绑定   


  • 相关阅读:
    iOS截取长图,自定义截取size
    工作
    UITableView适配iOS11
    利用脚本实现build号自动加一
    iOS原生与JS互调
    CSS高级技巧
    伪元素选择器
    CSS设置过渡
    CSS文本属性 二
    css设置圆角矩形
  • 原文地址:https://www.cnblogs.com/mrbourne/p/9959456.html
Copyright © 2020-2023  润新知