MyException - 我的异常网
当前位置:我的异常网» C++ » Tips for C++ Primer Chapter 八 IO库

Tips for C++ Primer Chapter 八 IO库

www.MyException.Cn  网友分享于:2013-11-02  浏览:0次
Tips for C++ Primer Chapter 8 IO库

第8章 IO库

IO类

IO库类型和头文件

头文件:类

iostream(控制台的IO):istream ostream iostream

fstream(命名文件的IO):ifstream ofstream fstream

sstream(内存string对象的IO):istringstream ostringstream stringstream

PS:

ifstream、istringstream继承自istream;

ofstream、ostringstream继承自ostream;

通常可以将一个派生类对象当作其基类对象来使用,例如可以对ifstream对象使用IO运算符(>>和<<)或getline等。

 

IO对象无拷贝和赋值

由于不能拷贝IO对象,因此不能将形参或返回类型设置为流类型;

进行IO操作的函数通常以引用的方式传递和返回流;

读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的

 

条件状态

IO类定义了一些函数和标志,以访问和操纵流的条件状态(condition state)

以下strm表示某种IO类型(istream等),s是某个流对象

strm::iostate   iostate是一种机器相关的类型,提供了表达条件状态的完整功能

strm::badbit   用来指出流已崩溃

strm::failbit   用来指出一个IO操作失败

strm::eofbit   用来指出流达到了文件结束

strm::goodbit   用来指出流未处于错误状态(此值保证为0)

s.eof()   若流s的eofbit置位,则返回true

s.bad()   若流s的badbit置位,则返回true

s.good()   若流s处于有效状态,则返回true

s.clear()   将流s中所有条件状态位复位,将流的状态设置为有效(goodbit也复位了);返回void

s.clear(flags)   根据给定的flags标志位,将流s中对应条件状态位复位;flags的类型为strm::iostate;返回void

s.setstate(flags)   根据给定的flags标志位,将流s中对应条件状态位置位;flags的类型为strm::iostate;返回void

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

 

流的条件状态位

badbit表示系统级错误,如不可恢复的读写错误。一旦badbit被置位流就无法再使用了;

当badbit被置位时,或者在发生可恢复错误后,failbit会被置位,如期望读取数值却读到一个字符等错误。这种错误可以修正,流还可以继续使用;

如果达到文件结束位置,eofbit和failbit都被置位;

当流未发生错误,goodbit保持为0

如果badbit、failbit、eofbit任一被置位,则检测流状态的条件会失败;

  例如 while(cin>>val) 在读到文件结束时终止循环。

 

流的条件状态查询函数

所有错误位均未置位时,good返回true(注意:此时goodbit为0而不是1);

bad、fail、eof在特定的对应错误位被置位时返回true(注意:badbit或eofbit被置位时,failbit也会被置位,所以fail也会返回true);

可见:good或fail是确定流的总体状态的方法。

  例如

  实际上 while(cin>>val)

  就等价于 while(cin>>val && cin.good())

  或 while(cin>>val && !cin.fail())

 

管理输出缓冲

每个输出流都管理一个缓冲区;

由于设备的写操作可能很耗时,允许操作系统将多个输出操作暂存在缓冲区,然后组合为单一的设备写操作,可以带来很大的性能提升

 

缓冲区刷新即:数据真正写到输出设备或文件

导致缓冲区刷新的原因:

  程序正常结束;(实际上,缓冲刷新是main函数return操作的一部分;程序异常终止时输出缓冲区不会被刷新)

  缓冲区满;

  使用操纵符endl显式刷新缓冲区;

  写到cerr;(在每个输出操作之后,可以用操纵符unitbuf设置流的内部状态,来清空缓冲区;而默认情况下,对流对象cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的)

  一个输出流被关联到了另一个流的情况;(例如,默认情况下,cin和cerr都关联到cout,因此,读cin写cerr都会导致cout的缓冲区被刷新)

 

刷新输出缓冲区

以下操纵符需出现在某个输出操作之后。(cout、cerr等)

endl:换行并刷新缓冲区

flush:仅刷新缓冲区

ends:向缓冲区插入一个空格符,再刷新缓冲区

 

unitbuf操纵符

如果想在每次输出操作后系统都自动刷新缓冲区,可以使用unitbuf操纵符;

unitbuf告诉流在接下来的每次写操作之后都自动进行一次flush操作。

  cout << unitbuf;

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

 

关联输入和输出流

当一个输入流被关联到一个输出流时,使用该输入流的操作时会先刷新关联的输出流

标准库将cin与cout关联在一起。

 

tie函数

tie函数有两个重载的版本:

一个版本不带参数返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回指向该输出流的指针;如果本对象未关联到流,则返回空指针

另一个版本接受一个指向ostream的指针,将自己关联到此ostream

例如:

  ostream* old_tie = cin.tie(); //old_tie指向当前关联到cin的流(系统默认是cout)

  cin.tie(&cerr); //将cin与cerr关联

  cin.tie(nullptr); //解除cin与任何流的关联

  cin.tie(old_tie); //重建cin与cout的关联

PS:

可以将一个istream关联到一个ostream,也可以将一个ostream关联到另一个ostream;

每个流最多关联到一个流,多个流可以同时关联到同一个ostream。

 

文件输入输出

头文件fstream定义了三个类型来支持文件IO:

  ifstream:读文件

  ofstream:写文件

  fstream:读写文件(将在第17章讨论)

 

除了继承自iostream类型的>>、<<、getline等行为之外,fstream中定义的类型有其特有的管理与流关联的文件的成员。

fstream特有的操作:

fstream fs   创建一个未绑定的文件流;fstream是头文件fstream中定义的一种类型

