重学C++Primer笔记7---标准IO库中输入输出流控制

1 IO标准库

  IO类型在三个头文件中定义:iostream定义读写控制窗口的类型;fstream定义读写已命名文件的类型;sstream定义的类型则用于读写存储在内存中的string对象。
  当然还有对国际字符的支持的标准库:wiostream,wfstream,wstringstream。

  使用IO标准库时,要注意:

  • 标准库类型不允许做复制或赋值操作;如下面的操作就是错误的:
    ofstream out1,out2;
    out1 = out2;
  • 形参或者返回类型也不能为流类型
  • 一般情况下,如果要传递IO对象以便对它进行读写,可用非const引用的方式传递这个流对象,因为对IO对象的读写会改变它的状态,因此应用必须是非const类型;

2 流的状态和控制

  • bad ,当badbit位置一时,则bad状态为true,即流已被破坏
  • fail ,当failbit位置一时,则fail状态为true,即IO操作失败
  • eof ,当eofbit位置一时,则eof状态为true,即流已经到达文件结束符
  • good

  对流的状态的一些操作函数:

  • clear(); 将流中所有状态都重置设为有效状态,即bad、fail、eof均变为false,good变为true。
  • clear(flag); 将流中某个指定条件状态设置为有效。如clear(istream::failbit);
  • setstate(flag); 如setstate(iftream::badbit);
  • rdstate(); 返回流当前的状态

3 输入输出缓冲区的管理

3.1 ignore函数

  作用:提取输入字符并丢弃他们。
  函数原型:istream& ignore (streamsize n = 1, int delim = EOF)
  读取到前n个字符或在读这n个字符进程中遇到delim字符就停止,把读取的这些东西丢掉。

3.2 输入缓冲区:

  程序的输入都建有一个缓冲区,即输入缓冲区。如当一次键盘输入结束时会将输入的数据存入输入缓冲区,而cin函数直接从输入缓冲区中取数据。当从输入缓冲区读取数据失败后,会产生一个错误状态,此时,缓冲区的数据没有被读走,如果不清空缓冲区或者不读走这个错误的数据,那么下一次读还是产生错误状态。对于特殊的符号,比如Enter、Space、Tab键,会读入到缓冲区,但是读取的时候会丢弃掉,不会读走。
  因为输入流的刷新是没有定义处理方式的,所以用特殊的缓冲区‘清理’的方式:
cin.clear(); //这里如果用cin.clear(istream::failbit); 是不行的
cin.ignore(numeric_limits::max(),’\n’);
  或者再后面加上getchar()函数,将错误的数据读走,用fgets( sbuf, 1024, stdin ); 将缓冲中的所有字符读到sbuf,也能达到清空缓冲的目的。

3.3 输出缓冲区

  • 标准输入对象:cin,有缓冲
  • 标准输出对象:cout,有缓冲
  • 标准错误对象:cerr,无缓冲输出
  • 标准错误对象:clog,有缓冲输出
  • 刷新输出缓冲区的方式:
    • cout << “hello” << flush; //刷新流,但不在输出中添加任何字符
    • cout << “hello” << endl; //刷新流,但是在输出缓冲区中先插入一个换行符,然后再刷新缓冲区
    • cout << “hello” << ends; //刷新流,先在输出缓冲区中插入一个空字符null,然后再刷新

  当然还可以用unitbuf操作符,这个操作符在每次执行完写操作后都刷新流。
cout << unitbuf << “hello1” << “hello2” ;
等价于
cout << “hello1” << flush << “hello2” << flush;

4 实验

  下面的程序只有输入整形数据才能正常,如果输入非整形,则会有相应状态改变。如果不清理输入缓冲区,那么缓冲区一直是错误的数据,一直会是fail状态,那么就会导致死循环(ctrl + c可以强制退出循环)。

#include <iostream>
#include <stdexcept>
#include <limits>

using namespace std;

int main(int argc,char **argv)
{
    int ival;
    while(cin >> ival,!cin.eof()){
        cout << "hello:" << cin.fail() << endl;
        if(cin.bad()){
            throw runtime_error("IO stream corrupted");
        }
        if(cin.fail()){
            cerr << "bad data,try again";
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            //上面两句可以用getchar();来替代,作用是清理错误的数据
            continue;
        }
        if(0 == ival)break;
    }
    return 0;
 }
ignore函数的实验:
#include <iostream>
#include <stdexcept>
#include <limits>

using namespace std;

int main(int argc,char **argv)
{
    int ival1, ival2;
    while(1)
    {
        cin >> ival1;
        cin.ignore(4, '5');
        cin >> ival2;
        cout << "ival1:" << ival1 << endl;
        cout << "ival2:" << ival2 << endl;
    }
    return 0;
}

实验结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值