Connecting Tech Pros Worldwide Help | Site Map

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

Trond Valen
Guest
 
Posts: n/a
#1: Dec 6 '05
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
Jonathan Mcdougall
Guest
 
Posts: n/a
#2: Dec 6 '05

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


Trond Valen wrote:[color=blue]
> 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?[/color]

# 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

deane_gavin@hotmail.com
Guest
 
Posts: n/a
#3: Dec 6 '05

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



Trond Valen wrote:[color=blue]
> 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?[/color]

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

Trond Valen
Guest
 
Posts: n/a
#4: Dec 6 '05

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


Jonathan Mcdougall wrote:[color=blue]
> Trond Valen wrote:
>[color=green]
>>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?[/color]
>
>
> # 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
>[/color]

Thanks :)
deane_gavin@hotmail.com
Guest
 
Posts: n/a
#5: Dec 6 '05

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



Jonathan Mcdougall wrote:[color=blue]
> Trond Valen wrote:[color=green]
> > 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?[/color]
>
> # 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;
> }[/color]

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

Krishanu Debnath
Guest
 
Posts: n/a
#6: Dec 6 '05

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


Jonathan Mcdougall wrote:[color=blue]
> Trond Valen wrote:[color=green]
>> 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?[/color]
>
> # 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;
> }
>[/color]

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.

[color=blue]
>
> Jonathan
>[/color]

Krishanu
Bob Hairgrove
Guest
 
Posts: n/a
#7: Dec 6 '05

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


On 6 Dec 2005 02:31:00 -0800, deane_gavin@hotmail.com wrote:
[color=blue]
>
>Trond Valen wrote:[color=green]
>> 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?[/color]
>
>Stupid indeed. But to answer your question: yes, there is a better way.
>Use C++ stringstreams from <sstream>[/color]

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;
}
[color=blue]
>or use strtod (and strtol instead
>of atoi) which can distinguish between zero and an error case.[/color]

This is much better IMHO.
[color=blue]
>
>Gavin Deane[/color]

--
Bob Hairgrove
NoSpamPlease@Home.com
deane_gavin@hotmail.com
Guest
 
Posts: n/a
#8: Dec 6 '05

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



Bob Hairgrove wrote:[color=blue]
> On 6 Dec 2005 02:31:00 -0800, deane_gavin@hotmail.com wrote:
>[color=green]
> >
> >Trond Valen wrote:[color=darkred]
> >> 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?[/color]
> >
> >Stupid indeed. But to answer your question: yes, there is a better way.
> >Use C++ stringstreams from <sstream>[/color]
>
> 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:[/color]

Why would I expect that? Apart from memory allocation, where is any
code that might throw?
[color=blue]
> #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;
> }[/color]

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
}
[color=blue][color=green]
> >or use strtod (and strtol instead
> >of atoi) which can distinguish between zero and an error case.[/color]
>
> This is much better IMHO.[/color]

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

Gavin Deane

Sumit Rajan
Guest
 
Posts: n/a
#9: Dec 6 '05

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



"Trond Valen" <valen@stud.ntnu.no> wrote in message
news:dn3ok5$r4g$1@orkan.itea.ntnu.no...[color=blue]
> 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?[/color]


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

Regards,
Sumit.
--
Sumit Rajan <sumitr@msdc.hcltech.com>


Bob Hairgrove
Guest
 
Posts: n/a
#10: Dec 6 '05

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


On 6 Dec 2005 04:39:29 -0800, deane_gavin@hotmail.com wrote:
[color=blue][color=green]
>> 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:[/color]
>
>Why would I expect that? Apart from memory allocation, where is any
>code that might throw?[/color]

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
NoSpamPlease@Home.com
deane_gavin@hotmail.com
Guest
 
Posts: n/a
#11: Dec 6 '05

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



Bob Hairgrove wrote:[color=blue]
> On 6 Dec 2005 04:39:29 -0800, deane_gavin@hotmail.com wrote:
>[color=green][color=darkred]
> >> 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:[/color]
> >
> >Why would I expect that? Apart from memory allocation, where is any
> >code that might throw?[/color]
>
> 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:"[/color]

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

