【问题标题】:Stringstream is not feeding into a string that has a endline character added to itStringstream 没有输入添加了结束行字符的字符串
【发布时间】:2025-12-03 16:50:02
【问题描述】:

我基本上是在尝试将整数添加到字符串中,然后在特定时间将结束符添加到字符串中,然后继续添加整数。我希望将其全部添加到一个字符串对象中。

所以我向 stringstream 添加了一个 int,将 stringstream 馈送到一个字符串。然后将'\n'添加到字符串中。

然后我在 stringstream 中添加了另一个 int,并再次将它提供给字符串。

不幸的是,来自 stringstream 对象的第二个对象没有被添加到字符串中,我不确定为什么它不能。

我尝试将两个对象添加到我的字符串流对象,然后一次将它们提供给字符串(中间有结束符),但是 stringstream 将字符串中的所有内容一次添加到字符串中,这样就不会不行。

int main(){
    string h;
    stringstream ss;

    ss << 1;
    ss >> h;
    h += '\n';
    ss << 2;
    ss >> h;
    h += '\n';
    cout << h << "endline";
    cout << endl;

    return 0;
}

当然没有错误消息。我希望它输出:

1
2
endline

我得到了

1

endline

很明显,字符串添加了我的两个结束行字符,但不是我添加到字符串流中的 2。

【问题讨论】:

  • 始终测试 IO 是否成功。总是。旁注:ss &gt;&gt; h; 如果成功,将覆盖h 中已有的所有内容。如果不成功,您可能不应该使用h
  • 谢谢!我不知道它会覆盖字符串中的所有内容。我最终做的是ss &gt;&gt; tempString,然后是h+= tempString,然后是ss = stringstream()。然后根据需要重复。
  • @r8__。您可以在每个 &gt;&gt; 之后使用 ss.str(""); ss.clear(); 重置字符串流,然后您将重用现有的字符串流而不创建新的。
  • 明白了。谢谢!
  • @r8__。您可以使用std::to_string() 代替std::stringstream,例如:string h; h += to_string(1); h += '\n'; h += to_string(2); h += '\n'; 或者,对所有输出使用std::ostringstream,然后在完成后将其保存到std::string,例如:ostringstream oss; oss &lt;&lt; 1; oss &lt;&lt; '\n'; oss &lt;&lt; 2; oss &lt;&lt; '\n'; string h = oss.str();

标签: c++ stringstream


【解决方案1】:

为了演示发生了什么,我们需要检查各种流状态位。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
    string h;
    stringstream ss;

    if (ss << 1)
    {
        cout << "1 success. Fail " << ss.fail() 
             << " eof " << ss.eof() << " bad " << ss.bad() << endl;
        if (ss >> h)
        {
            cout << "2 success. Fail " << ss.fail() 
                 << " eof " << ss.eof() << " bad " << ss.bad() << endl;
            h += '\n';
            if (ss << 2)
            {
                cout << "3 success. Fail " << ss.fail() 
                     << " eof " << ss.eof() << " bad " << ss.bad() << endl;
                if (ss >> h)
                {
                    cout << "4 success. Fail " << ss.fail() 
                         << " eof " << ss.eof() << " bad " << ss.bad() << endl;
                    h += '\n';
                    cout << h << "endline";
                    cout << endl;
                }
                else
                {
                    cout << "4 Fail " << ss.fail() << " eof " << ss.eof() 
                         << " bad " << ss.bad() << endl;
                }
            }
            else
            {
                cout << "3 Fail " << ss.fail() << " eof " << ss.eof() 
                     << " bad " << ss.bad() << endl;
            }
        }
        else
        {
            cout << "2 Fail " << ss.fail() << " eof " << ss.eof() 
                 << " bad " << ss.bad() << endl;
        }
    }
    else
    {
        cout << "1 Fail " << ss.fail() << " eof " << ss.eof() 
             << " bad " << ss.bad() << endl;
    }
    return 0;
}

输出

1成功。失败 0 eof 0 坏 0 2成功。失败 0 eof 1 坏 0 3 失败 1 eof 1 坏 0

所以第一次写入成功。无懈可击的胜利。但是第一次读取读取流中的所有内容并到达文件末尾(不是流是文件,而是名称卡住了),设置了 EOF 位。一旦设置了 EOF 位,除了清除该位并祈祷有人添加更多要读取的数据之外,您对流无能为力。

更多数据被添加到流中,但由于 EOF 位,文件无法接受它。

如果我们清除 EOF

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
    string h;
    stringstream ss;

    if (ss << 1)
    {
        cout << "1 success. Fail " << ss.fail() << " eof " << ss.eof() 
             << " bad " << ss.bad() << endl;
        if (ss >> h)
        {
            cout << "2 success. Fail " << ss.fail() << " eof " << ss.eof() 
                 << " bad " << ss.bad() << endl;
            h += '\n';
            ss.clear(); // added this
            if (ss << 2)
            {
                cout << "3 success. Fail " << ss.fail() << " eof " << ss.eof() 
                     << " bad " << ss.bad() << endl;
                if (ss >> h)
                {
                    cout << "4 success. Fail " << ss.fail() << " eof " << ss.eof() 
                         << " bad " << ss.bad() << endl;
                    h += '\n';
                    cout << h << "endline";
                    cout << endl;
                }
                else
                {
                    cout << "4 Fail " << ss.fail() << " eof " << ss.eof() 
                         << " bad " << ss.bad() << endl;
                }
            }
            else
            {
                cout << "3 Fail " << ss.fail() << " eof " << ss.eof() 
                     << " bad " << ss.bad() << endl;
            }
        }
        else
        {
            cout << "2 Fail " << ss.fail() << " eof " << ss.eof() 
                 << " bad " << ss.bad() << endl;
        }
    }
    else
    {
        cout << "1 Fail " << ss.fail() << " eof " << ss.eof() 
             << " bad " << ss.bad() << endl;
    }
    return 0;
}

现在是输出

1成功。失败 0 eof 0 坏 0 2成功。失败 0 eof 1 坏 0 3成功。失败 0 eof 0 坏 0 4成功。失败 0 eof 1 坏 0 2 端线

如果我们忽略我添加的所有状态信息,我们真的得到了

2 端线

不是你想要的

1 2 端线

因为ss &gt;&gt; h 将覆盖h 中已经存在的所有内容。 “1\n”被“2”抹去

获得所需内容的最简单方法是将所有内容写入其中,然后以string 的形式获取内容。

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main()
{
    string h;
    stringstream ss;

    if (ss << 1 << '\n' << 2 << '\n')
    {
        cout << ss.str() << "endline";
        cout << endl;
    }
    else
    {
        cout << "Fail " << ss.fail() << " eof " << ss.eof()
             << " bad " << ss.bad() << endl;
    }
    return 0;
}

这次的输出是

1 2 端线

【讨论】:

  • 感谢您的全面回答。我不认为将'\n' 字符包含在字符串流中。仅仅由于我项目的性质,ss.clear() 最终成为了我的救命稻草,而不是用我正在制作的很长的字符串来喂字符串流。感谢您解释 eof() 字符。这确实帮助我更好地理解了字符串流。
  • @r8__。附注:给Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?。它与您当前的问题无关,但它是迄今为止最常见的流读取错误,因为它看起来很合乎逻辑,直到您将其分开。如果您提前知道陷阱,它可能会为您节省一些未来的调试。
【解决方案2】:

使用stringstream 构建您想要的输出,然后提取字符串。

ss << 1 << '\n';
ss << 2 << '\n';
h = ss.str();

【讨论】: