I have some input to be read by a input filestream (for example):
-365.269511 -0.356123 -Inf 0.000000
When I use std::ifstream mystream;
to read from the file to some
double d1 = -1, d2 = -1, d3 = -1, d4 = -1;
(assume mystream
has already been opened and the file is valid),
mystream >> d1 >> d2 >> d3 >> d4;
mystream
is in the fail state. I would expect
std::cout << d1 << " " << d2 << " " << d3 << " " << d4 << std::endl;
to output
-365.269511 -0.356123 -1 -1
. I would want it to output -365.269511 -0.356123 -Inf 0
instead.
This set of data was output using C++ streams. Why can't I do the reverse process (read in my output)? How can I get the functionality I seek?
From MooingDuck:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
double myd = std::numeric_limits<double>::infinity();
cout << myd << '\n';
cin >> myd;
cout << cin.good() << ":" << myd << endl;
return 0;
}
Input: inf
Output:
inf
0:inf
See also: http://ideone.com/jVvei
Also related to this problem is NaN
parsing, even though I do not give examples for it.
I added to the accepted answer a complete solution on ideone. It also includes paring for "Inf" and "nan", some possible variations to those keywords that may come from other programs, such as MatLab.
Write a function with a signature like this:
Inside it, you:
operator>>
std::stod
,boost::lexical_cast
, etc...Edit: To avoid the use of a wrapper structure around a double, I enclose an
istream
within a wrapper class instead.Unfortunately, I am unable to figure out how to avoid the ambiguity created by adding another input method for
double
. For the implementation below, I created a wrapper structure around anistream
, and the wrapper class implements the input method. The input method determines negativity, then tries to extract a double. If that fails, it starts a parse.Edit: Thanks to sehe for getting me to check for error conditions better.
The parsing routine was a little trickier to implement than I first thought it would be, but I wanted to avoid trying to
putback
an entire string.One difference in behavior this routine will have over the the default
double
input is that the-
character is not consumed if the input was, for example"-inp"
. On failure,"-inp"
will still be in the stream fordouble_istream
, but for a regularistream
only"inp"
will be left in the the stream.The output of the above snippet on my system is:
Edit: Adding a "iomanip" like helper class. A
double_imanip
object will act like a toggle when it appears more than once in the>>
chain.And then the following code to try it out:
The output of the above is:
Edit from Drise: I made a few edits to accept variations such as Inf and nan that wasn't originally included. I also made it into a compiled demonstration, which can be viewed at http://ideone.com/qIFVo.
You will have to write a custom extraction function, since your specific implementation clearly does not handle them correctly.
Just read your variables into string and parse them. You can't put string into double variables and expect them to be outputted like a string, because if it worked, strings wouldn't be necessary.
Seomthing like:
Update Provided a simple test case that shows that Boost Spirit is capable to handle all varieties of special values in this area. See below: Boost Spirit (FTW).
The standard
The only normative information in this area that I've been able to find is in sections 7.19.6.1/7.19.6.2 of the C99 standard.
Sadly, the corresponding sections of the latest C++ standard document (n3337.pdf) doesn't appear to specify support for
infinity
,inf
and orNaN
in the same way. (Perhaps I'm missing a footnote that refers to the C99/C11 spec?)The library implementors
In 2000, the Apache libstdcxx received a bug report stating
However the subsequent discussion yielded that (at least with named
locale
-s) it would actually be illegal for an implementation to parse special values:Other resources
securecoding.cert.org clearly states that the following 'Compliant Code' is required to avoid parsing infinity or NaN. This implies, that some implementations actually support that - assuming the author ever tested the published code.
Boost Spirit (FTW)
The following trivial example has the desired output:
Output:
Summary/TL;DR
I'm inclined to say that C99 specifies the behaviour for *printf/*scanf to include infinity and NaN. C++11, sadly appears to not specify it (or even prohibit it, in the presence of named locales).