C++I/O操作:异常、函数与操纵符详解
立即解锁
发布时间: 2025-08-22 00:43:53 阅读量: 3 订阅数: 16 


深入解析C++标准库:从入门到精通
### C++ I/O 操作:异常、函数与操纵符详解
#### 1. C++11 之前的 I/O 异常
在 C++11 之前,`std::ios_base::failure` 类直接从 `std::exception` 类派生而来,并且只有一个接受 `std::string` 参数的构造函数,代码如下:
```cpp
namespace std {
class ios_base::failure : public exception {
public:
explicit failure (const string& msg);
...
};
}
```
这种设计带来了以下局限性:
- 对于生成的异常对象,只能调用 `what()` 方法来获取一个与实现相关的失败原因字符串,不支持异常类别或值。
- 由于构造函数只接受 `std::string` 类型的参数,当传递字符串字面量时,必须包含 `<string>` 头文件(因为需要相应字符串构造函数的声明来实现到 `std::string` 的转换)。
#### 2. 标准输入/输出函数
可以使用本节介绍的成员函数进行读写操作,而不是使用流的标准运算符(`operator <<` 和 `operator >>`)。这些函数读写“未格式化”的数据,与 `>>` 和 `<<` 运算符读写“格式化”的数据不同。在读取时,本节描述的函数从不跳过前导空格,而 `>>` 运算符默认会跳过前导空格,这由哨兵对象处理。此外,这些函数处理异常的方式与格式化 I/O 运算符不同:如果抛出异常(无论是从被调用的函数抛出,还是由于设置状态标志),`badbit` 标志会被设置。如果异常掩码中设置了 `badbit`,则会重新抛出异常。
标准 I/O 函数使用在 `<ios>` 中定义的 `streamsize` 类型来指定计数:
```cpp
namespace std {
typedef ... streamsize;
...
}
```
`streamsize` 通常是 `size_t` 的有符号版本,因为它也用于指定负值。
#### 3. 输入成员函数
对于输入流,C++ 标准库提供了几个成员函数来读取字符序列,不同函数的能力对比如下表所示(`s` 表示读取字符的字符序列):
| 成员函数 | 读取直到 | 字符数量 | 追加终止符 | 返回值 |
| --- | --- | --- | --- | --- |
| `get(s,num)` | 不包括换行符或文件结束符 | 最多 `num - 1` 个 | 是 | `istream` |
| `get(s,num,t)` | 不包括 `t` 或文件结束符 | 最多 `num - 1` 个 | 是 | `istream` |
| `getline(s,num)` | 包括换行符或文件结束符 | 最多 `num - 1` 个 | 是 | `istream` |
| `getline(s,num,t)` | 包括 `t` 或文件结束符 | 最多 `num - 1` 个 | 是 | `istream` |
| `read(s,num)` | 文件结束符 | `num` 个 | 否 | `istream` |
| `readsome(s,num)` | 文件结束符 | 最多 `num` 个 | 否 | 计数 |
以下是一些具体的输入成员函数及其功能:
- `int istream::get ()`:
- 读取下一个字符。
- 返回读取的字符或 `EOF`。
- 一般来说,返回类型是 `traits::int_type`,`EOF` 是 `traits::eof()` 返回的值。对于 `istream`,返回类型是 `int`,`EOF` 是常量 `EOF`,因此该函数对应于 C 语言的 `getchar()` 或 `getc()`。
- 注意,返回值不一定是字符类型,可能是具有更大取值范围的类型,否则无法区分 `EOF` 和具有相应值的字符。
- `istream& istream::get (char& c)`:
- 将下一个字符赋值给传入的参数 `c`。
- 返回流对象,流的状态表示读取是否成功。
- `istream& istream::get (char* str, streamsize count)` 和 `istream& istream::get (char* str, streamsize count, char delim)`:
- 两种形式都会将最多 `count - 1` 个字符读取到 `str` 指向的字符序列中。
- 第一种形式在读取到对应字符集的换行符时停止读取,对于 `istream` 是 `'\n'`,对于 `wistream` 是 `wchar_t('\n')`,一般使用 `widen('\n')`。
- 第二种形式在读取到 `delim` 字符时停止读取。
- 两种形式都返回流对象,流的状态表示读取是否成功。
- 终止字符(`delim`)不会被读取。
- 读取的字符序列以空字符结尾。
- 调用者必须确保 `str` 有足够的空间来存储 `count` 个字符。
- `istream& istream::getline (char* str, streamsize count)` 和 `istream& istream::getline (char* str, streamsize count, char delim)`:
- 这两种形式与 `get()` 函数的对应形式基本相同,区别在于:
- 它们分别在包括换行符或 `delim` 字符(但不提前)时停止读取。因此,如果在 `count - 1` 个字符内出现换行符或 `delim` 字符,会读取该字符,但不会存储在 `str` 中。
- 如果读取的行超过 `count - 1` 个字符,会设置 `failbit`。
- `istream& istream::read (char* str, streamsize count)`:
- 读取 `count` 个字符到 `str` 字符串中。
- 返回流对象,流的状态表示读取是否成功。
- `str` 中的字符串不会自动以空字符结尾。
- 调用者必须确保 `str` 有足够的空间来存储 `count` 个字符。
- 读取过程中遇到文件结束符被视为错误,除了设置 `eofbit` 外,还会设置 `failbit`。
- `streamsize istream::readsome (char* str, streamsize count)`:
- 最多读取 `count` 个字符到 `str` 字符串中。
- 返回读取的字符数。
- `str` 中的字符串不会自动以空字符结尾。
- 调用者必须确保 `str` 有足够的空间来存储 `count` 个字符。
- 与 `read()` 函数不同,`readsome()` 函数使用缓冲区的 `in_avail()` 成员函数读取流缓冲区中所有可用的字符。当不希望等待输入(例如输入来自键盘或其他进程)时,这很有用。遇到文件结束符不被视为错误,不会设置 `eofbit` 或 `failbit`。
- `streamsize istream::gcount () const`:
- 返回上一次未格式化读取操作读取的字符数。
- `istream& istream::ignore ()`、`istream& istream::ignore (streamsize count)` 和 `istream& istream::ignore (streamsize count, int delim)`:
- 所有形式都会提取并丢弃字符。
- 第一种形式忽略一个字符。
- 第二种形式最多忽略 `count` 个字符。
- 第三种形式最多忽略 `count` 个字符,直到提取并丢弃 `delim` 字符。
- 如果 `count` 是 `std::numeric_limits<std::streamsize>::max()`(`std::streamsize` 类型的最大值),则会丢弃所有字符,直到遇到 `delim` 或文件结束符。
- 所有形式都返回流对象。
- 示例:
- `cin.ignore(numeric_limits<std::streamsize>::max(),'\n');` 调用会丢弃该行的其余部分。
- `cin.ignore(numeric_limits<std::streamsize>::max());` 调用会丢弃 `cin` 的全部剩余内容。
- `int istream::peek ()`:
- 返回流中即将读取的下一个字符,但不提取该字符,下一次读取仍会读取该字符(除非读取位置被修改)。
- 如果没有更多字符可供读取,则返回 `EOF`,`EOF` 是 `traits::eof()` 返回的值,对于 `istream` 是常量 `EOF`。
- `istream& istream::unget ()` 和 `istream& istream::putback (char c)`:
- 这两个函数都会将最后读取的字符放回流中,以便下一次读取时再次读取该字符(除非读取位置被修改)。
- `unget()` 和 `putback()` 的区别在于,`putback()` 会检查传入的字符 `c` 是否确实是最后读取的字符
0
0
复制全文
相关推荐









