《C++primer》第八章读书笔记(Chapter 8 reading notes of C + + primer)

《C++Primer 第五版》

——读书随笔集

第八章

8.1 IO类

  • istream,(输入流)类型,提供输入操作
  • ostream ,(输出流)类型,提供输出操作
  • cin,一个istream对象,从标准输入读取数据‘
  • cout,一个ostream对象,向标准输出写入数据
  • cerr,一个ostream对象,通常用于输出程序错误消息,写入到标准错误
  • <<运算符,用来向一个ostream对象中写入输出数据
  • />>运算符,用来从一个istream对象中读取输入数据

8.1.1 IO对象无拷贝和赋值

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

ofstream out1, out2;
out1 = out2; //错误:不能对流对象赋值
ofstream print(ofstream); //错误:不能初始化ofstream对象
out2 = print(out2); //错误,不能拷贝流对象
头文件 类型
iostream istream,wistream从流中读取数据
ostream,wostream向流中写入数据
iostream,wiostream读写流
fstream ifstream,wifstream从文件中读取数据
ofstream,wofstream向文件中写入数据
fstream,wfstream读写文件
sstream istringstream,wistringstream从string中读取数据
ostringstream,wostringstream向string中写入数据
stringstream,wstringstream读写string

为了支持宽类型,标准库定义了一组类型和对象来wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始。

本文介绍的标准库流特性都可以无差别地应用于普通流,文件流和string流,以及char或宽字符版本

8.1.2 条件状态

IO类定义了一些函数和标志,可以帮助我们访问和操纵流的条件状态

strm::iostate strm是一种IO类型,iostate是一种机器相关的类型,提供了表达条件状态的完整功能
strm::badbit strm::badbit指流已崩溃
strm::failbit strm::failbit用来指一个IO操作已经失败
strm::eofbit strm::eofbit用来指出流到达了文件结束
strm::goodbit strm::goodbit用来指出流未处于错误状态。此值保证为零
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit或badbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear(flags) 根据给定的flags标志位,将流中对应条件状态位复位。flags的类型为strm::iostate。返回void
s.setstate(flags) 根据给定的flags标志位,将流中对应条件状态位置位。flags的类型为strm::iostate。返回void
s.rdstate() 返回流s的当前条件状态,返回值类型为strm::iostate
  • 查询流的状态
    badbit表示系统级错误,如不可恢复的错误。通常情况下,一旦badbit被置位,那么流就无法使用了。
    failbit被置位,如期望读取一个数值,结果读取了一个字符。这种问题是可以修复的,流还能继续使用。
    如果到达文件结束位置,eofbit和failbit就会被置位。goodbit的值为0,表示流还未发生错误。
    如果failbit,eofbit和badbit任一个被置位,则检测流状态的条件就会失败。
    标准库还提供了一组函数来查询这些标志位的状态。操作good在所有错误位均未被置位的情况下返回true。
  • 管理条件状态
    clear函数成员是一个重载的成员。他有一个接受参数的版本和一个不接受参数的版本。不接收参数的版本清除所有错误标志位。执行clear()后,调用good会返回true。
    auot old_stat = cin.rdstate(); //返回原来的旧参数
    cin.clear(); //清除参数
    process(cin); // 使用cin
    cin.setstate(old_state); //复原原来的cin

    带参数的clear版本接受一个iostate值,表示流的新状态。为了复位单一的状态位,我们可以首先用rdstate读出当前条件状态,然后用位操作将所需位复位来生成新的状态。例如:
    cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit) //将failbit和badbit复位,其它位保持不变。

8.1.3 管理输出缓冲

