473,385 Members | 1,192 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Reading and Writing float value of infinity to file.

The output of the following program is:
1.#INF
1

But:
1.#INF
1.#INF

was expected and desired. How can I read a value of infinity from a stream?

#include <iostream>
#include <fstream>
#include <limits>

int main(void)
{
float Infinity;
Infinity = std::numeric_limits<float>::infinity();
std::cout << Infinity << "\n";

std::ofstream outf("test.txt");
if ( outf.is_open() )
outf << Infinity;

outf.close();

float Value = 0.0f;
std::ifstream inf("test.txt");
if ( inf.is_open() )
inf >Value;

inf.close();

std::cout << Value << "\n";

return 0;
}
Oct 19 '07 #1
14 5496
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
The output of the following program is:
1.#INF
1
But:
1.#INF
1.#INF
was expected and desired. How can I read a value of infinity
from a stream?
According to the current C++ standard, there is no infinity, so
you're in the realm of implementation defined, if not undefined
behavior. Presumably, however, the next version of the standard
will use C99 as the reference, rather than C90; in C99,
infinity is required to be output as either "inf" or "infinity",
and both should convert to infinity when read.

The current standard does not allow this behavior, however, nor
does the current draft, since they do not allow extraction of
"inf" when reading a number. So while the implementations I
usually use all output "inf", all report a read error when
attempting to read it back into a double. The only solution I
know of off hand is to read into a string, compare manually for
inf and nan, and use istringstream to convert the double if thos
tests fail.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 19 '07 #2
On 2007-10-19 02:56:07 -0400, "Jim Langston" <ta*******@rocketmail.comsaid:
>
std::ofstream outf("test.txt");
if ( outf.is_open() )
outf << Infinity;

outf.close();
There's no newline at the end of "test.txt", so technically it's not a
valid text stream. No guarantees, but adding a newline might help.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 19 '07 #3
"James Kanze" <ja*********@gmail.comwrote in message
news:11*********************@i13g2000prf.googlegro ups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
The output of the following program is:
1.#INF
1
But:
1.#INF
1.#INF
was expected and desired. How can I read a value of infinity
from a stream?
According to the current C++ standard, there is no infinity, so
you're in the realm of implementation defined, if not undefined
behavior. Presumably, however, the next version of the standard
will use C99 as the reference, rather than C90; in C99,
infinity is required to be output as either "inf" or "infinity",
and both should convert to infinity when read.

The current standard does not allow this behavior, however, nor
does the current draft, since they do not allow extraction of
"inf" when reading a number. So while the implementations I
usually use all output "inf", all report a read error when
attempting to read it back into a double. The only solution I
know of off hand is to read into a string, compare manually for
inf and nan, and use istringstream to convert the double if thos
tests fail.

---------------

Hmmm.. I was actually looking for a 9's rule number to indicate no value.
But it seems that infinity won't do it for me then, especially since I need
to read 3 of these values in a row.

I guess can I can research an ifstream implementation to read 1.#INF as
infinity, create my own class and override operator<<. It might be enough
in this specific implementation to read the number, if it's 1, peek at the
next value, if it's # then presume it's going to be #INF, read to string,
compare for #INF and if so load infinity. And then override operator float.

Let me see what I can come up with.
Oct 19 '07 #4

"Jim Langston" <ta*******@rocketmail.comwrote in message
news:Gc*************@newsfe02.lga...
"James Kanze" <ja*********@gmail.comwrote in message
news:11*********************@i13g2000prf.googlegro ups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
>The output of the following program is:
1.#INF
1
>But:
1.#INF
1.#INF
>was expected and desired. How can I read a value of infinity
from a stream?
[Snip discussion about C++ not supporing infinity]

Well, this is what I came up with. Output is as I want. Do you see
anything I'm doing wrong here? Of course I'll have to come up with a better
name than "MyFloat".

1.#INF
1 2.2 3.3
1.#INF 2.2 3.3

#include <iostream>
#include <fstream>
#include <limits>
#include <string>

class MyFloat
{
public:
MyFloat( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};

std::istream& operator>>( std::istream& is, MyFloat& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}

return is;
}

