istringstream question

Discussion in 'C++' started by Luther Baker, May 22, 2004.

  1. Luther Baker

    Luther Baker Guest

    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::eek:stringstream os;
    os.write(key, 8);
    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, 8);
    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() << 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() << std::endl;
    }

    delete [] key;
    delete [] keytwo;

    return 0;
    }



    Thanks,

    -Luther
     
    Luther Baker, May 22, 2004
    #1
    1. Advertising

  2. "Luther Baker" <> 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::eek:stringstream os;
    > os.write(key, 8);
    > 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, 8);
    > 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() << 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() << std::endl;
    > }
    >
    > delete [] key;
    > delete [] keytwo;
    >
    > return 0;
    > }
    >
    >
    >
    > Thanks,
    >
    > -Luther
     
    Victor Bazarov, May 22, 2004
    #2
    1. Advertising

  3. Luther Baker

    Luther Baker Guest

    Victor Bazarov wrote:

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

    ....
    >>std::eek:stringstream os;
    >>os.write(key, 8);
    >>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::DeSerialize(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 = buffer;
    }

    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
     
    Luther Baker, May 22, 2004
    #3
  4. "Luther Baker" <> wrote...
    > Victor Bazarov wrote:
    >
    > > "Luther Baker" <> wrote...
    > >
    > >>My question is regarding std::istringstream. I am serializing data to
    > >>an ostringstream and the resulting buffer turns out just fine.

    > ...
    > >>std::eek:stringstream os;
    > >>os.write(key, 8);
    > >>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::DeSerialize(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 = buffer;
    > }


    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::Deserialize(const char *buffer)
    {
    std::istringstream is(std::string(buffer, size), ios::binary);
    // now read from it
    }

    Victor
     
    Victor Bazarov, May 22, 2004
    #4
  5. Luther Baker

    Mike Wahler Guest

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

    > ...
    > >>std::eek:stringstream os;
    > >>os.write(key, 8);
    > >>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::DeSerialize(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 = buffer;
    > }
    >
    > 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
     
    Mike Wahler, May 22, 2004
    #5
  6. Luther Baker

    Luther Baker Guest

    Victor Bazarov wrote:
    > "Luther Baker" <> wrote...
    >

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

    >
    >
    > 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::Deserialize(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
     
    Luther Baker, May 22, 2004
    #6
  7. Luther Baker

    Luther Baker Guest

    Mike Wahler wrote:

    > "Luther Baker" <> wrote in message
    > news:...

    ....
    >>
    >>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
     
    Luther Baker, May 22, 2004
    #7
  8. >
    > 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
     
    John Harrison, May 22, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Viet Le Hong

    istringstream question

    Viet Le Hong, Sep 18, 2003, in forum: C++
    Replies:
    3
    Views:
    675
    Buster Copley
    Sep 18, 2003
  2. Donald Canton

    istringstream syntax error question

    Donald Canton, Jan 29, 2004, in forum: C++
    Replies:
    1
    Views:
    409
    David Harmon
    Jan 30, 2004
  3. JustSomeGuy

    A question about istringstream

    JustSomeGuy, Nov 24, 2004, in forum: C++
    Replies:
    6
    Views:
    411
    =?iso-8859-1?Q?Ali_=C7ehreli?=
    Nov 25, 2004
  4. Randy Yates

    istringstream class question

    Randy Yates, Jan 2, 2005, in forum: C++
    Replies:
    8
    Views:
    516
    Jonathan Turkanis
    Jan 3, 2005
  5. Mike Copeland

    istringstream Conversion Question

    Mike Copeland, Jul 31, 2010, in forum: C++
    Replies:
    5
    Views:
    495
    Ian Collins
    Aug 1, 2010
Loading...

Share This Page