每个输出流都有一个缓冲区,用来保存程序读写的数据。

  • 刷新输出缓冲区
    可以使用操纵符endl来完成换行并刷新缓冲区。
    可以使用flush刷新缓冲区,但不输出任何额外的字符。
    可以使用ends向缓冲区插入一个空字符,然后刷新缓冲区。
  • unitbuf操纵符
    使用unitbuf可以在每次输出操作后,都刷新缓冲区,它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用系统正常的缓冲区刷新机制。
    cout<
  • 关联输入和输出流
    当一个输入流被关联到一个输出流时,任何一个试图从输入流读取数据的操作都会先刷新关联的输出流。标准库将cout和cin关联在一起
    cin>>ival; //将刷新cout的缓冲区

    交互式系统通常应该关联输入流和输出流。这意味着用户在输入之前,所有输出包括提示信息都应该被输出。
    tie函数有两个重载的版本:一个不带参数(返回指向输出流的指针)。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie的第二个版本接受收一个指向ostream的指针,将自己关联到另一个ostream。
    cin.tie(&cout); //仅仅用来展示
    ostream *old_tie = cin.tie(nullptr);//cin不再与其它流关联
    cin.tie(&cerr); //读取cin会刷新cerr
    cin.tie(&old_tie);//重建cin和cout之间的联系

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

8.2 文件的输入输出

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

这些类型提供的操作与我们之前已经使用过的对象cin和cout一样。它除了继承来自iostream类型的行为以外,fstream中定义的类型还新增了成员来管理与流关联的文件。这些成员只能对ifstream,ofstream,fstream对象调用这些操作,但不能对其他IO类型调用这些操作。

fstream fstrm 创建一个未绑定的文件流
fstream fstrm(s) 创建一个fstream,并打开名为s的文件。
fstream fstream(s,mode) 与前一个构造函数类型,但按指定mode打开文件
fstrm.open(s) 打开名为s的文件,并将文件与fstrm绑定。返回void
fstrm.close() 关闭与fstrm绑定的文件。返回void
fstrm.is_open() 返回一个bool值,指出文件是否打开且尚未关闭。

8.2.1使用文件流对象

ifstream in(file); //构建一个ifstream并打开给定文件
ofstream out; //输出流未关联到任何文件

文件名可以是一个库类型string对象,也可以是C风格字符数组

  • 用fstream代替iostream&
    在要求使用基类型对象的地方,我们可以用继承类型的对象来代替。
  • 成员函数open和close
    ifstream in(ifile); //构建一个ifstream并打开文件
    ofstream out; //输出文件流未与任何文件关联
    out.open(ifile + “.copy”); //打开指定文件

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

8.2.2 文件模式

每个流都有一个文件模式,用来指出如何使用文件。

in 以读方式打开
out 以写方式打开
app 每次写操作前均定位到文件末尾
ate 打开文件后立即定位到文件末尾
trunc 截断文件
binary 以二进制方式进行IO

无论用哪种方式打开文件,我们都可以指定文件模式,调用open打开文件时可以,用一个文件名初始化流来隐式打开文件时也可以。指定文件模式有如下限制∶

  • 只可以对 ofstream 或 fstream 对象设定 out 模式。
  • 只可以对ifstream 或 fstream 对象设定 in 模式。
  • 只有当 out 也被设定时才可设定 trunc 模式。
  • 只要trunc没被设定,就可以设定 app 模式。在app 模式下,即使没有显式指定 out 模式,文件也总是以输出方式被打开。
  • 默认情况下,即使我们没有指定trunc,以out 模式打开的文件也会被截断。为了保留以out 模式打开的文件的内容,我们必须同时指定 app 模式,这样只会将数据追加写到文件末尾;或者同时指定in 模式,即打开文件同时进行读写操作。
  • ate和binary 模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。

每个文件流类型都定义了一个默认的文件模式,当我们未指定文件模式时,就使用此默认模式。与ifstream关联的文件默认以in 模式打开;与 ofstream关联的文件默认以 out 模式打开;与fstream关联的文件默认以in 和 out 模式打开。

以out模式打开文件会丢失已有数据

默认情况下,当我们打开一个 ofstream 时,文件的内容会被丢弃。阻止一个 ofstream 清空给定文件内容的方法是同时指定 app 模式∶

