在 C++ 中,输入输出(I/O)库提供了流(stream)的状态管理功能。每个流对象(如 cin, cout, ifstream, ofstream 等)都有一个与之相关的状态,标志着当前流的操作是否成功。流的状态主要通过流的条件标志(flags)来表示。这些标志通常用于检查流是否处于有效的状态,以便在进行输入输出操作时处理异常或错误。

流的条件状态(Flags)

流的条件状态通过 ios 类中的几个成员标志进行管理,这些标志包括:

  1. **good()**:流是否处于正常状态,即没有发生任何错误。
  2. **eof()**:流是否已经到达文件末尾。
  3. **fail()**:流是否遇到输入/输出错误。
  4. **bad()**:流是否发生严重错误,导致无法继续读取或写入。

这些状态标志可以通过流对象的方法访问,通常用于判断流的状态。

流的状态检查

1. good()

  • good() 返回 true 如果流没有遇到任何错误,输入输出操作可以继续进行。它相当于检查流的状态是否为 ios::goodbit

    1
    2
    3
    if (cin.good()) {
    cout << "输入流状态正常。" << endl;
    }

2. eof()

  • eof() 检查流是否已经到达文件末尾或输入结束标志。对于从文件读取或从输入流读取数据时,可以使用该标志判断是否已读取完所有数据。

    1
    2
    3
    if (cin.eof()) {
    cout << "已到达输入的末尾。" << endl;
    }

3. fail()

  • fail() 检查流是否发生了格式错误或输入输出错误。如果输入的数据类型不匹配或文件无法打开等操作失败时,会返回 true

    1
    2
    3
    if (cin.fail()) {
    cout << "输入数据失败,数据格式错误。" << endl;
    }

4. bad()

  • bad() 返回 true,如果流处于严重错误状态,通常在硬件故障或流被意外关闭时会发生。这是最严重的错误状态。

    1
    2
    3
    if (cin.bad()) {
    cout << "发生了严重错误,流无法继续使用。" << endl;
    }

常见的流状态标志

  • **ios::goodbit**:正常状态,表示流没有错误。
  • **ios::eofbit**:表示流已到达文件末尾或输入结束。
  • **ios::failbit**:表示流遇到非致命错误,通常是格式错误或读取错误。
  • **ios::badbit**:表示流遇到致命错误,通常是硬件故障或无法继续操作。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <fstream>
using namespace std;

int main() {
// 示例 1: 标准输入流 (cin)
int num;
cout << "请输入一个整数:";
cin >> num;

// 检查输入是否成功
if (cin.fail()) {
cout << "输入失败,格式错误!" << endl;
} else {
cout << "你输入的整数是: " << num << endl;
}

// 示例 2: 文件输入流 (ifstream)
ifstream file("example.txt");

if (!file) {
cout << "文件打开失败!" << endl;
return 1;
}

string line;
while (getline(file, line)) {
cout << line << endl;
}

// 检查文件是否读取到末尾
if (file.eof()) {
cout << "已到达文件末尾。" << endl;
}

// 示例 3: 检查文件流是否出现严重错误
if (file.bad()) {
cout << "文件流出现严重错误!" << endl;
}

file.close();
return 0;
}

总结

  • good() 用于检查流是否没有任何错误。
  • eof() 用于检查是否已到达输入流的末尾。
  • fail() 用于检查流是否发生了可恢复的错误(如输入数据不匹配)。
  • bad() 用于检查流是否发生了致命错误。

通过检查这些状态标志,你可以更加精确地控制和管理程序中的输入输出操作,及时捕获和处理异常。

string流

在 C++ 中,string 流(stringstream)是用于处理字符串输入和输出的流类,它包含在 <sstream> 头文件中。stringstream 可以被用来从字符串中提取数据,或者将数据格式化并输出到字符串中。它是 iostream 库的扩展,结合了输入流(istringstream)、输出流(ostringstream)和读写流(stringstream)。

使用 stringstream(stringstream即可代替istringstream与ostringstream)

  1. 创建和初始化:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <iostream>
    #include <sstream>
    using namespace std;

    int main() {
    stringstream ss; // 创建一个空的 stringstream 对象

    // 使用 << 操作符向 stringstream 中写入数据
    ss << "Hello " << 123 << " world!";

    // 输出 stringstream 中的内容
    cout << "Stringstream content: " << ss.str() << endl;
    return 0;
    }

    这里,我们创建了一个空的 stringstream 对象 ss,并通过 << 操作符向其中写入数据。通过 ss.str() 可以获取当前 stringstream 中的字符串。

  2. 从字符串中提取数据:
    使用 istringstream 来从字符串中读取数据,类似于从文件或标准输入中读取数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #include <iostream>
    #include <sstream>
    using namespace std;

    int main() {
    string str = "123 45.67 Hello";
    istringstream iss(str); // 创建一个从字符串读取数据的 istringstream

    int i;
    double d;
    string s;

    // 从 stringstream 中提取数据
    iss >> i >> d >> s;

    cout << "Integer: " << i << endl;
    cout << "Double: " << d << endl;
    cout << "String: " << s << endl;

    return 0;
    }

    通过 iss >> i >> d >> s;,我们从字符串 str 中依次提取数据,将其赋值给变量 i(整数)、d(浮动数)和 s(字符串)。

  3. 向字符串写入数据:
    使用 ostringstream 可以将数据写入到一个字符串中。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>
    #include <sstream>
    using namespace std;

    int main() {
    ostringstream oss; // 创建一个输出流对象
    int age = 30;
    string name = "John";

    // 向 stringstream 写入数据
    oss << "Name: " << name << ", Age: " << age;

    // 获取存储在 stringstream 中的字符串
    string result = oss.str();
    cout << result << endl;

    return 0;
    }

    在此示例中,我们使用 ostringstream 将变量 nameage 写入字符串流 oss 中,然后通过 oss.str() 获取最终的字符串。

小结

  • **istringstream**:从字符串中读取数据。
  • **ostringstream**:将数据写入字符串。
  • **stringstream**:既能从字符串读取数据,也能将数据写入字符串。

这种流的使用场景很多,常用于处理复杂的字符串格式转换、提取和拼接。