fstream fs(s)   创建一个fstream,并打开(此时open会自动被调用)名为s的文件;s可以是string类型或者指向C风格字符串的指针(C++11之前只允许C风格的字符数组);这些构造函数数都是explicit(第7章)的;默认的文件模式mode依赖于fstream的类型

fstream fs(s, mode)   与前一个构造函数类似,但按指定mode打开文件

fs.open(s)   打开名为s的文件,并将文件与fs绑定;默认的文件mode依赖于fstream的类型;返回void

fs.close()   关闭与fs绑定的文件;返回void

fs.is_open()   返回bool值;指出与fs关联的文件是否成功打开尚且未关闭

 

用fstream代替iostream&

在要求使用基类对象的地方,我们可以用继承类型的对象来替代;

这意味着,接受一个iostream类型引用(或指针)参数的函数,可以用一个对应的fstream(或sstream)类型来调用;

例如,如果有一个函数接受一个ostream&参数,调用这个函数时,可以传给它一个ofstream对象;(isstream&和ifstream也类似)

 

成员函数open和close

如果调用open失败,failbit会被置位;

fs.open(s);

if(fs) //如果open失败,则条件为假

 

对一个已经打开的文件流调用open会失败,并导致failbit被置位,随后的文件流操作也都会失败;为了将文件流关联到另一个文件,必须首先关闭已关联的文件。

fs.close();

 

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

 

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

 

文件模式(file mode)

in   读

out   写

app   每次写操作前均定位到文件尾

ate   打开文件后立即定位到文件尾

trunc   截断文件

binary   以二进制方式进行IO

 

文件模式规则:

(1)只可对ofstream或fstream对象设定out模式;

(2)只可对ifstream或fstream对象设定in模式;

(3)只有当out被设定时才可设定trunc模式;

(4)只要trunc未被设定,就可以设定app模式;在app模式下,即使没有显式设定out,文件也总是以输出方式被打开;

(5)默认情况下,即使未设定trunc,以out模式打开的文件也会被截断;为了保留以out模式打开的文件内容,必须同时指定app模式,这样就会将数据追加到文件尾;或者同时指定in模式,同时进行读写操作(第17章)

(6)ate和binary模式可用于任何类型的文件流对象,且可与其它任何文件模式组合使用;

 

当未显式指定文件模式时,各文件流类型的默认模式

ifstream:in

ofstream:out

fstream:in和out

 

一些例子:

ofstream out(s1); //默认为out模式,文件被截断

ofstream out2(s1, ofstream::out); //显式指定out,会隐式地截断文件(参考“文件模式规则”:第5条)

ofstream out3(s1, ofstream::out | ofstream::trunc); //显式截断文件(只有out也被设定,trunc才能被设定;参考“文件模式规则”:第3条

ofstream app(s2,ofstream::app); //隐式地设定了out

ofstream app2(s2,ofstream::out | ofstream::app); //与上一条等价

PS:以上是在初始化流并隐式打开文件时指定文件模式,此外在使用open打开文件时也同样可以指定文件模式。

 

string流

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

istringstream:从string读取数据

ostringstream:向string写入数据

stringstream:可从string读取数据,或向string写入数据

 

除了继承自iostream头文件的>>、<<、getline等操作,sstream头文件定义的类有其特有操作:

sstream st   st是一个未绑定的stringstream对象;sstream是头文件sstream中定义的某个类型

sstream st(s)   st是一个sstream对象,保存string s的一个拷贝;此构造函数时explicit(第7章)

st.str()   返回st所保存的string的拷贝

st.str(s)   将string s拷贝到st中;返回void

 

使用istringstream

例子:

string line, word;
while(getline(cin, line)) //读取一行
{
    istringstream iss(line); //将string流iss绑定到读入的一行line(流对象iss中存有line的一个拷贝)
    while(iss>>word) //使用输入运算符从iss流中依次读取各个字符串
        cout<<word<<endl;
}

 

问题:若将istringstream对象定义在循坏之外程序还能完成之前的功能吗?

string line, word;
istringstream iss;
while(getline(cin, line))
{
    iss.str(line); //调用str函数将流iss绑定到line(流对象iss中存有line的一个拷贝)
    while(iss>>word)
        cout<<word<<endl;
    //iss.clear();
}

不能。程序只会成功读取并处理文件中的第一行就终止了。

原因:当string流中的数据全部读出后,同样会触发“文件结束”信号,此时流iss不在有效了。

改正:可在某次使用完流之后调用clear函数使所有条件状态位复位,使其重新恢复有效状态。

 

使用ostringstream

例子:

ostringstream oss;
string word;
while(cin>>word)
    oss << word << " ";
cout<< oss.str() <<endl;

以上程序完成的事情是:依次读取所有输入的单词,并将单词“写入”到oss流对象,最后使用str函数将oss流对象包含的string以一行打印出来。(PS:最后也有一个空格)

 

文章评论

代码女神横空出世
代码女神横空出世
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员应该关注的一些事儿
程序员应该关注的一些事儿
10个调试和排错的小建议
10个调试和排错的小建议
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
编程语言是女人
编程语言是女人
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
旅行,写作,编程
旅行,写作,编程
我是如何打败拖延症的
我是如何打败拖延症的
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
一个程序员的时间管理
一个程序员的时间管理
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
Java程序员必看电影
Java程序员必看电影
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
鲜为人知的编程真相
鲜为人知的编程真相
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我的丈夫是个程序员
我的丈夫是个程序员
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
如何成为一名黑客
如何成为一名黑客
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
漫画:程序员的工作
漫画:程序员的工作
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员和编码员之间的区别
程序员和编码员之间的区别
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序员必看的十大电影
程序员必看的十大电影
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员的鄙视链
程序员的鄙视链
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员都该阅读的书
程序员都该阅读的书
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有