// 在这几条语句中file1都被截断
ofstream out("file1");                    // 隐含以输出模式打开文件并截断文件                              
ofstream out2("file1", ofstream::out);    // 隐含地截断文件
ofstream out3("file1", ofstream::out | ofstream::trunc);
// 为保留文件内容,我们必须显式指定app模式
ofstream app("file2", ofstream::app);    // 隐含为输出模式
ofstream app2("file2", ofstream::out | ofstream::app);

每次调用open时都会确定文件模式

对于一个给定的流,每次打开文件时,都可以改变文件模式

ofstream out;                            // 未指定文件打开模式
out.open("scratchpad");                  // 模式隐含地设置为输出和截断
out.close();                             // 关闭out,以便用于其他文件
out.open("precious", ofstream::app);     // 模式为输出和追加
out.close();

第一个open调用未显式指定输出模式,文件隐式地以out 模式打开。

通常情况下,out模式意味着同时使用trunc模式。因此,当前目录下名为scratchpad的文件的内容将被清空。

当打开名为 precious 的文件时,我们指定了append模式。文件中已有的数据都得以保留,所有写操作都在文件末尾进行。

8.3 string流

sstream头文件定义了三个类型来支持内存IO,这些类型可以向string写入数据,也可以从string读取数据,就像string是一个IO流一样。

istringstream从string读取数据,ostringstream向string写入数据,而头文件stringstream都可以。下列是sstream特有的成员。

sstream strm strm是一个未绑定的stringstream对象
sstream strm(s) strm是一个sstream对象,保存了string s的一个拷贝
strm.str() 返回strm所保存的string的拷贝,返回的是个string
strm.str(s) 将string s拷贝到strm中。返回void
————————

C + + primer Fifth Edition

——Collection of reading essays

Chapter VIII

8.1 IO class

  • Istream (input stream) type, which provides input operations
  • Ostream (output stream) type, which provides output operations
  • CIN, an istream object, reads data from standard input‘
  • Cout, an ostream object, writes data to standard output
  • Cerr, an ostream object, is usually used to output program error messages and write them to standard errors
  • < < operator, which is used to write output data to an ostream object
  • />>Operator to read input data from an istream object

8.1.1 IO object has no copy and assignment

We cannot copy or assign values to IO objects, so we cannot set formal parameters or return types to stream types. Functions that perform IO operations usually pass and return streams by reference. Reading and writing an IO object will change its state, so the reference passed and returned cannot be const.

ofstream out1, out2;
out1 = out2; //错误:不能对流对象赋值
ofstream print(ofstream); //错误:不能初始化ofstream对象
out2 = print(out2); //错误,不能拷贝流对象
头文件 类型
iostream istream,wistream从流中读取数据
ostream,wostream向流中写入数据
iostream,wiostream读写流
fstream ifstream,wifstream从文件中读取数据
ofstream,wofstream向文件中写入数据
fstream,wfstream读写文件
sstream istringstream,wistringstream从string中读取数据
ostringstream,wostringstream向string中写入数据
stringstream,wstringstream读写string

To support wide types, the standard library defines a set of types and objects to wchar_ Data of type T. The names of types and functions in the wide character version start with a W.

< strong > the standard library stream features described in this article can be applied to ordinary streams, file streams and string streams, as well as char or wide character versions < / strong >

8.1.2 condition status

The IO class defines some functions and flags that can help us access and manipulate the < strong > condition status of the flow < / strong >

