Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > istringstream question

Reply
Thread Tools

istringstream question

 
 
Luther Baker
Guest
Posts: n/a
 
      05-22-2004
Hi,

My question is regarding std::istringstream. I am serializing data to
an ostringstream and the resulting buffer turns out just fine.

But, when I try the reverse, when the istringstream encounters the two
byte shorts, it either thinks it has reached the null terminator? or
eof and consequently stops reading values back in. It doesn't matter
whether or not I use the std::ios::binary flag when opening the
istringstream or the readsome method which does in-fact, not report
eof. It still can't build the shorts back up.

Any suggestions would be appreciated. Here is a brief example:


#include <cstring>
#include <sstream>

int
main(int argc, char** argv)
{
typedef unsigned short uint;

char* key = new char[8];
strncpy (key, "the key", 7)[7] = '\0';
uint var1 = 'a';
uint var2 = 'b';

std:stringstream os;
os.write(key, ;
os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
std::cout << "stream string: " << os.str() << std::endl;
std::cout << "stream c_str: " << os.str().c_str() << std::endl;

char* keytwo = new char[8];
keytwo[7] = 0;
uint feedme1 = 0;
uint feedme2 = 0;

//
// Here is where my question lies - how to initialize istringstream?
//
std::istringstream is (os.str().c_str(), std::ios::binary);
is.read(keytwo, ;
std::cout << "\n\nkeytwo: " << keytwo << std::endl;
if (is.eof())
{
std::cout << "END OF FILE!!!" << std::endl;
}

is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
std::cout << "feedme1: " << feedme1 << std::endl;

is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
std::cout << "feedme2: " << feedme2 << std::endl;

//
// but it is clear the both shorts are present in the c_str
//
for (int i = 0; i < 12; ++i)
{
std::cout << os.str().c_str()[i] << std::endl;
}

//
// and my favorite way to see what's happening
//
for (int i = 0; i < 12; ++i)
{
std::cout << (int)os.str().c_str()[i] << std::endl;
}

delete [] key;
delete [] keytwo;

return 0;
}



Thanks,

-Luther
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      05-22-2004
"Luther Baker" <(E-Mail Removed)> wrote...
> My question is regarding std::istringstream. I am serializing data to
> an ostringstream and the resulting buffer turns out just fine.
>
> But, when I try the reverse, when the istringstream encounters the two
> byte shorts, it either thinks it has reached the null terminator? or
> eof and consequently stops reading values back in. It doesn't matter
> whether or not I use the std::ios::binary flag when opening the
> istringstream or the readsome method which does in-fact, not report
> eof. It still can't build the shorts back up.
>
> Any suggestions would be appreciated. Here is a brief example:
>
>
> #include <cstring>
> #include <sstream>
>
> int
> main(int argc, char** argv)
> {
> typedef unsigned short uint;
>
> char* key = new char[8];
> strncpy (key, "the key", 7)[7] = '\0';
> uint var1 = 'a';
> uint var2 = 'b';
>
> std:stringstream os;
> os.write(key, ;
> os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> std::cout << "stream string: " << os.str() << std::endl;
> std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>
> char* keytwo = new char[8];
> keytwo[7] = 0;
> uint feedme1 = 0;
> uint feedme2 = 0;
>
> //
> // Here is where my question lies - how to initialize istringstream?
> //
> std::istringstream is (os.str().c_str(), std::ios::binary);


As soon as you use .c_str() here, you lose everything after the first
zero character, which becomes the terminator. You need to use the
string directly:

std::istringstream is(os.str(), std::ios::binary);

HTH

> is.read(keytwo, ;
> std::cout << "\n\nkeytwo: " << keytwo << std::endl;
> if (is.eof())
> {
> std::cout << "END OF FILE!!!" << std::endl;
> }
>
> is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
> std::cout << "feedme1: " << feedme1 << std::endl;
>
> is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
> std::cout << "feedme2: " << feedme2 << std::endl;
>
> //
> // but it is clear the both shorts are present in the c_str
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << os.str().c_str()[i] << std::endl;
> }
>
> //
> // and my favorite way to see what's happening
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << (int)os.str().c_str()[i] << std::endl;
> }
>
> delete [] key;
> delete [] keytwo;
>
> return 0;
> }
>
>
>
> Thanks,
>
> -Luther



 
Reply With Quote
 
 
 
 
Luther Baker
Guest
Posts: n/a
 
      05-22-2004
Victor Bazarov wrote:

> "Luther Baker" <(E-Mail Removed)> wrote...
>
>>My question is regarding std::istringstream. I am serializing data to
>>an ostringstream and the resulting buffer turns out just fine.

....
>>std:stringstream os;
>>os.write(key, ;
>>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
>>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
>>std::cout << "stream string: " << os.str() << std::endl;
>>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>>
>>char* keytwo = new char[8];
>>keytwo[7] = 0;
>>uint feedme1 = 0;
>>uint feedme2 = 0;
>>
>> //
>> // Here is where my question lies - how to initialize istringstream?
>> //
>>std::istringstream is (os.str().c_str(), std::ios::binary);

>
>
> As soon as you use .c_str() here, you lose everything after the first
> zero character, which becomes the terminator. You need to use the
> string directly:
>
> std::istringstream is(os.str(), std::ios::binary);


Ah.

So - for my real project, I have the following:

void AnObject:eSerialize(const void* buffer)
{
std::istringstream ( ? ... );
....
}

Following your lead, I'll try to create a string.

std::string str(reinterpret_cast<const char*>(buffer));

Nope. Loses the tail end ... (NULL terminated)

const int size = X;
std::string str(size, size)
for (int i = 1; i < size; ++i)
{
str[i] = buffer[i];
}

Ah ... that works! And I do, in fact, know exactly how many bytes I need
to copy.

Would you suggest a smoother way or different approach now that you see
a bit more of what I'm after?

Thanks,

-Luther
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      05-22-2004
"Luther Baker" <(E-Mail Removed)> wrote...
> Victor Bazarov wrote:
>
> > "Luther Baker" <(E-Mail Removed)> wrote...
> >
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.

> ...
> >>std:stringstream os;
> >>os.write(key, ;
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize

istringstream?
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);

> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);

>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject:eSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }


Don't you mean

std::string str(buffer, size);

?

>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?


I am not sure what way would be "smoother". If you need to have meaningful
zeroes in the "buffer", then you cannot hope to call deserialise without
passing the size of the stream in, btw.

void AnObject:eserialize(const char *buffer)
{
std::istringstream is(std::string(buffer, size), ios::binary);
// now read from it
}

Victor


 
Reply With Quote
 
Mike Wahler
Guest
Posts: n/a
 
      05-22-2004

"Luther Baker" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Victor Bazarov wrote:
>
> > "Luther Baker" <(E-Mail Removed)> wrote...
> >
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.

> ...
> >>std:stringstream os;
> >>os.write(key, ;
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize

istringstream?
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);

> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);