int main(void)
{
float Infinity, Foo = 2.2f, Bar = 3.3f;
Infinity = std::numeric_limits<float>::infinity();
std::cout << Infinity << "\n";

std::ofstream outf("test.txt");
if ( outf.is_open() )
outf << Infinity << " " << Foo << " " << Bar << "\n";

outf.close();

float Value = 0.0f, Value2 = 0.0f, Value3 = 0.0f;
std::ifstream inf("test.txt");
if ( inf.is_open() )
inf >Value >Foo >Bar;

inf.close();

std::cout << Value << " " << Foo << " " << Bar << "\n";

MyFloat MyValue = 0.0f, MyValue2 = 0.0f, MyValue3 = 0.0f;
std::ifstream inf2("test.txt");
if ( inf2.is_open() )
inf2 >MyValue >MyValue2 >MyValue3;

inf2.close();

std::cout << MyValue << " " << MyValue2 << " " << MyValue3 << "\n";

return 0;
}
Oct 19 '07 #5
"Jim Langston" <ta*******@rocketmail.comwrote in message
news:0o***********@newsfe06.lga...
>
"Jim Langston" <ta*******@rocketmail.comwrote in message
news:Gc*************@newsfe02.lga...
>"James Kanze" <ja*********@gmail.comwrote in message
news:11*********************@i13g2000prf.googlegr oups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
>>The output of the following program is:
1.#INF
1
>>But:
1.#INF
1.#INF
>>was expected and desired. How can I read a value of infinity
from a stream?
[Snip discussion about C++ not supporing infinity]
Well, this is what I think I'll put into production, unless anyone can show
me any flaws in it. It seems to work fine as a float in my rudimentary
tests.

namespace jml
{
class Float
{
public:
Float( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};

std::istream& operator>>( std::istream& is, Float& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}

return is;
}

};

I'll probably make Value private just because.
Oct 19 '07 #6
Jim Langston wrote:
[..]
Well, this is what I think I'll put into production, unless anyone
can show me any flaws in it. It seems to work fine as a float in my
rudimentary tests.

namespace jml
{
class Float
{
public:
Float( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};

std::istream& operator>>( std::istream& is, Float& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}

return is;
}

};

I'll probably make Value private just because.
Actually, I'd probably get rid of 'operator float()' in it (besides,
it ought to be declared 'const' if you ask me), and always use the
explicit ".Value", or have a function called "value()" in it instead:

class Float
{
...
float value() const { return Value; }
private:
float Value;
};

