Re: Stream states questions
On Sep 9, 3:03 am, "Alf P. Steinbach" <al...@start.no> wrote:
* john:
Alf P. Steinbach wrote:
It helps to consider that fail() checks one bit in a set of possible
problem flags: badbit, eofbit and failbit. good() is not a separate
bit, and it's not the inverted fail bit: good() says that /all/ the
three problem bits are zero. Alles in ordnung.
But note that the only way eof() is set automatically, is by failing
to read beyond end of file, which tends to also set the fail bit.
I think that an implementation should understand when the end of file is
encountered. Also I am still learning C++, but doesn't it make sense
that the next read will fail after end of file is encountered?
Sense and sense... There have been long discussions here and in the
moderated group about when exactly eofbit and failbit "should" be set
according to the standard, and when they're actually set with given
implementations.
Do you actually know of implementations which aren't conform
here, or are you just spouting FUD? For the pre-defined types,
this is one of the few things the standard didn't change
compared to the classical iostreams. And I've never seen an
implementation which got it wrong.
That aside, if the streams are set up to generate
exceptions on failure, then you're not guaranteed to avoid exception on
detecting end of file, which makes that feature rather useless.
Have you ever actually tried it? If you're stupid enough to
request an exception on eofbit, you'll get one whenever the
implemention reaches eof. If you ask for one on failbit (not
usually recommended either, but useful in some cases), then
you'll get one on failbit, and only on failbit. And if you ask
for one on badbit (highly recommended), then you'll get one on
badbit, and only on badbit.
Also note that operator void* (used for conversion to logical boolean)
and operator! (ditto) just check the failbit.
In other words, let s be a stream object, then if(s){...} is not the
same as if(s.good()){...}, it's the same as if(!s.fail()){...}. It's
all very perplexing. But, remember, you can just say NO to iostreams.
Also, if a stream's bad() is true, doesn't that imply that
fail() should be true in real world?
I'd think so, but fail() only checks the failbit.
This is completely false.
If failbit were equivalent to eofbit||badbit, then failbit
would be redundant, meaningless.
Failbit is failbit. The function fail() returns (io_status &
(failbit | badbit)) != 0.
So there must be situations where either eofbit doesn't imply
failbit, or badbit doesn't imply failbit. My feelings about
iostreams are such that I have not investigated what those
situations are.
In sum, you're arguing about something you know nothing about.
Also, what about using "if (s.good())" and working with the rest eof(),
fail(), and bad() when the statement becomes false and we want to?
The convention is to use "!s.fail()", expressed as "s".
The C subset functions return NULL in case of errors, we can check
"s.good()" alone too.
The C functions are simple and more efficient but not type safe.
The C functions for formatting are not at all simple; they
require learning an additional, very obtuse language. They are
not type safe, not extendable to user defined types, don't
support logical markup, and can't be used for anything *but*
files and C-style strings. I/O stream is only marginally
simpler than printf when it comes to formatting---the formatting
commands have mnemonic names, but that's about it---, but it
beats the C functions by several orders of magnitude on all
other criteria.
However, the iostreams' formatted input is defined in terms of C fscanf,
and inherits the Undefined Behavior of fscanf. For example, when
inputting hex -- yes, iostreams have built-in Undefined Behavior!
Not just hex. That's something they didn't change from C. But
should have. (In practice, I don't think it's a problem, as
most implementations do the right thing anyway.)
The problem is that in the C and C++ standards there are no
generally good i/o facilities (I think Posix defines the old
Unix open etc. as a generally clean and good but very very
low-level i/o facility).
The problem with the C I/O is that it tries to cover both the
very low (Posix) level, and formatting, in a single abstraction.
For very simple tasks the iostreams are good because they're
relatively safe, thus, well suited to typical beginner's
experimental programs, but bring in e.g. input of hex or
numbers, or text handling like uppercasing, or anything not
very simple, and the complexity, inefficiency, verbosity and
unsafety meet you head on.
It depends on what you're doing. I do agree that where I/O is
concerned, one size does not fit all, and most of my I/O is also
hand written, based on the Posix interface. But using
[io]stringstream for the formatting---I'm not about to rewrite
conversion to/from double.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34