Float-to-string conversion that raises exception instead of returning0.0 like atof

Discussion in 'C++' started by Trond Valen, Dec 6, 2005.

  1. Trond Valen

    Trond Valen Guest

    Hi!

    Stupid atof, it returns 0.0 when it tries to parse something like
    "fish". So I don't know whether the number was really 0 or a string that
    couldn't be parsed. Is there a better way to do this?

    Trond Valen
     
    Trond Valen, Dec 6, 2005
    #1
    1. Advertising

  2. Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Trond Valen wrote:
    > Hi!
    >
    > Stupid atof, it returns 0.0 when it tries to parse something like
    > "fish". So I don't know whether the number was really 0 or a string that
    > couldn't be parsed. Is there a better way to do this?


    # include <sstream>
    # include <string>

    class bad_float {};

    float string_to_float(const std::string &s)
    {
    std::istringstream iss(s);
    float f;
    iss >> f;

    if (!iss) throw bad_float();

    return f;
    }


    Jonathan
     
    Jonathan Mcdougall, Dec 6, 2005
    #2
    1. Advertising

  3. Trond Valen

    Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Trond Valen wrote:
    > Hi!
    >
    > Stupid atof, it returns 0.0 when it tries to parse something like
    > "fish". So I don't know whether the number was really 0 or a string that
    > couldn't be parsed. Is there a better way to do this?


    Stupid indeed. But to answer your question: yes, there is a better way.
    Use C++ stringstreams from <sstream> or use strtod (and strtol instead
    of atoi) which can distinguish between zero and an error case.

    Gavin Deane
     
    , Dec 6, 2005
    #3
  4. Trond Valen

    Trond Valen Guest

    Jonathan Mcdougall wrote:
    > Trond Valen wrote:
    >
    >>Hi!
    >>
    >>Stupid atof, it returns 0.0 when it tries to parse something like
    >>"fish". So I don't know whether the number was really 0 or a string that
    >>couldn't be parsed. Is there a better way to do this?

    >
    >
    > # include <sstream>
    > # include <string>
    >
    > class bad_float {};
    >
    > float string_to_float(const std::string &s)
    > {
    > std::istringstream iss(s);
    > float f;
    > iss >> f;
    >
    > if (!iss) throw bad_float();
    >
    > return f;
    > }
    >
    >
    > Jonathan
    >


    Thanks :)
     
    Trond Valen, Dec 6, 2005
    #4
  5. Trond Valen

    Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Jonathan Mcdougall wrote:
    > Trond Valen wrote:
    > > Hi!
    > >
    > > Stupid atof, it returns 0.0 when it tries to parse something like
    > > "fish". So I don't know whether the number was really 0 or a string that
    > > couldn't be parsed. Is there a better way to do this?

    >
    > # include <sstream>
    > # include <string>
    >
    > class bad_float {};
    >
    > float string_to_float(const std::string &s)
    > {
    > std::istringstream iss(s);
    > float f;
    > iss >> f;
    >
    > if (!iss) throw bad_float();
    >
    > return f;
    > }


    Better to use double rather than float. Despite its name, atof returns
    a double rather than a float [*], so your function would need to be
    changed to work with double to be a direct replacement.

    [*] as far as I can work out from a bit of testing and research. I
    don't have the C standard available for a definitive answer.

    Gavin Deane
     
    , Dec 6, 2005
    #5
  6. Jonathan Mcdougall wrote:
    > Trond Valen wrote:
    >> Hi!
    >>
    >> Stupid atof, it returns 0.0 when it tries to parse something like
    >> "fish". So I don't know whether the number was really 0 or a string that
    >> couldn't be parsed. Is there a better way to do this?

    >
    > # include <sstream>
    > # include <string>
    >
    > class bad_float {};
    >
    > float string_to_float(const std::string &s)
    > {
    > std::istringstream iss(s);
    > float f;
    > iss >> f;
    >
    > if (!iss) throw bad_float();
    >
    > return f;
    > }
    >


    This doesn't take care invalid input like "1.04df". It cannot detect
    overflow. strto* family functions are always a better choice unless you
    are not doing toy programming.


    >
    > Jonathan
    >


    Krishanu
     
    Krishanu Debnath, Dec 6, 2005
    #6
  7. Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    On 6 Dec 2005 02:31:00 -0800, wrote:

    >
    >Trond Valen wrote:
    >> Hi!
    >>
    >> Stupid atof, it returns 0.0 when it tries to parse something like
    >> "fish". So I don't know whether the number was really 0 or a string that
    >> couldn't be parsed. Is there a better way to do this?

    >
    >Stupid indeed. But to answer your question: yes, there is a better way.
    >Use C++ stringstreams from <sstream>


    It isn't quite that easy. For example, what does this program do? You
    might expect it to throw an exception, but it doesn't:

    #include <iostream>
    #include <ostream>
    #include <sstream>
    #include <string>

    int main() {
    using namespace std;
    istringstream ss(string("fish"));
    double f = 0.0;
    ss >> f;
    cout << f << endl;
    }

    >or use strtod (and strtol instead
    >of atoi) which can distinguish between zero and an error case.


    This is much better IMHO.

    >
    >Gavin Deane


    --
    Bob Hairgrove
     
    Bob Hairgrove, Dec 6, 2005
    #7
  8. Trond Valen

    Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Bob Hairgrove wrote:
    > On 6 Dec 2005 02:31:00 -0800, wrote:
    >
    > >
    > >Trond Valen wrote:
    > >> Hi!
    > >>
    > >> Stupid atof, it returns 0.0 when it tries to parse something like
    > >> "fish". So I don't know whether the number was really 0 or a string that
    > >> couldn't be parsed. Is there a better way to do this?

    > >
    > >Stupid indeed. But to answer your question: yes, there is a better way.
    > >Use C++ stringstreams from <sstream>

    >
    > It isn't quite that easy. For example, what does this program do? You
    > might expect it to throw an exception, but it doesn't:


    Why would I expect that? Apart from memory allocation, where is any
    code that might throw?

    > #include <iostream>
    > #include <ostream>
    > #include <sstream>
    > #include <string>
    >
    > int main() {
    > using namespace std;
    > istringstream ss(string("fish"));
    > double f = 0.0;
    > ss >> f;
    > cout << f << endl;
    > }


    Implicit in my statement that you can use streams is the requirement
    that you know (or learn) *how* to use them. What your code is missing
    is an important part of using any input stream (including, for example,
    std::cin). That is, *every* time you read something, you should check
    the stream state to see if it succeeded. So after ss >> f; you need
    something like

    if (!ss)
    {
    // failed to read a double
    // report the error, perhaps by throwing an exception
    }

    > >or use strtod (and strtol instead
    > >of atoi) which can distinguish between zero and an error case.

    >
    > This is much better IMHO.


    For simple cases (like the OP's) it is perfectly sufficient.

    Gavin Deane
     
    , Dec 6, 2005
    #8
  9. Trond Valen

    Sumit Rajan Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    "Trond Valen" <> wrote in message
    news:dn3ok5$r4g$...
    > Hi!
    >
    > Stupid atof, it returns 0.0 when it tries to parse something like "fish".
    > So I don't know whether the number was really 0 or a string that couldn't
    > be parsed. Is there a better way to do this?



    Read the first few questions (and maybe the answers, too) on this page:
    http://www.parashift.com/c -faq-lite/misc-technical-issues.html

    Regards,
    Sumit.
    --
    Sumit Rajan <>
     
    Sumit Rajan, Dec 6, 2005
    #9
  10. Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    On 6 Dec 2005 04:39:29 -0800, wrote:

    >> It isn't quite that easy. For example, what does this program do? You
    >> might expect it to throw an exception, but it doesn't:

    >
    >Why would I expect that? Apart from memory allocation, where is any
    >code that might throw?


    I meant "you" in a general, hypothetical sense ... just a sloppy
    Americanism, I suppose. Here's a better version:

    "One might expect it to throw an exception, but it doesn't:"

    --
    Bob Hairgrove
     
    Bob Hairgrove, Dec 6, 2005
    #10
  11. Trond Valen

    Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Bob Hairgrove wrote:
    > On 6 Dec 2005 04:39:29 -0800, wrote:
    >
    > >> It isn't quite that easy. For example, what does this program do? You
    > >> might expect it to throw an exception, but it doesn't:

    > >
    > >Why would I expect that? Apart from memory allocation, where is any
    > >code that might throw?

    >
    > I meant "you" in a general, hypothetical sense ... just a sloppy
    > Americanism, I suppose. Here's a better version:
    >
    > "One might expect it to throw an exception, but it doesn't:"


    By the same token, my response should have been

    "Why would one expect that?"

    Sometimes it would be easier if everyone could just read the words I
    meant to write instead of the ones I actually wrote ;-)

    Gavin Deane
     
    , Dec 6, 2005
    #11
  12. Jonathan Mcdougall wrote:
    >
    > # include <sstream>
    > # include <string>
    >
    > class bad_float {};
    >
    > float string_to_float(const std::string &s)
    > {
    > std::istringstream iss(s);
    > float f;
    > iss >> f;
    >
    > if (!iss) throw bad_float();


    Wouldn't a successful read of the float from the
    istringstream set the eof() and fail() flags of the
    stream, thus making (!iss) true upon *success*?

    >
    > return f;
    > }
    >
    >
    > Jonathan
    >
     
    Jacek Dziedzic, Dec 6, 2005
    #12
  13. Trond Valen

    red floyd Guest

    Jacek Dziedzic wrote:
    > Jonathan Mcdougall wrote:
    >
    >>
    >> # include <sstream>
    >> # include <string>
    >>
    >> class bad_float {};
    >>
    >> float string_to_float(const std::string &s)
    >> {
    >> std::istringstream iss(s);
    >> float f;
    >> iss >> f;
    >>
    >> if (!iss) throw bad_float();

    >
    >
    > Wouldn't a successful read of the float from the
    > istringstream set the eof() and fail() flags of the
    > stream, thus making (!iss) true upon *success*?
    >
    >


    No. The eof() and fail() are only set upon an attempt to read past EOF.
     
    red floyd, Dec 6, 2005
    #13
  14. Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Krishanu Debnath wrote:

    > This doesn't take care invalid input like "1.04df". It cannot detect
    > overflow. strto* family functions are always a better choice unless you
    > are not doing toy programming.
    >


    "Unless you are not"? So strto* is good for toy programming then? I
    think you mixed up your logic there ;)

    Or not:
    http://www.parashift.com/c -faq-lite/input-output.html#faq-15.1
     
    Michael O'Keeffe, Dec 6, 2005
    #14
  15. Trond Valen

    Marcus Kwok Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    Krishanu Debnath <> wrote:
    > Jonathan Mcdougall wrote:
    >> Trond Valen wrote:
    >>> Hi!
    >>>
    >>> Stupid atof, it returns 0.0 when it tries to parse something like
    >>> "fish". So I don't know whether the number was really 0 or a string that
    >>> couldn't be parsed. Is there a better way to do this?

    >>
    >> # include <sstream>
    >> # include <string>
    >>
    >> class bad_float {};
    >>
    >> float string_to_float(const std::string &s)
    >> {
    >> std::istringstream iss(s);
    >> float f;
    >> iss >> f;
    >>
    >> if (!iss) throw bad_float();
    >>
    >> return f;
    >> }
    >>

    >
    > This doesn't take care invalid input like "1.04df". It cannot detect
    > overflow. strto* family functions are always a better choice unless you
    > are not doing toy programming.


    This version (from the FAQ) can detect if there are extra characters:

    class BadConversion : public std::runtime_error {
    public:
    BadConversion(const std::string& s)
    : std::runtime_error(s)
    { }
    };

    inline double convertToDouble(const std::string& s,
    bool failIfLeftoverChars = true)
    {
    std::istringstream i(s);
    double x;
    char c;
    if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
    throw BadConversion("convertToDouble(\"" + s + "\")");
    return x;
    }

    --
    Marcus Kwok
     
    Marcus Kwok, Dec 6, 2005
    #15
  16. red floyd wrote:

    > No. The eof() and fail() are only set upon an attempt to read past EOF.


    Are they? I thought they *may* either trigger upon reading past
    EOF or up till EOF

    http://www.parashift.com/c -faq-lite/input-output.html#faq-15.5
    has this to say:

    "(...) the eof state may not get set until after a read is attempted
    past the end of file. That is, reading the last byte from a file might
    not set the eof state" (which I interpret as "reading the last byte
    from a file may as well set the eof state").

    Can somebody clarify?

    - J.
     
    Jacek Dziedzic, Dec 6, 2005
    #16
  17. Trond Valen

    red floyd Guest

    Jacek Dziedzic wrote:
    > red floyd wrote:
    >
    >> No. The eof() and fail() are only set upon an attempt to read past EOF.

    >
    >
    > Are they? I thought they *may* either trigger upon reading past
    > EOF or up till EOF
    >
    > http://www.parashift.com/c -faq-lite/input-output.html#faq-15.5
    > has this to say:
    >
    > "(...) the eof state may not get set until after a read is attempted
    > past the end of file. That is, reading the last byte from a file might
    > not set the eof state" (which I interpret as "reading the last byte
    > from a file may as well set the eof state").
    >
    > Can somebody clarify?
    >
    > - J.


    consider the following snippet:

    std::istringstream is("123");
    int i;
    while (is >> i)
    std::cout << i << std::endl;


    If an istringstream was allowed to set eof() or fail() upon reading the
    123, but before trying to read (or read past) the end of file/buffer,
    then the semantics of the above snippet would be messed up, and you
    wouldn't get the expected output of "123".
     
    red floyd, Dec 6, 2005
    #17
  18. Trond Valen

    meagar Guest

    Re: Float-to-string conversion that raises exception instead of returning 0.0 like atof

    I have never known the EOF flag to be set until an attempt is made to
    read past the end of the file. The classic example of how to read
    until EOF with an istream depends on this behaviour:

    int n;
    while (cin >> n) {
    // use N, knowing it contains actual input; the loops condition does
    the EOF checking
    }

    If reading the last byte could "sometimes" cause (bool)cin to be false
    (ie, EOF) then this logic totally breaks.
     
    meagar, Dec 7, 2005
    #18
  19. meagar wrote:
    > I have never known the EOF flag to be set until an attempt is made to
    > read past the end of the file. The classic example of how to read
    > until EOF with an istream depends on this behaviour:


    Well, running this code

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

    int main() {
    istringstream ss("123");
    int i;
    ss >> i;
    cout << ss.eof() << ss.fail() << endl;
    }

    produces "10" on my machine. Therefore I'd argue that EOF
    was set here after having read the last datum in the stream.

    > int n;
    > while (cin >> n) {
    > // use N, knowing it contains actual input; the loops condition does
    > the EOF checking
    > }


    this apparrently does not break, because fail() was not set.

    > If reading the last byte could "sometimes" cause (bool)cin to be false
    > (ie, EOF) then this logic totally breaks.


    doesn't (bool)(cin >>n) check for (!good()) rather than eof()?

    - J.
     
    Jacek Dziedzic, Dec 7, 2005
    #19
  20. red floyd wrote:
    > consider the following snippet:
    >
    > std::istringstream is("123");
    > int i;
    > while (is >> i)
    > std::cout << i << std::endl;
    >
    >
    > If an istringstream was allowed to set eof() or fail() upon reading the
    > 123, but before trying to read (or read past) the end of file/buffer,
    > then the semantics of the above snippet would be messed up, and you
    > wouldn't get the expected output of "123".


    The following code

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

    int main() {
    istringstream ss("123");
    int i;
    ss >> i;
    cout << ss.eof() << ss.fail() << endl;
    }

    produces "10" on my machine. Therefore I'd argue that inded
    " an istringstream *was* allowed to set eof() or fail() upon
    reading the 123 " (since eof() was set).

    Your snippet still works, because while(is >> i) does not
    care about eof() but fail(), at least that's how I understand it.

    - J.
     
    Jacek Dziedzic, Dec 7, 2005
    #20
    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. bd
    Replies:
    0
    Views:
    669
  2. Noah
    Replies:
    3
    Views:
    506
  3. Replies:
    21
    Views:
    720
    Pete Becker
    Apr 13, 2006
  4. Replies:
    14
    Views:
    1,094
    Old Wolf
    Aug 1, 2006
  5. Carsten Fuchs
    Replies:
    45
    Views:
    1,655
    James Kanze
    Oct 8, 2009
Loading...

Share This Page