Recently in our development we ran into some implicit conversions
that we didn't want, and it was all due to type conversion functions
(which BTW you can't declare "explicit"). We decided we didn't like
those in our own types.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 19 '07 #7
On Oct 19, 2:26 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
"Jim Langston" <tazmas...@rocketmail.comwrote in message
news:Gc*************@newsfe02.lga..."James Kanze"
<james.ka...@gmail.comwrote in message
news:11*********************@i13g2000prf.googlegro ups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
The output of the following program is:
1.#INF
1
But:
1.#INF
1.#INF
was expected and desired. How can I read a value of infinity
from a stream?
[Snip discussion about C++ not supporing infinity]
Well, this is what I came up with. Output is as I want. Do
you see anything I'm doing wrong here? Of course I'll have to
come up with a better name than "MyFloat".
1.#INF
1 2.2 3.3
1.#INF 2.2 3.3
#include <iostream>
#include <fstream>
#include <limits>
#include <string>
class MyFloat
{
public:
MyFloat( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};
std::istream& operator>>( std::istream& is, MyFloat& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}
return is;
}
I'm not sure I like that. You've built in knowledge of how your
implementation formats infinity, and I'll bet that this format
is not guaranteed. I'd do something more along the lines of:

std::istream&
operator>>( std::istream& in, MyFloat& out )
{
std::string s ;
in >s ;
if ( in ) {
static std::string const
infRepresentation =
initInfRepresentation() ;
if ( s == infRepresentation ) {
out.value = std::numeric_limits< float >::infinity() ;
} else {
std::istringstream t( s ) ;
t >out.value ;
}
}
return in ;
}

with:

std::string
initInfRepresentation()
{
std::ostringstream t ;
t << std::numeric_limits< float >::infinity() ;
return t.string() ;
}

Actually, I'd go even further, since I'd want to handle at
least positive and negative infinity, and I'd probably make the
comparison case insensitive. But you get the idea.

And of course, regardless of the solution, you have to be aware
that it will break anytime the compiler changes its
representation of infinity. Which in your case seems almost
inevitable, given that the C99 standard requires "[+-]inf" or
"[+-]infinity", and that this requirement will almost certainly
be part of the next version of the C++ standard. So if you want
any kind of portability, you really have to use your MyFloat for
both output and input.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 20 '07 #8
"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@q3g2000prf.googlegro ups.com...
On Oct 19, 2:26 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
"Jim Langston" <tazmas...@rocketmail.comwrote in message
news:Gc*************@newsfe02.lga..."James Kanze"
<james.ka...@gmail.comwrote in message
>news:11*********************@i13g2000prf.googlegr oups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
>The output of the following program is:
>1.#INF
>1
>But:
>1.#INF
>1.#INF
was expected and desired. How can I read a value of infinity
from a stream?
[Snip discussion about C++ not supporing infinity]
Well, this is what I came up with. Output is as I want. Do
you see anything I'm doing wrong here? Of course I'll have to
come up with a better name than "MyFloat".
1.#INF
1 2.2 3.3
1.#INF 2.2 3.3
#include <iostream>
#include <fstream>
#include <limits>
#include <string>
class MyFloat
{
public:
MyFloat( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};
std::istream& operator>>( std::istream& is, MyFloat& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}
return is;
}

I'm not sure I like that. You've built in knowledge of how your
implementation formats infinity, and I'll bet that this format
is not guaranteed. I'd do something more along the lines of:

std::istream&
operator>>( std::istream& in, MyFloat& out )
{
std::string s ;
in >s ;
One thing here, though, is you read a string from istream. This could put
is in a different state then if this operator>wasn't used. For example.
Say what is waiting is:
123.45And that's all.

Using a pure is >float
"And that's all" would be waiting in the stream. With this function this
way, however, "And that's all" will be thrown away.

The way I did it it would only be thrown away if the first character was #,
not as likely an occurance (but adminttedly still could happen).

Other than that, I agree with your assessment. But I don't like putting the
stream in a state that would be different if my function wasn't used.
if ( in ) {
static std::string const
infRepresentation =
initInfRepresentation() ;
if ( s == infRepresentation ) {
out.value = std::numeric_limits< float >::infinity() ;
} else {
std::istringstream t( s ) ;
t >out.value ;
}
}
return in ;
}

with:

std::string
initInfRepresentation()
{
std::ostringstream t ;
t << std::numeric_limits< float >::infinity() ;
return t.string() ;
}

Actually, I'd go even further, since I'd want to handle at
least positive and negative infinity, and I'd probably make the
comparison case insensitive. But you get the idea.

And of course, regardless of the solution, you have to be aware
that it will break anytime the compiler changes its
representation of infinity. Which in your case seems almost
inevitable, given that the C99 standard requires "[+-]inf" or
"[+-]infinity", and that this requirement will almost certainly
be part of the next version of the C++ standard. So if you want
any kind of portability, you really have to use your MyFloat for
both output and input.

Oct 20 '07 #9
"Jim Langston" <ta*******@rocketmail.comwrote in message
news:1c*************@newsfe06.lga...
>"James Kanze" <ja*********@gmail.comwrote in message
news:11**********************@q3g2000prf.googlegr oups.com...
On Oct 19, 2:26 pm, "Jim Langston" <tazmas...@rocketmail.comwrote:
"Jim Langston" <tazmas...@rocketmail.comwrote in message
news:Gc*************@newsfe02.lga..."James Kanze"
<james.ka...@gmail.comwrote in message
news:11*********************@i13g2000prf.googlegr oups.com...
On Oct 19, 8:56 am, "Jim Langston" <tazmas...@rocketmail.comwrote:
The output of the following program is:
1.#INF
1
>But:
1.#INF
1.#INF

was expected and desired. How can I read a value of infinity
from a stream?

[Snip discussion about C++ not supporing infinity]

Well, this is what I came up with. Output is as I want. Do
you see anything I'm doing wrong here? Of course I'll have to
come up with a better name than "MyFloat".
1.#INF
1 2.2 3.3
1.#INF 2.2 3.3
#include <iostream>
#include <fstream>
#include <limits>
#include <string>
class MyFloat
{
public:
MyFloat( float Value = 0.0f ): Value( Value ) {}
operator float() { return Value; }
float Value;
};
std::istream& operator>>( std::istream& is, MyFloat& mf )
{
if ( is >mf.Value )
{
if ( mf.Value == 1.0f && is.peek() == '#' )
{
std::string Rest;
is >Rest;
if ( Rest == "#INF" )
mf.Value = std::numeric_limits<float>::infinity();
}
}
return is;
}

I'm not sure I like that. You've built in knowledge of how your
implementation formats infinity, and I'll bet that this format
is not guaranteed. I'd do something more along the lines of:

std::istream&
operator>>( std::istream& in, MyFloat& out )
{
std::string s ;
in >s ;

One thing here, though, is you read a string from istream. This could put
is in a different state then if this operator>wasn't used. For example.
Say what is waiting is:
123.45And that's all.

Using a pure is >float
"And that's all" would be waiting in the stream. With this function this
way, however, "And that's all" will be thrown away.
Actually, "And" would be thrown away.
>
The way I did it it would only be thrown away if the first character was
#, not as likely an occurance (but adminttedly still could happen).

Other than that, I agree with your assessment. But I don't like putting
the stream in a state that would be different if my function wasn't used.
> if ( in ) {
static std::string const
infRepresentation =
initInfRepresentation() ;
if ( s == infRepresentation ) {
out.value = std::numeric_limits< float >::infinity() ;
} else {
std::istringstream t( s ) ;
t >out.value ;
}
}
return in ;
}

with:

std::string
initInfRepresentation()
{
std::ostringstream t ;
t << std::numeric_limits< float >::infinity() ;
return t.string() ;
}

Actually, I'd go even further, since I'd want to handle at
least positive and negative infinity, and I'd probably make the
comparison case insensitive. But you get the idea.

And of course, regardless of the solution, you have to be aware
that it will break anytime the compiler changes its
representation of infinity. Which in your case seems almost
inevitable, given that the C99 standard requires "[+-]inf" or
"[+-]infinity", and that this requirement will almost certainly
be part of the next version of the C++ standard. So if you want
any kind of portability, you really have to use your MyFloat for
both output and input.


Oct 20 '07 #10
James Kanze <ja*********@gmail.comwrites:
I'm not really sure what the C standard says here---C99
requires, for example, that the string "Infinity" be recognized
and read as a valid float or double, e.g. when matching a "%f"
or "%lf" in a scanf. What happens when it tries to match
"Infinitx" to a "%f". I don't see any way that it could be made
to work so that you don't extract some characters which aren't
then consumed as part of a value. (Remember that "Inf" *is*
also a legitimate float/double value in C. So given the above,
and a scanf format like "%f%s", the float should contain
infinity, and the string "initx". And of course, only one
character push back/look ahead is allowed.) I think that
there's a fundamental problem involved, without any real
solution.
C99 clarified the behavior of fscanf, with the following sentence
and footnote:

An input item is defined as the longest sequence of input
characters which does not exceed any specified field width
and which is, or is a prefix of, a matching input
sequence.242)

