Topic: ifstream behaviour


Author: Kaleb Pederson <kibab@boink.net>
Date: Fri, 26 Oct 2001 17:13:00 GMT
Raw View
Does the actually specify that the implementation be done as such, or is
that just one implementation of the standard?  I was trying to figure out
what the standard said, but I don't quite see how the implementation aspect
you gave relates?  This is what I found (using the draft):

[27.4.6.3]:
....
ios_base& hex(ios_base& str);

  Effects:
Calls str.setf(ios_base::hex, ios_base::basefield).
  Returns:
str.

Forgive me for my ignorance, I'm just trying to get this figured out.  What
you said makes sense, I would just like to know where it states such.  Is
it all defined in the standard?  What section should I look at?

Thanks again.

--Kaleb Pederson

James Russell Kuyper Jr. wrote:
>>
>> Does the standard state that a input stream should automatically take in
>> the following as hex without specifying the hex manipulator.
>>
>> myfile.txt:
>> 0x12
>> 0x33
>> 0xc3
>>
>> code:
>> int val;
>> ifstream infile("myfile.txt");
>> infile >> val;
>> //infile >> hex >> val; // what I believe to be correct
>>
>> Will val end up 0 or 0x12 according to the standard?  I've seen both
>> behaviours on different compilers.
>
> A post condition for initialization of an iso_base() object is that
> flags() must return skipws | dec, so 'infile' starts out in decimal
> mode. Without the 'hex' manipulator, it's still in decimal mode when
> loading in the value of 'val'. You can trace through the C++ standard
> from operator>>() to num_get<>::get(), which in turn cross references
> scanf("%d"), since we're in decimal mode. You have to look at the C
> standard to verify that scanf("%d" ...) is defined in terms of a call to
> strtol() with a base of 10. However, once you've done that, you find
> that strtol() is required to stop after reading in the "0"; it can't
> read in the 'x'. 'val' therefore must get a value of 0.
>
> There's no point in the process whereby the stream can automagically
> convert from decimal mode to hexadecimal mode, so a value of 0x12 is
> wrong.

That's the behavior I was expecting.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Sat, 27 Oct 2001 00:42:35 GMT
Raw View
Kaleb Pederson wrote:
>
> Does the actually specify that the implementation be done as such, or is
> that just one implementation of the standard?  I was trying to figure out

Every statement I made is based entirely upon the standard. I know a lot
more about the standard, than I know about any particular
implementation.

> what the standard said, but I don't quite see how the implementation aspect
> you gave relates?  This is what I found (using the draft):
>
> [27.4.6.3]:
> ....
> ios_base& hex(ios_base& str);
>
>   Effects:
> Calls str.setf(ios_base::hex, ios_base::basefield).
>   Returns:
> str.
>
> Forgive me for my ignorance, I'm just trying to get this figured out.  What
> you said makes sense, I would just like to know where it states such.  Is
> it all defined in the standard?  What section should I look at?

OK. We'll start from there. The behavior of  str.setf(fmtfl, mask) is
defined in 27.4.2.2p6: "Clears mask in flags(), sets fmtfl&mask in
flags()." flags() is the function which, per 27.4.2.2.p1, returns "The
format control information for both input and output."

The meaning of the various format flags is defined in table 83. It
specifies that ios_base::hex is the flag value that means "converts
integer input or generates integer output in hexedecimal base." A
different flag is ios_base::dec, which is defined as meaning "converts
integer input or generates integer output in decimal base." 27.4.2.1.2p1
specifies that fmtflgs is a bitmask type, with dec and hex as two
different elements of the bitmask.

I'll intersperse the rest of my references to the standard in with the
original text, below:

...
> James Russell Kuyper Jr. wrote:
> >>
> >> Does the standard state that a input stream should automatically take in
> >> the following as hex without specifying the hex manipulator.
> >>
> >> myfile.txt:
> >> 0x12
> >> 0x33
> >> 0xc3
> >>
> >> code:
> >> int val;
> >> ifstream infile("myfile.txt");
> >> infile >> val;
> >> //infile >> hex >> val; // what I believe to be correct
> >>
> >> Will val end up 0 or 0x12 according to the standard?  I've seen both
> >> behaviours on different compilers.
> >
> > A post condition for initialization of an iso_base() object is that

This isn't quite correct. I should have specified that I was talking
about basic_istream. The constructor you used for ifstream invokes the
basic_istream(sb) constructor whose effects are described in
27.6.1.1.1p6: "Constructs an object of class basic_istream, assigning
intitial values to the base class by calling basic_io::init(sb)
(27.4.4.1)."

