C++ Primer 5th学习笔记7 IO库

IO库

1 IO类

常用的IO库类型和头文件如下表:

头文件类型
iostreamistreamwistream从流读取数据
ostreamwostream 向流写入数据
iostreamwiostream 读写流
fstreamifstreamwifstream 从文件读取数据
ostreamwofstream 向文件写入数据
fstreamwfstream 读写文件
sstreamistringstreamwistringstream 从string读取数据
ostringstreamwostringstream 向string写入数据
stringstreamwstringstream 读写string

w开头的表示宽字符类型

1.1 条件状态
IO库条件状态
名称描述
strm::iostatestrm是一种IO类型,在上表中已列出
strm::badbit用来指出流已经崩溃
strm::failbit用来指出一个IO操作失败了
strm::eofbit用来指出流到达了文件结束
strm::goodbit用来指出流未处于错误状态
s.eof()若流s的eofbit置位,则返回true
s.fail()若流s的failbitbadbit置位,则返回true
s.bad()若流s的badbit置位,则返回true
s.good()若流s处于有效状态,则返回true
s.clear()将流s中所有条件状态复位,将流的状态设置为有效。返回void
s.clear(flags)根据给定的flag标志位,将流s中对应条件状态位复位。flag类型为strm::iostate
s.setstate(flags)根据给定的flag标志位,将流s中对应条件状态位置位。flag类型为strm::iostate
s.rdstate()返回流s的当前条件状态,返回类型为strm::iostate
1.2 管理输出缓冲

  每一个输出流都管理一个缓冲区,用来保存程序读写的数据。其中导致缓冲区刷新的原因有如下几种:

  • 程序正常结束
  • 缓冲区满时,需要刷新缓冲区,后面新来的数据才能继续写入缓冲区
  • 使用操作符如endl来显示刷新缓冲
  • 在每个输出操作之后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区
  • 一个输出流可能被关联到另一个流,当读写被关联的流时,关联到的流的缓冲区会被刷新

刷新输出缓冲区操作符:flush和ends,其中flush刷新缓冲区,但不输出任何额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区。

2 文件输入输出

  头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,fstream可以读写给定文件

`fstream`特有的操作
名称描述
fstream fstrm;创建一个未绑定的文件流
fstream fstrm(s);创建一个fstream,并打开名为s的文件,s可以是string类型,或指向C风格字符串的指针
fstream fstrm(s, mode);创建一个fstream,并打开名为s的文件,按指定mode打开文件
fstrm.open();打开名为s的文件,并将文件与fstrm绑定
fstrm.close();关闭与fstrm绑定的文件。返回void
fstrm.is_open();返回一个bool值,表示与fstrm关联的文件是否打开成功并且尚未关闭

示例:

ifstream in(ifile);       //创建一个ifstream并打开给定文件
ofstream out;        //输出文件流
out.open(ifile + ".txt");        //打开指定文件
2.1 文件模式
文件模式
操作描述
in以读方式打开文件
out以写方式打开文件
app每次写操作前均定位到文件末尾
ate打开文件后立即定位到文件末尾
trunc截断文件
binary以二进制方式进行IO

指定文件模式有如下限制:

  • 只可以对ofstreamfstream对象设定out模式
  • 只可以对ifstreamfstream对象设定in模式
  • 只有当out也被设定时,才可设定trunc模式
  • ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用
  • 只要trunc没有被设定。就可以设定app模式。在app模式下即使没有显式指定out模式,文件也总是以输出方式被打开。
  • 即使没有指定trunc,以out模式打开的文件也会被截断,因此为保留此时的内容,必须同时指定app模式,这样数据将追加写到文件末尾

Tips:当打开一个ofstream时文件的内容会被丢弃,因此此时必须显式指定app或in模式
示例如下:

//文件内容会被截断
ofstream app("file2");
ofstream app("file2", ofstream::out);
//文件内容保留
ofstream app("file2", ofstream::app);
ofstream app("file2", ofstream::out | ofstream::app);

3 string流

string特有的操作
名称描述
sstream strm;strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型
sstream strm(s);strm是一个sstream对象,保存string s的一个拷贝
strm.str()返回strm所保存的string的拷贝
strm.str(s)string s拷贝到strm中,返回void
3.1 使用istringstream

示例如下:
现有一个这样的文件,其输入格式如下:

morgan 2015552368 8625550123
drew 9735550130
lee 6095550132 2015550175 8005550000

首先定义一个简单的类来描述输入数据:

struct PersonInfo{
    string name;
    vector<string> phones;
}

读取信息的实例函数如下:

string line,word;                //分别保存来自输入的一行和单词
vector<PersonInfo> people;        //保存来自输入的所有记录
while (getline(cin, line)){       //逐行从输入读取数据,直到遇到文件末尾
    PersonInfo info;              //创建一个保存此记录数据的对象
    istringstream record(line);   //将记录绑定到刚读入的行
    record >> info.name;          //读取名字
    while(record >> word)         //读取电话号码
    {
        info.phones.push_back(word);//保持它们
    }
    people.push_back(info);       //将此记录追加到people末尾
}

这里的istringstreamgetline读取的文本进行绑定,然后在istringstream上使用输入运算符来读取当前记录中的每个元素,即元素之间以空格为区分。

3.2 使用ostringstream

对于上例,现将每个人的电话打印出来,但是不希望输出无效电话号码的人,因此需要进行验证。此时可以先将要输出的内容“写入”到一个内存ostringstream中,其代码如下:

for(const auto &entry : people)          //对people中的每一项
{
    ostringstream formatted,badNums;     //每个循环步创建的对象
    for(const auto &num : entry.phones)  //对每个数
    {
        if(!valid(nums))
        {
            badNums << " " << nums;      //将数的字符串形式存入badNums
        }
        else
        formatted << " " << format(num); //将格式化的字符串“写入”formatted
    }
    if(bad.Nums.str().empty())           //没有错误的数
    //打印名字和格式化的数
    os << entry.name << " " << formatted.str() << endl;
    else//打印名字和错误的数
    ceer << "input error: " << entry.name 
         << " invalid number(s)" << badNums.str() << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值