242) fscanf pushes back at most one input character onto the
input stream. Therefore, some sequences that are
acceptable to strtod, strtol, etc., are unacceptable to
fscanf.
--
"...dans ce pays-ci il est bon de tuer de temps en temps un amiral
pour encourager les autres."
--Voltaire, _Candide_
Oct 21 '07 #11
"Ben Pfaff" <bl*@cs.stanford.eduwrote in message
news:87************@blp.benpfaff.org...
James Kanze <ja*********@gmail.comwrites:
>I'm not really sure what the C standard says here---C99
requires, for example, that the string "Infinity" be recognized
and read as a valid float or double, e.g. when matching a "%f"
or "%lf" in a scanf. What happens when it tries to match
"Infinitx" to a "%f". I don't see any way that it could be made
to work so that you don't extract some characters which aren't
then consumed as part of a value. (Remember that "Inf" *is*
also a legitimate float/double value in C. So given the above,
and a scanf format like "%f%s", the float should contain
infinity, and the string "initx". And of course, only one
character push back/look ahead is allowed.) I think that
there's a fundamental problem involved, without any real
solution.

C99 clarified the behavior of fscanf, with the following sentence
and footnote:

An input item is defined as the longest sequence of input
characters which does not exceed any specified field width
and which is, or is a prefix of, a matching input
sequence.242)