Jacek Dziedzic
Guest
 
Posts: n/a
#12: Dec 6 '05

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


Jonathan Mcdougall wrote:[color=blue]
>
> # 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();[/color]

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*?
[color=blue]
>
> return f;
> }
>
>
> Jonathan
>[/color]
red floyd
Guest
 
Posts: n/a
#13: Dec 6 '05

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


Jacek Dziedzic wrote:[color=blue]
> Jonathan Mcdougall wrote:
>[color=green]
>>
>> # 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();[/color]
>
>
> 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*?
>
>[/color]

No. The eof() and fail() are only set upon an attempt to read past EOF.
Michael O'Keeffe
Guest
 
Posts: n/a
#14: Dec 6 '05

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


Krishanu Debnath wrote:
[color=blue]
> 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.
>[/color]

"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-lit....html#faq-15.1

Marcus Kwok
Guest
 
Posts: n/a
#15: Dec 6 '05

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


Krishanu Debnath <krishanu@interrasystems.com> wrote:[color=blue]
> Jonathan Mcdougall wrote:[color=green]
>> Trond Valen wrote:[color=darkred]
>>> 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?[/color]
>>
>> # 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;
>> }
>>[/color]
>
> 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.[/color]

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
Jacek Dziedzic
Guest
 
Posts: n/a
#16: Dec 6 '05

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


red floyd wrote:
[color=blue]
> No. The eof() and fail() are only set upon an attempt to read past EOF.[/color]

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

http://www.parashift.com/c++-faq-lit....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.
red floyd
Guest
 
Posts: n/a
#17: Dec 6 '05

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


Jacek Dziedzic wrote:[color=blue]
> red floyd wrote:
>[color=green]
>> No. The eof() and fail() are only set upon an attempt to read past EOF.[/color]
>
>
> Are they? I thought they *may* either trigger upon reading past
> EOF or up till EOF
>
> http://www.parashift.com/c++-faq-lit....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.[/color]

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".
meagar
Guest
 
Posts: n/a
#18: Dec 7 '05

re: Float-to-string conversion that raises exception instead of returning0.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.

Jacek Dziedzic
Guest
 
Posts: n/a
#19: Dec 7 '05

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


meagar wrote:[color=blue]
> 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:[/color]

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.
[color=blue]
> int n;
> while (cin >> n) {
> // use N, knowing it contains actual input; the loops condition does
> the EOF checking
> }[/color]

this apparrently does not break, because fail() was not set.
[color=blue]
> If reading the last byte could "sometimes" cause (bool)cin to be false
> (ie, EOF) then this logic totally breaks.[/color]

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

- J.
Jacek Dziedzic
Guest
 
Posts: n/a
#20: Dec 7 '05

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


red floyd wrote:[color=blue]
> 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".[/color]

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
Guest
 
Posts: n/a
#21: Dec 7 '05

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


Perhaps we can clarify the eof() and fail() issue?
I propose the code I've been using with success for
some time. I *think* it is correct as it had never
failed me, but perhaps I'm missing something and it's
not portable or something. Please comment.

double str_to_double(std::string s) {
stringstream ss(s);
double i;
ss >> i;

// when the conversion goes fine:
// - the stream is eof(), because all chars were read
// - because of eof() it is also !good(),
// - fail(), however, is 0 (sic!)
// good: 0, fail: 0, eof: 1, !ss==fail==0

// when the conversion goes wrong
// 1) some chars could not be converted as in "foo"
// - stream is in fail state
// - good: 0, fail: 1, eof: any, !ss==fail==1
// 2) conversion was fine, but chars remain in the
// stream, which means the text was something
// more than a number, as in "234.aaa" or "1.2.3"
// then stream is good() and !eof() (chars remain)
// - good:1, fail: 0, eof: 0, !ss==fail==0
// 3) trying to convert a "" (empty string)
// - stream ran out of characters and is in eof and fail
// - good:0, fail: 1, eof: 1, !ss==fail==1

// summary: a conversion is deemed successful when
// !good() and !fail() (sic!)

if(!ss.good() && !ss.fail()) return i;
throw EConversionError("Offending string: "+s); // defined elsewhere
}
Closed Thread