To demonstrate what happened we need to inspect the various stream status bits.
#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;
}
Output
1 success. Fail 0 eof 0 bad 0
2 success. Fail 0 eof 1 bad 0
3 Fail 1 eof 1 bad 0
So the first write succeeded. Flawless victory. But the first read read everything in the stream and hit the end of file (not that the stream is a file, but the name stuck), setting the EOF bit. Once the EOF bit is set, there isn't much you can do with a stream other than clear the bit and pray someone adds more data to be read.
More data was added to the stream, but the file could not accept it because of the EOF bit.
If we clear the 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;
}
the output is now
1 success. Fail 0 eof 0 bad 0
2 success. Fail 0 eof 1 bad 0
3 success. Fail 0 eof 0 bad 0
4 success. Fail 0 eof 1 bad 0
2
endline
If we ignore all the status information I added we really got
2
endline
not the desired
1
2
endline
because ss >> h
will overwrite everything already in h
. The "1\n" is wiped out by the "2"
The easiest way to get what you want is to write everything in and then get the contents as a 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;
}
This time the output is
1
2
endline