242) fscanf pushes back at most one input character onto the
input stream. Therefore, some sequences that are
acceptable to strtod, strtol, etc., are unacceptable to
fscanf.
If the standard says that (and you say it does, so I don't doubt it) then I
have no problem with Jame's solution. If the standard disallows some
sequences as unacceptable then I think that using Infinity and leaving the
stream in some undefined state is acceptable (undefined as to how different
compilers may do it when C++Ox comes out).
Oct 22 '07 #12
On Oct 21, 10:38 pm, Ben Pfaff <b...@cs.stanford.eduwrote:
James Kanze <james.ka...@gmail.comwrites:
I'm not really sure what the C standard says here---C99
requires, for example, that the string "Infinity" be recognized
and read as a valid float or double, e.g. when matching a "%f"
or "%lf" in a scanf. What happens when it tries to match
"Infinitx" to a "%f". I don't see any way that it could be made
to work so that you don't extract some characters which aren't
then consumed as part of a value. (Remember that "Inf" *is*
also a legitimate float/double value in C. So given the above,
and a scanf format like "%f%s", the float should contain
infinity, and the string "initx". And of course, only one
character push back/look ahead is allowed.) I think that
there's a fundamental problem involved, without any real
solution.
C99 clarified the behavior of fscanf, with the following sentence
and footnote:
An input item is defined as the longest sequence of input
characters which does not exceed any specified field width
and which is, or is a prefix of, a matching input
sequence.242)
242) fscanf pushes back at most one input character onto the
input stream. Therefore, some sequences that are
acceptable to strtod, strtol, etc., are unacceptable to
fscanf.
I'm not too sure about the footnote (which is non-normative),
but if I understand the phrase correctly, given

sscanf( "Infinitx", "%f%s", &aFloat, aCharBuffer ) ;

the library would put infinity in aFloat, and "x" in
aCharBuffer.

As I said, it's not an easy problem, and there's no good
solution. About the only way to handle this sort of thing
correctly is to read a complete line, then use regular
expressions to match what looks like a floating point, i.e.
something like
"[+-](" "([0-9]+\.[0-9]*([Ee][+-]?[0-9]+)?)"
"|(\.[0-9]+([Ee][+-]?[0-9]+)?)"
"|([0-9]+[Ee][+-]?[0-9]+)"
"|([Ii][Nn][Ff])"
"|([Ii][Nn][Ff][Ii][Nn][Ii][Tt][Yy])"
")"
(The exact syntax will depend on the regular expression class
you use. The above corresponds to my own regular expression
class---which is probably not the one you use, or even should be
using.)

Any reasonable regular expression class will allow you to obtain
the end point of the match; you then use that and the starting
point to create a string which initializes an istringsream,
which then converts the input. This works, of course, only
because you can easily multiply scan in a string; the look-ahead
needed when matching Infinitx, for example, doesn't matter,
because when you do the actual conversion, you'll reread from
the start anyway, and only read the characters which were really
part of the match.

Note that for a seekable input source, you can do this with my
RegularExpression class (which itself works with input
iterators, although there's not often much you can do with the
output in such cases) as well: memorize the current position,
break up the different cases above, try for the match each time,
reseeking to the original position in case of failure; for
either "inf" or "infinity", just store the results; for anything
else, >into a double&.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 22 '07 #13
James Kanze <ja*********@gmail.comwrites:
On Oct 21, 10:38 pm, Ben Pfaff <b...@cs.stanford.eduwrote:
>C99 clarified the behavior of fscanf, with the following sentence
and footnote:
> An input item is defined as the longest sequence of input
characters which does not exceed any specified field width
and which is, or is a prefix of, a matching input
sequence.242)
> 242) fscanf pushes back at most one input character onto the
input stream. Therefore, some sequences that are
acceptable to strtod, strtol, etc., are unacceptable to
fscanf.

I'm not too sure about the footnote (which is non-normative),
but if I understand the phrase correctly, given

sscanf( "Infinitx", "%f%s", &aFloat, aCharBuffer ) ;

the library would put infinity in aFloat, and "x" in
aCharBuffer.
I interpreted this the opposite way: that the library's attempt
to match "Infinity" would fail at 'x' and therefore push back 'x'
and return 0, having consumed "Infinit".