strm::iostate strm是一种IO类型,iostate是一种机器相关的类型,提供了表达条件状态的完整功能
strm::badbit strm::badbit指流已崩溃
strm::failbit strm::failbit用来指一个IO操作已经失败
strm::eofbit strm::eofbit用来指出流到达了文件结束
strm::goodbit strm::goodbit用来指出流未处于错误状态。此值保证为零
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit或badbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear(flags) 根据给定的flags标志位,将流中对应条件状态位复位。flags的类型为strm::iostate。返回void
s.setstate(flags) 根据给定的flags标志位,将流中对应条件状态位置位。flags的类型为strm::iostate。返回void
s.rdstate() 返回流s的当前条件状态,返回值类型为strm::iostate
  • Status of query flow
    Badbit indicates a system level error, such as an unrecoverable error. In general, once badbit is set, the stream cannot be used.
    Failbit is set to read a value as expected, and a character is read as a result. This problem can be fixed and the stream can continue to be used.
    If the end of the file is reached, eofbit and failbit are set. The value of goodbit is 0, indicating that no error has occurred in the stream.
    If any of failbit, eofbit and badbit is set, the condition to detect the flow state will fail.
    The standard library also provides a set of functions to query the status of these flag bits. The operation good returns true when all error bits are not set.
  • Management condition status
    The clear function member is an overloaded member. It has a version that accepts parameters and a version that does not accept parameters. The version that does not receive the parameter clears all error flag bits. After executing clear (), calling good will return true.
    auot old_ stat = cin.rdstate(); // Returns the original old parameter
    cin.clear(); // Clear parameters
    process(cin); // Using CIN
    cin.setstate(old_state); // Restore the original CIN
    The clear version with parameters accepts an iostate value indicating the new state of the flow. In order to reset a single status bit, we can first read out the current condition state with rdstate, and then reset the required bit with bit operation to generate a new state. For example:
    CIN. Clear (CIN. Rdstate() & ~ CIN. Failbit & ~ CIN. Badbit) / / reset failbit and badbit and keep other bits unchanged.

8.1.3 manage output buffer

Each output stream has a buffer to hold the data read and written by the program.

  • Flush output buffer
    You can use the operator endl to wrap lines and flush the buffer.
    You can use flush to flush the buffer without outputting any additional characters.
    You can use ends to insert an empty character into the buffer and then flush the buffer.
  • Unitbuf operator
    Using unitbuf, you can flush the buffer after each output operation, which tells the stream to flush after each subsequent write operation. The nounitbuf operator resets the stream to use the normal buffer refresh mechanism of the system.
    cout<
  • Associate input and output streams
    When an input stream is associated with an output stream, any operation that attempts to read data from the input stream will refresh the associated output stream first. The standard library associates cout and CIN together
    cin>>ival; // The buffer of cout will be flushed
    Interactive systems should usually associate input and output streams. This means that all output, including prompt information, should be output before the user inputs.
    The tie function has two overloaded versions: one with no parameters (returns a pointer to the output stream). If the object is currently associated with an output stream, it returns a pointer to the stream. If the object is not associated with a stream, it returns a null pointer. The second version of tie accepts a pointer to an ostream and associates itself with another ostream.
    cin.tie(&cout); // Just to show
    ostream *old_ tie = cin.tie(nullptr);// CIN is no longer associated with other flows
    cin.tie(&cerr); // Reading CIN refreshes the cerr
    cin.tie(&old_tie);// Reconstruct the relationship between CIN and cout
    Each flow can be associated with at most one flow at the same time, but multiple flows can be associated with the same ostream

8.2 input and output of documents

The header file fsstream defines three types to support file IO: ifstream, OFSTREAM and fsstream.

These types provide the same operations as the objects CIN and cout we have used before. In addition to inheriting the behavior from iostream types, the types defined in fsstream also add members to manage the files associated with the stream. These members can only call these operations on ifstream, OFSTREAM and fsstream objects, but they cannot call these operations on other IO types.

fstream fstrm 创建一个未绑定的文件流
fstream fstrm(s) 创建一个fstream,并打开名为s的文件。
fstream fstream(s,mode) 与前一个构造函数类型,但按指定mode打开文件
fstrm.open(s) 打开名为s的文件,并将文件与fstrm绑定。返回void
fstrm.close() 关闭与fstrm绑定的文件。返回void
fstrm.is_open() 返回一个bool值,指出文件是否打开且尚未关闭。

