1 流和缓冲区
C++程序把输入和输出看作字节流。输入时,程序从输入流中抽取字节;输出时,程序将字节插入到输出流中。
缓冲区是用作中介的内存块,它是将信息从设备传输到程序或从程序传输给设备的临时存储工具,通过使用缓冲区可以更高效地处理输入和输出。
iostream 文件中包含了一些专门设计用来实现、管理流和缓冲区的类:
- streambuf 类为缓冲区提供了内存,并提供了用于填充缓冲区、访问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法。
- ios_base 类表示流的一般特征,如是否可读取、是二进制流还是文本流等。
- ostream 类是从 ios 类派生而来的,提供了输出方法。
- istream 类也是从 ios 类派生而来的,提供了输入方法。
- iostream 类是基于 istream 类和 ostream 类的,因此继承了输入方法和输出方法。
1.1 iostream 类库对象
C++ 的 iostream 类库管理了很多细节。例如,在程序中包含 iostream 文件将自动创建 8 个流对象(4个用于窄字符流,4个用于宽字符流):
- cin 对象对应于标准输入流,默认会被关联到标准输入设备(通常为键盘)。wcin 对象与此类似,但处理的是 wchar_t 类型。
- cout 对象对应于标准输出流,默认会被关联到标准输出设备(通常为显示器)。wcout 对象与此类似,但处理的是 wchar_t 类型。
- cerr 对象对应于标准错误流,可用于显示错误信息,默认会被关联到标准输出设备(通常为显示器),这个流没有被缓冲,这意味着消息将被直接发送给屏幕。wcerr 对象与此类似,但处理的是 wchar_t 类型。
- clog 对象也对应于标准错误流,默认会被关联到标准输出设备(通常为显示器),这个流被缓冲。wclog 对象与此类似,但处理的是 wchar_t 类型。
1.2 ostream 对象方法
重载的 << 作为插入操作符,将其重载为输出。支持识别 C++ 中所有的基本类型和部分指针类型(const signed char*、const unsigned char*、const char*、void*)。
ostream& operator<< (T value);
由于插入操作符的调用返回类型是 ostream&,因此也支持拼接输出 cout << a << b。
-
put() 方法用于显示字符,write() 方法用于显示字符串。
-
控制符 flush 用于刷新缓冲区。
实际上,这类控制符如 flush 也是函数,只是因为 << 重载了,所以支持这样调用:cout << flush,等价于 flush(cout)。
- 插入操作符在将值转为文本格式时,对char值、数值、字符串都有默认的格式化方式,但是可以调用相应函数来改变格式化的方式。
dec、hex、oct:修改显示时使用的计数系统。
width:调整字段宽度。
fill:填充字符。
precision:设置浮点数显示精度。
setf:控制浮点数打印的相关格式选项,例如 cout.setf(ios_base::showpoint) 可以选择打印末尾的 0 和小数点。
- iomanip 头文件提供了以上简化调用的控制符,例如 setprecision()、setfill()、setw()。
1.3 istream 对象方法
同样地,重载的 >> 作为抽取操作符,支持将输入数据转换为目标指定的格式。
istream& operator>> (T& value);
1.4 流状态
cin 或 cout 对象包含一个描述流状态的数据成员(从 ios_base 类继承)。
流状态(ios_state 类型,是一种 bitmask 类型)由 3 个 ios_base 元素组成:eofbit、badbit、failbit。
- get(char&) 和 get(void) 方法提供不跳过空白的单字符输入功能。
- get(char*, int, char) 和 getline(char*, int, char) 方法在默认情况下会读取整行。
-
ignore(int = 1, int = EOF) 方法用于读取并丢弃字符。
-
read() 方法用于读取指定数目的字节,并将它们存储在指定的位置。
-
peek() 方法返回输入中的下一个字符,但不抽取输入流中的字符。
-
gcount() 方法返回最后一个非格式化抽取方法读取的字符数(即不是用 << 读取的)。
-
putback() 方法将一个字符插入到输入字符串中,被插入的字符将是下一条输入语句读取的第一个字符。
2 文件输入和输出
头文件 fstream 定义了用于文件输入的 ifstream 类、用于文件输出的 ofstream 类和用于同步文件 I/O 的 fstream 类。
文件打开:
- ifstream is; is.open(“filePath”);
- ifstream is(“filePath”);
文件关闭:
- is.close();
在打开文件时,可以提供指定文件模式的第二个参数:
ifstream is(“filePath”, mode);
2.1 二进制文件
将数据存储在文件中时,可以将其存储为文本格式或二进制格式。
为执行二进制 I/O,需要使用 ios_base::binary 模式。
3 内核格式化
C++ 库还提供了 sstream 族,它们使用相同的接口提供程序和 string 对象之间的 I/O。读取 string 对象中的格式化信息或将格式化信息写入 string 对象中被称为内核格式化
。
sstream 头文件定义了从 ostream 类派生而来的 ostringstream 类和从 istream 类派生而来的 istringstream 类。