是否可以使用输入流读取无穷大或NaN值? [英] Is it possible to read infinity or NaN values using input streams?
问题描述
我有一些输入要通过输入文件流读取(例如):
-365.269511 -0.356123 -Inf 0.000000
当我使用
std :: ifstream mystream;
从文件读取一些 double d1 = -1,d2 = -1,d3 = -1,d4 = -1;
(假设 mystream
已经打开并且文件有效),
mystream>> d1> d2> d3> d4;
mystream
处于失败状态。我会期望
std :: cout< d1<< < d2 < < d3 < < d4 < std :: endl;
输出
-365.269511 -0.356123 -1 -1
。我想要它输出 -365.269511 -0.356123 -Inf 0
。
C ++流。为什么我不能做逆过程(在我的输出中读取)?
> #include< iostream>
#include< limits>
using namespace std;
int main()
{
double myd = std :: numeric_limits< double> :: infinity();
cout<< myd < '\\\
';
cin>> myd;
cout<< cin.good()<< :<< myd < endl;
return 0;
}
输入:
inf
输出:
inf
0:inf
另请参阅: http:/ /ideone.com/jVvei
与此问题相关的还有
NaN
解析,即使我
我添加到接受的答案在ideone的一个完整的解决方案。
解决方案 div>Edit:为了避免在double周围使用包装器结构,我在包装器类中封装了一个
istream
。
不幸的是,我无法弄清楚如何避免为
编辑:感谢您为我更好地检查错误情况。如果失败,它会启动解析。double
添加另一个输入法创建的歧义。对于下面的实现,我在istream
周围创建了一个包装器结构,并且包装器类实现了输入法。输入法确定负性,然后尝试提取双精度。struct double_istream {
std :: istream& in;
double_istream(std :: istream& i):in(i){}
double_istream& parse_on_fail(double& x,bool neg);
double_istream& operator>> (double& x){
bool neg = false;
char c;
if(!in.good())return * this;
while(isspace(c = in.peek()))in.get();
if(c ==' - '){neg = true; }
在>> X;
if(!in.fail())return * this;
return parse_on_fail(x,neg);
}
};
解析例程比我初次想象的要复杂一些,避免尝试
putback
整个字符串。double_istream&
double_istream :: parse_on_fail(double& x,bool neg){
const char * exp [] = {,inf,NaN};
const char * e = exp [0];
int l = 0;
char inf [4];
char * c = inf;
if(neg)* c ++ =' - ';
in.clear();
if(!(in>> * c).good())return * this;
switch(* c){
case'i':e = exp [l = 1];打破;
case'N':e = exp [l = 2];打破;
}
while(* c == * e){
if((e-exp [1])== 2)break;
++ e; if(!(in>> * ++ c).good())break;
}
if(in.good()&& * c == * e){
switch(l){
case 1:x = std :: numeric_limits< ; double> :: infinity();打破;
case 2:x = std :: numeric_limits< double> :: quiet_NaN();打破;
}
if(neg)x = -x;
return * this;
} else if(!in.good()){
if(!in.fail())return * this;
in.clear(); - C;
}
do {in.putback(* c); } while(c--!= inf);
in.setstate(std :: ios_base :: failbit);
return * this;
}
此例程的行为与默认
double
输入是如果输入为-
字符没有消耗,例如- inp
。失败时,- inp
仍会在double_istream
的流中,但对于常规istream
只有inp
将留在流中。std :: istringstream iss(1.0 -NaN inf -inf NaN 1.2);
double_istream in(iss);
double u,v,w,x,y,z;
在>> u> v>> w。 x>> y>> z;
std :: cout<< u<< < v<< < w <
<< x<< < y < < z < std :: endl;
我的系统上面的代码片段的输出是:
1 nan inf -inf nan 1.2
修改:添加类似辅助类的iomanip。当
>>
链中出现多次时,double_imanip
p>
struct double_imanip {
mutable std :: istream * in;
const double_imanip& operator>> (double& x)const {
double_istream(* in)>> X;
return * this;
}
std :: istream& operator>> (const double_imanip&)const {
return * in;
}
};
const double_imanip&
operator>> (std :: istream& in,const double_imanip& dm){
dm.in =& in;
return dm;
}
然后下面的代码试试:
std :: istringstream iss(1.0 -NaN inf -inf NaN 1.2 inf);
double u,v,w,x,y,z,fail_double;
std :: string fail_string
iss>> double_imanip()
>> u> v>> w。 x>> y>> z
>> double_imanip()
>> fail_double;
std :: cout<< u<< < v<< < w <
<< x<< < y < < z < std :: endl;
if(iss.fail()){
iss.clear();
iss>> fail_string;
std :: cout<< fail_string<< std :: endl;
} else {
std :: cout<< TEST FAILED<< std :: endl;
}
上面的输出是:
1 nan inf -inf nan 1.2
inf
从Drise编辑:我进行了几项修改,以接受原本不包含的Inf和nan等变体。我还将其编入了一个编译演示,可以在 http://ideone.com/qIFVo 上查看。 / p>
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.
解决方案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.
struct double_istream { std::istream ∈ double_istream (std::istream &i) : in(i) {} double_istream & parse_on_fail (double &x, bool neg); double_istream & operator >> (double &x) { bool neg = false; char c; if (!in.good()) return *this; while (isspace(c = in.peek())) in.get(); if (c == '-') { neg = true; } in >> x; if (! in.fail()) return *this; return parse_on_fail(x, neg); } };
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.double_istream & double_istream::parse_on_fail (double &x, bool neg) { const char *exp[] = { "", "inf", "NaN" }; const char *e = exp[0]; int l = 0; char inf[4]; char *c = inf; if (neg) *c++ = '-'; in.clear(); if (!(in >> *c).good()) return *this; switch (*c) { case 'i': e = exp[l=1]; break; case 'N': e = exp[l=2]; break; } while (*c == *e) { if ((e-exp[l]) == 2) break; ++e; if (!(in >> *++c).good()) break; } if (in.good() && *c == *e) { switch (l) { case 1: x = std::numeric_limits<double>::infinity(); break; case 2: x = std::numeric_limits<double>::quiet_NaN(); break; } if (neg) x = -x; return *this; } else if (!in.good()) { if (!in.fail()) return *this; in.clear(); --c; } do { in.putback(*c); } while (c-- != inf); in.setstate(std::ios_base::failbit); return *this; }
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.std::istringstream iss("1.0 -NaN inf -inf NaN 1.2"); double_istream in(iss); double u, v, w, x, y, z; in >> u >> v >> w >> x >> y >> z; std::cout << u << " " << v << " " << w << " " << x << " " << y << " " << z << std::endl;
The output of the above snippet on my system is:
1 nan inf -inf nan 1.2
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.struct double_imanip { mutable std::istream *in; const double_imanip & operator >> (double &x) const { double_istream(*in) >> x; return *this; } std::istream & operator >> (const double_imanip &) const { return *in; } }; const double_imanip & operator >> (std::istream &in, const double_imanip &dm) { dm.in = ∈ return dm; }
And then the following code to try it out:
std::istringstream iss("1.0 -NaN inf -inf NaN 1.2 inf"); double u, v, w, x, y, z, fail_double; std::string fail_string; iss >> double_imanip() >> u >> v >> w >> x >> y >> z >> double_imanip() >> fail_double; std::cout << u << " " << v << " " << w << " " << x << " " << y << " " << z << std::endl; if (iss.fail()) { iss.clear(); iss >> fail_string; std::cout << fail_string << std::endl; } else { std::cout << "TEST FAILED" << std::endl; }
The output of the above is:
1 nan inf -inf nan 1.2 inf
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.
这篇关于是否可以使用输入流读取无穷大或NaN值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文