Click to See Complete Forum and Search --> : stringstream question


pimeson
September 1st, 2004, 11:59 AM
Hello,

I am trying to do the following: write some stuff to a stringstream, output the stringstream to a string, write the string and some stuff into another stringstream; later get the string out of the second stringstream, and resurrect the original stringstream and its content from the string. Here is the example code:


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

int main(int argc, char *argv[]){

int t = 1;
int z;
stringstream stream1;
stringstream stream2;
stringstream stream3;
int size;
string tmp;
char * in;

// write int to first stream
stream1.write(reinterpret_cast<char *>(&t), sizeof(t));
// output stream into string
stream1 >> tmp;
// then string into next stream
size = tmp.size();
stream2.write(reinterpret_cast<char *>(&size), sizeof(size));
stream2.write(tmp.c_str(), size+1);

// get everything out
in = new char[size+1];
stream2.read(reinterpret_cast<char *>(&size), sizeof(size));
stream2.read(in, size+1);
tmp = in;

// and resurect the original stream
stream3 << tmp;
stream3.read(reinterpret_cast<char *>(&z), sizeof(z));

cout << z << "\n";

return 1;
}


The code should output 1 but it outputs -1073745663 so I suppose I've got an over/underflow somewhere or messed up with the number of bytes read. I tried putting just the first stream into a string and resurecting it from there, that worked without problems, so I thought wrapping stringstreams in stringstreams should work too? Any hints?

Thx,
PiMeson

HighCommander4
September 1st, 2004, 12:57 PM
Your problem is that you're mixing binary i/o operations with text (formatted) i/o operations.

Let me go through logically the sequence of operations you're doing so you can see what's wrong:

First, you use the stringstream::write() function, a binary output function to write the int value 1 to the stream1

object. Assuming your system uses a 4-byte int, your stream1 object will now hold the following byte values (in

hex):
00 00 00 01 (the binary representation of the integer value 1).
In ASCII, this is equivalenbt to 3 null character and another non-printable character.
Now you input, using the string::operator>>() method, a FORMATTED input function, the contents of stream1 into

the std::string object tmp. Tmp being a string object, the input operation halts when it encounters a null character,

in this case the first character in stream1. So you end up with tmp being an empty string.

Presently you assign the size of tmp (0) to the integer "size." You now write, using the binary write() method, the

integer value 0 to stream2. Stream2 now holds the following byte values:
00 00 00 00 (the binary representation of the integer value 1).
Your next statement
stream2.write(tmp.c_str(), size+1);
attempts to write the non-existent first character of the tmp string into the stream2 object. Tmp being empty, the

next character written to stream2 will be whatever happened to be at the memory location adjacent to where the

pointer tmp.c_str() points, which can be anything.
So now the stream2 object holds the following bytes:
00 00 00 00 XX (where XX is a random hex combination that could be anything).

Now you request a block of memory for 1 char (size + 1) = 1, and assign in to the pointer-to-char "in".
Then you read a 4-byte int value from the stringstream object stream2 ito the integer size. The binary read()

method reads the first 4 bhytes of stream2 (00 00 00 00) and assigns the integer value that this 4-byte cobination

represents to size. Size will now hold the integer value 0.
Presently, you use the binary read() fuction again, to read size + 1 characters (that is, 1 character) from stream2

and assign it to "in". Teh function reads the byte XX and assigns it to in[0]. So in[0] now holds a random character.
Then you assign in to tmp, so tmp will now hold the randomc character as well.

Finally you use the formatted operator<<() output function to output the tmp string into the stringstream object

"stream3". Stream 3 will now hold one random character.

Then you attempt to read 4-byte integer value from the stream3 object, which only holds 1 byte, even that

reprsenting a random character. Quite obviously the result of the read() operation will be jibberish.

I'm sorry if this was all poorly explained, but I hope you got the point that it does not do well to mix binary functions

like write() and read() with formatted ones like operator<<() and operator>>().

pimeson
September 1st, 2004, 03:08 PM
Thanks a lot for the explanations, that made the error very clear. I didn't realise mixing >> and write/read operator wasn't a good idea, as I'm still very new to this C++ stuff.

Also, can you confirm if the way I'm using the stringstream operations (with reinterpret_cast) is correct? I found it in some tutorial, and copied the syntax (and think I've understood what it does), but since I've read that using reinterpret_cast is a good way to shoot oneself in the foot, I'm unsure if there might be a better / nicer way to use it this way.

PiMeson