8.2.1 using file stream objects

ifstream in(file); //构建一个ifstream并打开给定文件
ofstream out; //输出流未关联到任何文件

< strong > the file name can be a library type string object or a C-style character array < / strong >

  • Fsstream instead of iostream&
    Where base type objects are required, we can replace them with objects of inherited types.
  • 成员函数open和close
    ifstream in(ifile); //构建一个ifstream并打开文件
    ofstream out; //输出文件流未与任何文件关联
    out.open(ifile + “.copy”); //打开指定文件

  • Automatic construction and Deconstruction
    When an fstream object is destroyed, close is automatically called

8.2.2 document mode

Each stream has a file schema that indicates how files are used.

in 以读方式打开
out 以写方式打开
app 每次写操作前均定位到文件末尾
ate 打开文件后立即定位到文件末尾
trunc 截断文件
binary 以二进制方式进行IO

No matter which way to open the file, we can specify the file mode. When calling open to open the file, we can also use a file name initialization stream to implicitly open the file. The specified file mode has the following limitations:

  • 只可以对 ofstream 或 fstream 对象设定 out 模式。
  • 只可以对ifstream 或 fstream 对象设定 in 模式。
  • The TRUNC mode can be set only when out is also set.
  • As long as TRUNC is not set, the app mode can be set. In app mode, even if out mode is not explicitly specified, the file is always opened as output.
  • By default, even if TRUNC is not specified, files opened in out mode will be truncated. In order to preserve the contents of the file opened in out mode, we must specify the app mode at the same time, so that only the data will be appended to the end of the file; Or specify the in mode at the same time, that is, open the file and read and write at the same time.
  • The ate and binary modes can be used for any type of file stream object and can be used in combination with any other file mode.

Each file stream type defines a default file mode, which is used when we do not specify a file mode. The files associated with ifstream are opened in in mode by default; The files associated with OFSTREAM are opened in out mode by default; Files associated with fstream are opened in in and out mode by default.

< strong > opening a file in out mode will lose existing data < / strong >

By default, when we open an OFSTREAM, the contents of the file are discarded. The method to prevent an OFSTREAM from emptying the contents of a given file is to specify the app mode at the same time:

// 在这几条语句中file1都被截断
ofstream out("file1");                    // 隐含以输出模式打开文件并截断文件                              
ofstream out2("file1", ofstream::out);    // 隐含地截断文件
ofstream out3("file1", ofstream::out | ofstream::trunc);
// 为保留文件内容,我们必须显式指定app模式
ofstream app("file2", ofstream::app);    // 隐含为输出模式
ofstream app2("file2", ofstream::out | ofstream::app);

< strong > the file mode will be determined every time open is called < / strong >

For a given stream, the file mode can be changed each time a file is opened

ofstream out;                            // 未指定文件打开模式
out.open("scratchpad");                  // 模式隐含地设置为输出和截断
out.close();                             // 关闭out,以便用于其他文件
out.open("precious", ofstream::app);     // 模式为输出和追加
out.close();

The first open call does not explicitly specify the output mode, and the file is implicitly opened in out mode.

In general, out mode means using TRUNC mode at the same time. Therefore, the contents of the file named scratchpad in the current directory will be emptied.

When we open the file named precious, we specify the append mode. The existing data in the file is retained, and all writes are performed at the end of the file.

8.3 string流

The ssstream header file defines three types to support memory io. These types can write data to or read data from string, just as string is an IO stream.

Istringstream reads data from string, ostringstream writes data to string, and the header file stringstream can. The following are ssstream specific members.

sstream strm strm是一个未绑定的stringstream对象
sstream strm(s) strm是一个sstream对象,保存了string s的一个拷贝
strm.str() 返回strm所保存的string的拷贝,返回的是个string
strm.str(s) 将string s拷贝到strm中。返回void