Topic: stream_cast (was : why stringstream?)


Author: Alex Vinokur <alexvn@bigfoot.com>
Date: 10 May 2001 22:42:59 -0400
Raw View
Dietmar Kuehl wrote:

> Hi,
> James Kanze (James.Kanze@dresdner-bank.com) wrote:
> : > Thus, you want to keep your string stream around and use
> : > it for formatting this like this in "normal" programs.
>
> : Are you sure?  Making sure that the string steam object is in its
> : "initial" state isn't necessarily trival or cheap either.  For that
> : matter, how DO you ensure the initial state of extended flags
> : allocated with xalloc?
>
>   template <typename T, typename S>
>   T stream_cast(S const& obj) {
>     static std::stringstream stream;
>     stream << obj;
>     T rc;
>     if (stream >> rc)
>       return rc;
>     else
>     {
>       stream.clear();
>       throw "some error indication...";
>     }
>   }

[snip]


Hi,

Here is a similar stream_cast function using strstream.

==============================
%uname -sr
Linux 2.2.17-21mdk

%g++ -v
gcc version 2.95.3 19991030 (prerelease)
==============================

---------- C++ code : BEGIN --------------
#include <strstream>

template <typename From, typename To>
bool stream_cast(From const& from, To& to)
{
strstream       tmp_stream;
bool            ret_bool;

        tmp_stream << from;
        ret_bool = (tmp_stream >> to);
        tmp_stream.rdbuf()->freeze (0);
        return ret_bool;
}

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

        for (int i = 1; i < argc; i++)
        {
                cout << "[" << i  << "] : " << argv[i] << " ---> ";
                if (stream_cast(argv[i], result))
                {
                        cout << result << endl;
                }
                else
                {
                        cout << "Cannot convert between types" << endl;
                }
        }
        return 0;
}

---------- C++ code : END ----------------

---------- Running : BEGIN ----------------
%a.out "123" "4xy" "x5y" "6 78"
[1] : 123 ---> 123
[2] : 4xy ---> 4
[3] : x5y ---> Cannot convert between types
[4] : 6 78 ---> 6
---------- Running : END ------------------

We can see that stream_cast accepts argv[2] and argv[4] as 'int'.
However these strings ("4xy" and "6 78") are not of int type.
What is wrong?
    ----------------------------
    return (tmp_stream >> to);      // ???
    ----------------------------
    (via ret_bool).


==================================
Alex Vinokur
   mailto:alexvn@bigfoot.com
   http://up.to/alexvn
   http://visitweb.com/alexvn.math
==================================
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 12 May 01 04:38:17 GMT
Raw View
Alex Vinokur wrote:
...
> %a.out "123" "4xy" "x5y" "6 78"
> [1] : 123 ---> 123
> [2] : 4xy ---> 4
> [3] : x5y ---> Cannot convert between types
> [4] : 6 78 ---> 6
> ---------- Running : END ------------------
>
> We can see that stream_cast accepts argv[2] and argv[4] as 'int'.
> However these strings ("4xy" and "6 78") are not of int type.
> What is wrong?

It stops reading those strings as soon as it's identified a complete
number. If you want to make sure that the entire input string has been
consumed in the process of carrying out the conversion, you'll need to
test whether stream.rdbuf().in_avail()==0 in your streamcast constuctor.

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]




Author: Christopher Eltschka <celtschk@dollywood.itp.tuwien.ac.at>
Date: 12 May 01 04:45:04 GMT
Raw View
Alex Vinokur wrote:
>
> Dietmar Kuehl wrote:
>
> > Hi,
> > James Kanze (James.Kanze@dresdner-bank.com) wrote:
> > : > Thus, you want to keep your string stream around and use
> > : > it for formatting this like this in "normal" programs.
> >
> > : Are you sure?  Making sure that the string steam object is in its
> > : "initial" state isn't necessarily trival or cheap either.  For that
> > : matter, how DO you ensure the initial state of extended flags
> > : allocated with xalloc?
> >
> >   template <typename T, typename S>
> >   T stream_cast(S const& obj) {
> >     static std::stringstream stream;
> >     stream << obj;
> >     T rc;
> >     if (stream >> rc)
> >       return rc;
> >     else
> >     {
> >       stream.clear();
> >       throw "some error indication...";
> >     }
> >   }
>
> [snip]
>
> Hi,
>
> Here is a similar stream_cast function using strstream.
>
> ==============================
> %uname -sr
> Linux 2.2.17-21mdk
>
> %g++ -v
> gcc version 2.95.3 19991030 (prerelease)
> ==============================
>
> ---------- C++ code : BEGIN --------------
> #include <strstream>
>
> template <typename From, typename To>
> bool stream_cast(From const& from, To& to)
> {
> strstream       tmp_stream;
> bool            ret_bool;
>
>         tmp_stream << from;
>         ret_bool = (tmp_stream >> to);
>         tmp_stream.rdbuf()->freeze (0);
>         return ret_bool;
> }
>
> int main (int argc, char* argv[])
> {
> int     result;
>
>         for (int i = 1; i < argc; i++)
>         {
>                 cout << "[" << i  << "] : " << argv[i] << " ---> ";
>                 if (stream_cast(argv[i], result))
>                 {
>                         cout << result << endl;
>                 }
>                 else
>                 {
>                         cout << "Cannot convert between types" << endl;
>                 }
>         }
>         return 0;
> }
>
> ---------- C++ code : END ----------------
>
> ---------- Running : BEGIN ----------------
> %a.out "123" "4xy" "x5y" "6 78"
> [1] : 123 ---> 123
> [2] : 4xy ---> 4
> [3] : x5y ---> Cannot convert between types
> [4] : 6 78 ---> 6
> ---------- Running : END ------------------
>
> We can see that stream_cast accepts argv[2] and argv[4] as 'int'.
> However these strings ("4xy" and "6 78") are not of int type.
> What is wrong?
>     ----------------------------
>     return (tmp_stream >> to);      // ???
>     ----------------------------
>     (via ret_bool).

Try:

      ret_bool = (tmp_stream >> to >> ws)
                 && (tmp_stream.get() == tmp.stream.traits.eof());


The second line checks that the stream was read out completely;
the ws in the first line prevents errors due to trailing
whitespace (otherwise you'd get a failed cast from "12 " to int).

BTW, shouldn't there be a tmp_stream.seekg(0) between
writing and reading?

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]