Not that it matters much.
--
Ben Pfaff
http://benpfaff.org
Oct 22 '07 #14
On Oct 22, 5:26 pm, Ben Pfaff <b...@cs.stanford.eduwrote:
James Kanze <james.ka...@gmail.comwrites:
On Oct 21, 10:38 pm, Ben Pfaff <b...@cs.stanford.eduwrote:
C99 clarified the behavior of fscanf, with the following sentence
and footnote:
An input item is defined as the longest sequence of input
characters which does not exceed any specified field width
and which is, or is a prefix of, a matching input
sequence.242)
242) fscanf pushes back at most one input character onto the
input stream. Therefore, some sequences that are
acceptable to strtod, strtol, etc., are unacceptable to
fscanf.
I'm not too sure about the footnote (which is non-normative),
but if I understand the phrase correctly, given
sscanf( "Infinitx", "%f%s", &aFloat, aCharBuffer ) ;
the library would put infinity in aFloat, and "x" in
aCharBuffer.
I interpreted this the opposite way: that the library's attempt
to match "Infinity" would fail at 'x' and therefore push back 'x'
and return 0, having consumed "Infinit".
This is the point where I'm not sure. From the above phrase, it
seems clear that the "%f" specifier would consume "Infinit".
The question is then whether this sequence is an error. There
is a statement (§7.19.6.2/10): "If the input item is not a
matching sequence, the execution of the directive fails: this
condition is a matching failure." But what does it really mean
by "matching sequence"; for "%f", all it says is: "Matches an
optionally signed floating-point number, infinity, or NaN whose
format is the same as expected for the subject sequence of the
strtod function." The strtod function accepts "Infinit" without
problems.

But you're probably right, since in the description of stdtod,
the term "subject sequence" is also used, and given "Infinit" as
input, the "subject sequence" for stdtod is "Inf", which is not
the sequence which was extracted.