> > flags() must return skipws | dec, so 'infile' starts out in decimal

If you look in 27.4.4.1, you'll find that the post-conditions for
calling ios_base::init(sb) include a requirement that flags() be set to
"skipws | dec". In particular, since 'hex' and 'dec' are distinct
elements of the fmtflags bitmask type, this guarantees that 'hex' is NOT
set by this call.

> > mode. Without the 'hex' manipulator, it's still in decimal mode when
> > loading in the value of 'val'. You can trace through the C++ standard
> > from operator>>() to num_get<>::get(), which in turn cross references

See 27.6.1.2.2 for that connection.

> > scanf("%d"), since we're in decimal mode. ...

22.2.2.1.1 specifies that num_get<>::get() calls do_get().

22.2.2.1.2p4 specifies that do_get() uses "%d". In that same section,
p11 specifies that the way do_get() uses that format string, is to parse
the input string in accordance with the rules for scanf().

> > ... You have to look at the C
> > standard to verify that scanf("%d" ...) is defined in terms of a call to
> > strtol() with a base of 10. However, once you've done that, you find

That would be section 7.19.6.2p12 of the C99 standard. Properly, I
should be referring to the C90 standard, but I don't have a copy of that
standard. In any event, I don't think that any of the differences
between C90 and C99 are relevant here.

> > that strtol() is required to stop after reading in the "0"; it can't

In the C99 standard, 7.20.1.4p3 specifies the what digits strtol()
permits for any given base. For a base of 10, those digits are
"0123456789". A leading "0x" is permitted when the base is 16, but that
doesn't apply when the base is 10. The only way to have 'x' parse as a
valid character is to set the base to 34 or higher.

7.20.1.4p4 specifies that the portion of the input string that is used,
is the "longest initial subsequence of the input string, starting with
the first non-white-space character, that is of the expected form."
Since 'x' doesn't match the expected form, the longest such subsequence
is "0".

> > read in the 'x'. 'val' therefore must get a value of 0.
> >
> > There's no point in the process whereby the stream can automagically
> > convert from decimal mode to hexadecimal mode, so a value of 0x12 is
> > wrong.
>
> That's the behavior I was expecting.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Kaleb Pederson <kibab@boink.net>
Date: Mon, 29 Oct 2001 16:13:14 GMT
Raw View
Thanks.  Your response was exactly what I wanted to know.

--Kaleb

James Kuyper Jr. wrote:

> Kaleb Pederson wrote:
>>
>> Does the actually specify that the implementation be done as such, or is
>> that just one implementation of the standard?  I was trying to figure out
>
> Every statement I made is based entirely upon the standard. I know a lot
> more about the standard, than I know about any particular
> implementation.

<snip>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Kaleb Pederson <stufin02@mail.ewu.edu>
Date: Tue, 23 Oct 2001 21:21:36 GMT
Raw View
Does the standard state that a input stream should automatically take in the
following as hex without specifying the hex manipulator.

myfile.txt:
0x12
0x33
0xc3

code:
int val;
ifstream infile("myfile.txt");
infile >> val;
//infile >> hex >> val; // what I believe to be correct

Will val end up 0 or 0x12 according to the standard?  I've seen both
behaviours on different compilers.

--Kaleb Pederson


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Russell Kuyper Jr." <kuyper@wizard.net>
Date: Wed, 24 Oct 2001 11:48:49 GMT
Raw View
Kaleb Pederson wrote:
>
> Does the standard state that a input stream should automatically take in the
> following as hex without specifying the hex manipulator.
>
> myfile.txt:
> 0x12
> 0x33
> 0xc3
>
> code:
> int val;
> ifstream infile("myfile.txt");
> infile >> val;
> //infile >> hex >> val; // what I believe to be correct
>
> Will val end up 0 or 0x12 according to the standard?  I've seen both
> behaviours on different compilers.

A post condition for initialization of an iso_base() object is that
flags() must return skipws | dec, so 'infile' starts out in decimal
mode. Without the 'hex' manipulator, it's still in decimal mode when
loading in the value of 'val'. You can trace through the C++ standard
from operator>>() to num_get<>::get(), which in turn cross references
scanf("%d"), since we're in decimal mode. You have to look at the C
standard to verify that scanf("%d" ...) is defined in terms of a call to
strtol() with a base of 10. However, once you've done that, you find
that strtol() is required to stop after reading in the "0"; it can't
read in the 'x'. 'val' therefore must get a value of 0.

There's no point in the process whereby the stream can automagically
convert from decimal mode to hexadecimal mode, so a value of 0x12 is
wrong.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]