`
chenning009
  • 浏览: 4125 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

C++ Primer 第八章 标准 IO 库

 
阅读更多

8.1. 面向对象的标准库

IO 类型在三个独立的头文件中定义:iostream 定义读写控制窗口的类型,fstream 定义读写已命名文件的类型,而 sstream 所定义的类型则用于读写存储在内存中的 string 对象。在 fstreamsstream 里定义的每种类型都是从 iostream 头文件中定义的相关类型派生而来。

 

 

Header

Type

iostream

istream 从流中读取

ostream 写到流中去

iostream 对流进行读写;从 istreamostream 派生而来

fstream

ifstream 从文件中读取;由 istream 派生而来

ofstream 写到文件中去;由 ostream 派生而来

fstream 读写文件;由 iostream 派生而来

sstream

istringstreamstring 对象中读取;由 istream 派生而来

ostringstream 写到 string 对象中去;由 ostream 派生而来

stringstreamstring 对象进行读写;由 iostream 派生而来

 

迄今为止,所描述的流类(stream class)读写的是由 char 类型组成的流。此外,标准库还定义了一组相关的类型,支持 wchar_t 类型。每个类都加上“w ”前缀以此与 char 类型的版本区分开来 。于是,wostreamwistreamwiostream 类型从控制窗口读写 wchar_t 数据。相应的文件输入输出类是 wifstreamwofstreamwfstream 。而 wchar_t 版本的 string 输入/输出流则是 wistringstreamwostringstreamwstringstream 。标准库还定义了从标准输入输出读写宽字符的对象。这些对象加上“w ”前缀,以此与 char 类型版本区分:wchar_t 类型的标准输入对象是 wcin ;标准输出是 wcout ;而标准错误则是 wcerr

 

IO 对象不可复制或赋值

这个要求有两层特别重要的含义。正如在第九章 看到的,只有支持复制的元素类型可以存储在 vector 或其他容器类型里 。由于流对象不能复制 ,因此不能存储在 vector (或其他)容器中(即不存在存储流对象的 vector 或其他容器)

 

第二个含义是:形参或返回类型也不能为流类型 。如果需要传递或返回 IO 对象,则必须传递或返回指向该对象的指针或引用:

 

8.2. 条件状态

实现 IO 的继承正是错误发生的根源。一些错误是可恢复的;一些错误则发生在系统底层,位于程序可修正的范围之外。IO 标准库管理一系列条件状态(condition state) 成员,用来标记给定的 IO 对象是否处于可用状态 ,或者碰到了哪种特定的错误。表 8.2 列出了标准库定义的一组函数和标记,提供访问和操纵流状态的手段。

 

表 8.2. IO 标准库的条件状态

strm ::iostate

 

机器相关的整型名,由各个 iostream 类定义,用于定义条件状态

strm ::badbit

 

strm ::iostate 类型的值,用于指出被破坏的流

strm ::failbit

 

strm ::iostate 类型的值,用于指出失败的 IO 操作

strm ::eofbit

 

strm ::iostate 类型的值,用于指出流已经到达文件结束符

s.eof()

如果设置了流 seofbit 值,则该函数返回 true

s.fail()

如果设置了流 sfailbit 值,则该函数返回 true

s.bad()

如果设置了流 sbadbit 值,则该函数返回 true

s.good()

如果流 s 处于有效状态,则该函数返回 true

s.clear()

 

将流 s 中的所有状态值都重设为有效状态

s.clear(flag)

 

将流 s 中的某个指定条件状态设置为有效。flag 的类型是 strm ::iostate

s.setstate(flag)

 

给流 s 添加指定条件。flag 的类型是 strm ::iostate

s.rdstate()

 

返回流 s 的当前条件,返回值类型为 strm ::iostate

 

if 语句直接检查流的状态,而 while 语句则检测条件表达式返回的流,从而间接地检查了流的状态。如果成功输入,则条件检测为 true

 

    int ival;
    // read


 cin


 and test only for EOF; loop is executed even if there are other IO failures



    while (cin >> ival, !cin.eof()) {
        if (cin.bad())         // input stream is corrupted; bail out



            throw runtime_error("IO stream corrupted");
        if (cin.fail()) {                        // bad input



            cerr<< "bad data, try again";        // warn the user



            cin.clear(istream::failbit);         // reset the stream



            continue;                            // get next input



        }
        // ok to process


 ival



    }

8.3. 输出缓冲区的管理

系统将字符串字面值存储在与流 os 关联的缓冲区中。下面几种情况将导致缓冲区的内容被刷新,即写入到真实的输出设备或者文件:

程序正常结束 。作为 main 返回工作的一部分,将清空所有输出缓冲区。

在一些不确定的时候,缓冲区可能已经满了 ,在这种情况下,缓冲区将会在写下一个值之前刷新。

用操纵符(第 1.2.2 节显式地刷新缓冲区,例如行结束符 endl

在每次输出操作执行完后,unitbuf 操作符设置流的内部状态,从而清空缓冲区

可将输出流与输入流关联(tie )起来。在这种情况下,在读输入流时将刷新其关联的输出缓冲区

 

我们的程序已经使用过 endl 操纵符,用于输出一个换行符并刷新缓冲区。除此之外,C++ 语言还提供了另外两个类似的操纵符。第一个经常使用的 flush ,用于刷新流,但不在输出中添加任何字符。第二个则是比较少用的 ends ,这个操纵符在缓冲区中插入空字符 null,然后后刷新它:

 

如果需要刷新所有输出,最好使用 unitbuf 操纵符。这个操纵符在每次执行完写操作后都刷新流:

cout << unitbuf << "first" << " second" << nounitbuf;

等价于:

    cout << "first" << flush << " second" << flush;

nounitbuf 操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。

 

警告:如果程序崩溃了,则不会刷新缓冲区

如果需要使用最后的输出给程序错误定位,则必须确定所有要输出的都已经输出。为了确保用户看到程序实际上处理的所有输出, 最好的方法是保证所有的输出操作都显式地调用了 flushendl

 

将输入和输出绑在一起

tie 函数可用 istreamostream 对象调用,使用一个指向 ostream 对象的指针形参。调用 tie 函数时,将实参流绑在调用该函数的对象上。如果一个流调用 tie 函数将其本身绑在传递给 tieostream 实参对象上,则该流上的任何 IO 操作都会刷新实参所关联的缓冲区。

 

一个 ostream 对象每次只能与一个 istream 对象绑在一起如果在调用 tie 函数时传递实参 0,则打破该流上已存在的捆绑。

 

8.4. 文件的输入和输出

fstream 类型除了继承下来的行为外,还定义了两个自己的新操作—— openclose ,以及形参为要打开的文件名的构造函数。fstreamifstreamofstream 对象可调用这些操作,而其他的 IO 类型则不能调用

 

警告:C++ 中的文件名

由于历史原因,IO 标准库使用 C 风格字符串(第 4.3 节 )而不是 C++ strings 类型的字符串作为文件名。在创建 fstream 对象时,如果调用 open 或使用文件名作初始化式,需要传递的实参应为 C 风格字符串,而不是标准库 strings 对象。程序常常从标准输入获得文件名。通常,比较好的方法是将文件名读入 string 对象,而不是 C 风格字符数组。假设要使用的文件名保存在 string 对象中,则可调用 c_str 成员(第 4.3.2 节 )获取 C 风格字符串。

检查文件打开是否成功

打开文件后,通常要检验打开是否成功,这是一个好习惯:

    // check that the


 open


 succeeded



    if (!infile) {
        cerr << "error: unable to open input file: "
             << ifile << endl;
        return -1;
    }
将文件流与新文件重新捆绑

先关再开 ,如:

     ifstream infile("in");      // opens file named "in" for reading



     infile.close();             // closes "in"



     infile.open("next");        // opens file named "next" for reading



清除文件流的状态

如果希望避免在每次 while 循环过程中创建新流对象,可将 input 的定义移到 while 之前。这点小小的改动意味着必须更仔细地管理流的状态。如果遇到文件结束符或其他错误,将设置流的内部状态,以便之后不允许再对该流做读写操作。关闭流并不能改变流对象的内部状态。如果最后的读写操作失败了,对象的状态将保持为错误模式,直到执行 clear 操作重新恢复流的状态为止。调用 clear 后,就像重新创建了该对象一样。

    ifstream input;
    vector<string>::const_iterator it = files.begin();
    //   for each file in the


 vector



    while (it != files.end()) {
        input.open(it->c_str());  // open the file



        // if the file is ok, read and "process" the input



        if (!input)
            break;                    // error: bail out!



        while(input >> s) // do the work on this file



            process(s);
        input.close();        // close file when we're done with it






        input.clear();        // reset state to ok






        ++it;                 // increment iterator to get next file



    }

如果程序员需要重用文件流读写多个文件,必须在读另一个文件之前调用 clear 清除该流的状态。

 

 

8.4.2. 文件模式

 

in

打开文件做读操作

out

打开文件做写操作

app

在每次写之前找到文件尾

ate

打开文件后立即将文件定位在文件尾

trunc

打开文件时清空已存在的文件流

binary

以二进制模式进行 IO 操作

 

 

从效果来看,为 ofstream 对象指定 out 模式等效于同时指定了 outtrunc 模式。


对同一个文件作输入和输出运算

fstream 对象既可以读也可以写它所关联的文件。fstream 如何使用它的文件取决于打开文件时指定的模式

默认情况下,fstream 对象以 inout 模式同时打开。当文件同时以 inout 打开时不清空。如果打开 fstream 所关联的文件时,只使用 out 模式,而不指定 in 模式,则文件会清空已存在的数据。如果打开文件时指定了 trunc 模式,则无论是否同时指定了 in 模式,文件同样会被清空。 下面的定义将 copyOut 文件同时以输入和输出的模式打开:

    // open for input and output



    fstream inOut("copyOut", fstream::in | fstream::out);
模式是文件的属性而不是流的属性

8.5. 字符串流

  • istringstream ,由 istream 派生而来,提供读 string 的功能。

  • ostringstream ,由 ostream 派生而来,提供写 string 的功能。

  • stringstream ,由 iostream 派生而来,提供读写 string 的功能。

表 8.5. stringstream 特定的操作

stringstream strm;

 

创建自由的 stringstream 对象

stringstream strm(s);

 

创建存储 s 的副本的 stringstream 对象,其中 s 是 string 类型的对象

strm.str()

 

返回 strm 中存储的 string 类型对象

strm.str(s)

 

string 类型的 s 复制给 strm ,返回 void

 

分享到:
评论

相关推荐

    C++Primer第五版 第8章 IO库(练习解答)

    C++Primer第五版 第8章 IO库(练习解答)个人总结的文档+源码,供学习参考之用,遗漏之处请参考我的博客

    C++primer 课后题答案

    第八章 标准IO库 37 第九章 顺序容器 43 第十章 关联容器 60 第十一章 泛型算法 75 第十二章 类和数据抽象 86 第十三章 复制控制 94 第十四章 重载操作符与转换 102 第十五章 面向对象编程 116 第十六章 部分选做...

    C++ Primer第四版【中文高清扫描版】.pdf

    第8章 标准IO库 243 8.1 面向对象的标准库 244 8.2 条件状态 247 8.3 输出缓冲区的管理 249 8.4 文件的输入和输出 251 8.4.1 文件流对象的使用 251 8.4.2 文件模式 254 8.4.3 一个打开并检查输入文件的 程序 256 ...

    非常经典的c++ primer视频教程6-10

    本课程是C++ Primer初级教程,课程内容是学习C++语言基础知识,对应着教材的第1章到第8章。 第1章 快速入门 1.1 编写简单的C++程序 1.2 初窥输入/输出 1.2.1 标准输入与输出对象 1.2.2 一个使用IO库的程序 ...

    C++Primer视频(初级)下载地址

    1.下载和安装VC++2008 ...第8章面向对象的标准IO库 75.第8章条件状态 76.第8章文件流对象的使用 77.第8章重点习题解答 78.第8章文件模式 79.第8章一个打开并检查输入文件的程序 80.第8章字符串流

    C++ Primer中文版(第5版)李普曼 等著 pdf 1/3

     第8章 IO库 277  8.1 IO类 278  8.1.1 IO对象无拷贝或赋值 279  8.1.2 条件状态 279  8.1.3 管理输出缓冲 281  8.2 文件输入输出 283  8.2.1 使用文件流对象 284  8.2.2 文件模式 286  8.3 string流 287 ...

    C++ primer 第4版 原书+习题解答+源码 清晰pdf

     第8章 标准IO库  8.1 面向对象的标准库  8.2 条件状态  8.3 输出缓冲区的管理  8.4 文件的输入和输出  8.5 字符串流  小结  术语  第二部分 容器和算法  第9章 顺序容器  第10章 关联容器 ...

    C++Primer(第5版 )中文版(美)李普曼等著.part2.rar

     第8章 IO库 277  8.1 IO类 278  8.1.1 IO对象无拷贝或赋值 279  8.1.2 条件状态 279  8.1.3 管理输出缓冲 281  8.2 文件输入输出 283  8.2.1 使用文件流对象 284  8.2.2 文件模式 286  8.3 string流 287 ...

    C++Primer中文版(第4版).part4

     第8章 标准IO库  8.1 面向对象的标准库  8.2 条件状态  8.3 输出缓冲区的管理  8.4 文件的输入和输出  8.5 字符串流  小结  术语  第二部分 容器和算法  第9章 顺序容器  第10章 关联容器 ...

    C++ Primer习题集 第5版(完整版)

    第8章 IO库 183 练习8.1~练习8.14 第9章 顺序容器 193 练习9.1~练习9.52 第10章 泛型算法 234 练习10.1~练习10.42 第11章 关联容器 273 练习11.1~练习11.38 第12章 动态内存 297 练习12.1~练习12.33 ...

    java坑爹的笔试题-cpp-primer-5th:C++Primer第五版学习资料

    ,第8、9章最为重要,IO库和容器对于一个程序来说是比较基础的,记得不要在C++中还依然保持C的习惯,使用cout而不是printf()、使用vector而不是内置数组、使用迭代器进行遍历。第10、11章有点基础的看起来不是很难,...

    CppPrimer5th:CppPrimer5th的习题解答

    The Solutions for C++ Primer 5th目录第I部分 C++基础第2章 变量和基本类型第3章 字符串、向量和数组第4章 表达式第5章 语句第6章 函数第7章 类第II部分 C++标准库第8章 IO库第9章 顺序容器第10章 泛型算法第11章 ...

    [C++ Primer中文版(第4版)].习题解答(1-18章完整版)

    37 第八章 标准IO库 ................................................................................................................................................. 37 第九章 顺序容器 ..................

    CppPrimer:C++ 入门 5 个回答

    ##C++ 入门 5 个回答 笔记 编译时使用-std=c++11 (可选: -pedantic -Wall ...第 8 章 IO 库 第 9 章顺序容器 第 10 章通用算法 第 11 章关联容器 第三部分:课堂作者工具 第四部分:高级主题 第 19 章专用工具和技术

    Linux多线程服务端编程:使用muduo C++网络库

    《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...

Global site tag (gtag.js) - Google Analytics