This would solve Jim Langston's problem nicely. In his
conversion operator, having gotten past any leading white space
and the sign, he can then do a switch on the next character:
[0-9.], and the usual floating point conversion can be used
(he's already extracted the sign, but that's easy to handle
after the conversion); [Ii], and he advances, extracting the
characters, trying to match "infinity"---if the resulting string
matches "inf" or "infinity", that's the results, otherwise, it's
an error; and for [Nn], he does the same thing for "nan" (not
forgetting the n-char-sequence, if he wants to be strictly
conform with C---but then, he also has to handle the hex
format, since his C++ implementation almost certainly won't).

Just for the fun of it, I whipped up a simple implementation
here. It doesn't handle all of the formatting flags correctly,
and it supposes a C99 compliant math.h, but it should be a good
starting point:

class FloatWithInfIn
{
public:
FloatWithInfIn( float& f )
: myValue( &f )
{
}

friend std::ostream&operator<<( std::ostream& dest,
FloatWithInfIn const& src ) ;
friend std::istream&operator>>( std::istream& source,
FloatWithInfIn const& dest ) ;

private:
float* myValue ;
} ;

class FloatWithInfOut
{
public:
FloatWithInfOut( float const& f )
: myValue( &f )
{
}

friend std::ostream&operator<<( std::ostream& dest,
FloatWithInfOut const& src ) ;

private:
float const* myValue ;
} ;

std::ostream&
outputFloatWithInf(
std::ostream& dest,
float const& value )
{
switch ( fpclassify( value ) ) {
case FP_INFINITE :
if ( value < 0.0 ) {
dest << '-' ;
} else if ( (dest.flags() & std::ios::showpos) != 0 ) {
dest << '+' ;
}
dest << "Infinity" ;
break ;

case FP_NAN :
dest << "NaN" ;
break ;

default :
dest << value ;
break ;
}
return dest ;
}

inline std::ostream&
operator<<(
std::ostream& dest,
FloatWithInfOut const&
value )
{
return outputFloatWithInf( dest, *value.myValue ) ;
}

inline std::ostream&
operator<<(
std::ostream& dest,
FloatWithInfIn const&
value )
{
return outputFloatWithInf( dest, *value.myValue ) ;
}

void
getInfinity(
std::istream& source,
float& dest )
{
static std::string const
inf( "infinity" ) ;
std::ctype< char const&
ctype
= std::use_facet< std::ctype< char >
>( source.getloc() ) ;
std::string extracted ;
std::string::const_iterator
pos = inf.begin() ;
while ( pos != inf.end() && ctype.tolower( source.peek() ) ==
*pos ) {
extracted += ctype.tolower( source.get() ) ;
++ pos ;
}
if ( extracted != "inf" && extracted != "infinity" ) {
source.setstate( std::ios::failbit ) ;
} else {
dest = std::numeric_limits< float >::infinity() ;
}
}

void
getNaN(
std::istream& source,
float& dest )
{
static std::string const
nan( "nan" ) ;
std::ctype< char const&
ctype
= std::use_facet< std::ctype< char >
>( source.getloc() ) ;
std::string extracted ;
std::string::const_iterator
pos = nan.begin() ;
while ( pos != nan.end() && ctype.tolower( source.peek() ) ==
*pos ) {
extracted += ctype.tolower( source.get() ) ;
++ pos ;
}
if ( extracted != "nan" ) {
source.setstate( std::ios::failbit ) ;
} else {
// Or maybe only characters in the basic character set
// should be allowed here.
while ( ctype.is( std::ctype_base::alnum, source.peek() )
|| source.peek() == '_' ) {
source.get() ;
}
dest = std::numeric_limits< float >::quiet_NaN() ;
}
}

std::istream&
operator>>(
std::istream& source,
FloatWithInfIn const&
dest )
{
if ( (source.flags() & std::ios::skipws) != 0 ) {
source >std::ws ;
}
char sign
= ( source.peek() == '-' || source.peek() == '+'
? source.get()
: '+' ) ;
float result = 0.0 ;
switch ( source.peek() ) {
case 'I' :
case 'i' :
getInfinity( source, result ) ;
break ;

case 'N' :
case 'n' :
getNaN( source, result ) ;
break ;

default :
{
// Should use RAII for this, since >can throw...
std::ios::fmtflags flags = source.flags() ;
source.unsetf( std::ios::skipws ) ;
source >result ;
source.flags( flags ) ;
}
break ;
}
if ( source ) {
*dest.myValue = ( sign == '-'
? - result
: result ) ;
}
return source ;
}

FloatWithInfIn
floatWithInf(
float& f )
{
return FloatWithInfIn( f ) ;
}

FloatWithInfOut
floatWithInf(
float const& f )
{
return FloatWithInfOut( f ) ;
}

(Note the use of a function to automatically choose, according
to lvalue-ness and const-ness, whether we can do just output, or
both.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 23 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: franzkowiak | last post by:
Hello, I've read some bytes from a file and just now I can't interpret 4 bytes in this dates like a real value. An extract from my program def l32(c): return ord(c) + (ord(c)<<8) +...
2
by: Goran | last post by:
Hi! I need to convert from a unsigned char array to a float. I don't think i get the right results in the program below. unsigned char array1 = { 0xde, 0xc2, 0x44, 0x23}; //I'm not sure in...
6
by: karthi | last post by:
hi, I need user defined function that converts string to float in c. since the library function atof and strtod occupies large space in my processor memory I can't use it in my code. regards,...
3
by: joshuawilsonster | last post by:
All, I'm hoping you can provide some help. I have opened a temporary file, written to it, verified the correct amount was written, done freopen() for the file to stdin, then try read the...
8
by: bearophileHUGS | last post by:
sys.maxint gives the largest positive integer supported by Python's regular integer type. But maybe such attribute, with few others (they can be called min and max) can be given to int type itself....
1
by: Mark P | last post by:
I have a float value which should be initialized to the minimum allowed value (analogous to -infinity). I discovered today (thank you, unit tests!) that numeric_limits<float>::min() returns a very...
37
by: The87Boy | last post by:
Hey all I have a problem with float I should write a program, where you are getting some numbers from the command-line and try to find the maximum and minimum-values of these numbers. I need...
13
by: swetha | last post by:
HI Every1, I have a problem in reading a binary file. Actually i want a C program which reads in the data from a file which is in binary format and i want to update values in it. The file...
10
by: Steven D'Aprano | last post by:
Is there a simple, elegant way in Python to get the next float from a given one? By "next float", I mean given a float x, I want the smallest float larger than x. Bonus points if I can go in...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.