>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject:eSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }
>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?


const char *p = static_cast<const char *>buffer;
std::string str(p, p + X);

-Mike


 
Reply With Quote
 
Luther Baker
Guest
Posts: n/a
 
      05-22-2004
Victor Bazarov wrote:
> "Luther Baker" <(E-Mail Removed)> wrote...
>

....
>> const int size = X;
>> std::string str(size, size)
>> for (int i = 1; i < size; ++i)
>> {
>> str[i] = buffer[i];
>> }

>
>
> Don't you mean
>
> std::string str(buffer, size);

....
>
> I am not sure what way would be "smoother". If you need to have meaningful
> zeroes in the "buffer", then you cannot hope to call deserialise without
> passing the size of the stream in, btw.
>
> void AnObject:eserialize(const char *buffer)
> {
> std::istringstream is(std::string(buffer, size), ios::binary);
> // now read from it
> }
>


For some reason, I thought that *std::string str(buffer, size);* would
have strncpy semantics and stop copying buffer at the first null. But as
I'm sure you're aware, it doesn't.

When I said "smoother" I guess I meant more elegant. It seems clunky to
have to create a std::string to get a std::istringstream interface over
the buffer - but I guess it is a *string* stream.

Many Thanks,

-Luther
 
Reply With Quote
 
Luther Baker
Guest
Posts: n/a
 
      05-22-2004
Mike Wahler wrote:

> "Luther Baker" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...

....
>>
>>Would you suggest a smoother way or different approach now that you see
>>a bit more of what I'm after?

>
>
> const char *p = static_cast<const char *>buffer;
> std::string str(p, p + X);


Does that imply

string::string (const char* cstrBegin, const char* cstrEnd);

Josuttis pg.509 left that one out! unless that is silently turned into

string::string (InputIterator beg, InputIterator end);

Thanks for your insight,

-Luther



 
Reply With Quote
 
John Harrison
Guest
Posts: n/a
 
      05-22-2004
>
> When I said "smoother" I guess I meant more elegant. It seems clunky to
> have to create a std::string to get a std::istringstream interface over
> the buffer - but I guess it is a *string* stream.
>


Use an istrstream instead. Reading from a fixed size buffer is about the
only reasonable use of strstream.

john


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
istringstream Conversion Question Mike Copeland C++ 5 08-01-2010 09:57 PM
istringstream class question Randy Yates C++ 8 01-03-2005 08:30 PM
A question about istringstream JustSomeGuy C++ 6 11-25-2004 12:20 AM
istringstream syntax error question Donald Canton C++ 1 01-30-2004 02:16 AM
istringstream question Viet Le Hong C++ 3 09-18-2003 03:34 PM



Advertisments