从 istringstream 读取时出现意外行为

unexpected behavior when reading from istringstream

本文关键字:意外 istringstream 读取      更新时间:2023-10-16

我对流行为有疑问,请参阅以下示例。我所期望的是,由于字符串中只有 5 个字符,当我尝试读取 10 个字符时,流读取会卡住。相反,输出是"hellooooo"...最后一个字符重复。我的问题有两个方面:第一,为什么?其次,有没有办法让流表现得好像不再重复最后一个字符?

#include <sstream>
#include <iostream>
using namespace std;
int main(void) {
    char c;
    string msg("hello");
    istringstream iss(msg);
    unsigned int i = 0;
    while (i < 10) {
        iss >> c;
        cout << c;
        i++;
    }
    cout << endl;
    return 0;
}

你看到的是阅读错误状态的流的结果。 当您读取流中的最后一个元素(这是一个字符串流)时,流变得错误,任何其他从中读取的尝试都将失败(并且提取变量保持不变)。

在进一步阅读之前,您必须检查提取操作是否成功:

if (iss >> c) {
  // succeess
} else {
  // failed to extract, handle error
}

如果您使用连接到控制台的流(例如),则对>>的调用将按预期阻止。 stringstream的行为是不同的(你不能指望包含更多的数据)

原因是当您读取到流的末尾时,之后的所有读取尝试都会失败,从而将最后一个值读取留在您的c中。

如果您最多想阅读 10 个字符:

while (i < 10 && is >> c) {
    cout << c;
    i++;
}

这是有效的,因为流可以转换为bool,并且流是否处于"良好"状态true

"最后一个字符重复"
iss >> c失败时,c保持不变。

通过直接计算此表达式来检查值提取是否成功:if (iss >> c),但甚至不要考虑调用iss.good()。检查此答案,并查看:
这种时髦的 while (std::cin>> foo) 语法是如何工作的?
为什么我的输入似乎在文件末尾处理?