C++Primer学习笔记:第8章 IO库

  • C++语言不直接处理输入输出,而是通过一族定义在标准库中的类型来处理IO

    • iostream定义了用于读写流的基本类型
    • fstream定义了读写命名文件的类型
    • sstream定义了读写内存string对象的类型
  • 标准库使得我们能够忽略这些不同类型的流之间的差异,是通过继承机制实现的

  • 不能拷贝或者对IO对象赋值,因此也不能将形式参数或者返回类型设置为流类型,进行IO操作的函数通常是已引用方式传递和返回流,读写一个IO对象会改变其状态,因此传递和返回的引用不能是const

    strm::iostate	提供表达条件状态的完整功能
    strm::badbit	用来指出流已经崩溃
    strm::failbit	用来指出一个IO操作失败了
    strm::eofbit	用来指出流到达了文件结束
    strm::goodbit	用来指出流未处于错误状态,此值保证为零
    s.eof()			若流s的eofbit置位,返回true
    s.fail()		
    s.bad()
    s.good()		若流s处于有效状态,返回true
    s.clear()		所有条件状态复位,将流的状态设置为有效,返回void
    s.clear(flags)	根据给定的flags标志位将流s中对应条件状态位复位
    s.setstate(flags)同上
    s.rdstate()		返回流s的当前条件状态
    
    auto old_state = cin.rdstate();		//记住cin的当前状态
    cin.clear()							//使cin有效
    process_input(cin);					//使用cin
    cin.setstate(old_state);			//将cin置为原有状态
    cin.clear(cin.rdstate & ~cin.failbit & ~cin.badbit);	//复位failbit和badbit,保持eofbit不变
    
  • 通过缓冲机制,操作系统可以将程序的多个输出操作组合成单一的系统级写操作。(原因在于设备的写操作可能很耗时)

  • 导致缓冲刷新的原因:

    • 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行
    • 缓冲区满
    • 使用操纵符endl显式刷新缓冲区
    • 在每个输出操作后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区(默认情况下cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的)
    • 一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新
  • 除了endl外,还可以使用flushends刷新缓冲区,但是他们有不同的效果:

    cout << "hi" << endl;		//输出"hi\n"
    cout << "hi" << flush;		//输出"hi"
    cout << "hi" << ends;		//输出"hi "
    
  • 如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符,它告诉流在接下来每次写操作后都进行一次flush操作

    cout << unitbuf;	//所有输出操作都会立即刷新缓冲区
    cout << nounitbuf;	//回到正常的缓冲方式
    
  • 调试/程序崩溃时要记得及时刷新缓冲区

  • 当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流(例如cincout)。交互式系统通常应该关联输入流和输出流。每个输入流最多关联到一个流,但多个流可以同时关联到同一个ostream

    cin.tie();				//返回cin关联的流,如果之前没有关联则返回空指针
    cin.tie(&cout);			//返回值同上,但是将cin与cout关联
    ostream *old_tie = cin.tie(nullptr);	//取消关联,同时保存关联的流的指针
    cin.tie(old_tie);		//恢复关联
    
  • 文件输入输出的流定义在头文件fstream

    fstream fstrm;
    fstream fstrm(s);		打开名为s的文件,s可以是string类型或者是一个指向C风格字符串的指针,默认的文件模式mode依赖							fstream的类型
    fstream fstrm(s, mode);
    fstrm.open(s);			打开名为s的文件,并将文件与fstrm绑定,返回void
    fstrm.close();			关闭与fstrm绑定的文件,返回void
    fstrm.is_open(s);		返回一个bool,指出与fstrm关联的文件是否打开成功且尚未关闭
    
  • 我们可以用fstream代替iostream&,即在需要接受一个iostream类型引用或者指针参数的函数可以用一个对应的fstreamsstream来调用

  • 在使用流之前检查是一个好的习惯

  • 当一个fstream对象被销毁时,close会自动被调用

  • 每个流都有一个关联的文件模式,用来指出如何使用文件

    in			以读方式打开,只可以对ifstream或fstream
    out			以写方式打开,只可以对ofstream或fstream,默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截				断,为了保留以out模式打开的文件的内容,我们必须同时指定app,或者指定in
    		fstream默认关联in和out
    app			每次操作均定位到文件末尾,只要trunc没有被设定就可以设定,包含out
    ate			打开文件后立即定位到文件末尾
    trunc		截断文件,只有当out也被设定时才能设定
    binary		以二进制方式进行IO
    
    //下面三种方式打开文件是等价的,都会截断文件
    ofstream out("file");
    ofstream out("file", ofstream::out);
    ofstream out("file", ofstream::out | ofstream::trunc);
    //为了保留文件的内容,我们必须显式指定app模式
    ofstream out("file", ofstream::app);
    ofstream out("file", ofstream::out | ofstream::app);
    
  • sstream头文件定义了三个类型来支持内存IO,这些类型可以向string写入数据,从string读取数据

  • istringstreamstring读取数据,ostringstreamstring写入数据,stringstream既可以读也可以写

    sstream strm;		
    sstream strm(s);		strm保存string类型的s的拷贝
    strm.str()				返回strm保存的string的拷贝
    strm.str(s)				将string s拷贝到strm中,返回void
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值