By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,069 Members | 1,716 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,069 IT Pros & Developers. It's quick & easy.

Stream states questions

P: n/a
I am reading TC++PL3 and in "21.3.3 Stream State", 4 member functions
returning bool are mentioned:
template <class Ch, class Tr= char_traits<Ch
class basic_ios: public ios_base {
public:
// ...
bool good() const; // next operation might succeed
bool eof() const; // end of input seen
bool fail() const; // next operation will fail
bool bad() const; // stream is corrupted

[...]
};

It is also mentioned:

"If the state is good() the previous input operation succeeded. If the
state is good(), the next input operation might succeed; otherwise, it
will fail.

==Applying an input operation to a stream that is not in the good()
state is a null operation as far as the variable being read into is
concerned."

Q1: What does the above mean?
=="If we try to read into a variable v and the operation fails,"

Q2: Does this mean that fail() becomes true after this?
"the value of v should be unchanged (it is unchanged if v is a variable
of one of the types handled by istream or ostream member functions). The
difference between the states fail() and bad() is subtle. When the state
is fail() but not also bad(), it is assumed that the stream is
uncorrupted and that no characters have been lost. When the state is
bad(), all bets are off".
Q3: When !good() is true, is fail() always true?
Sep 8 '07 #1
Share this Question
Share on Google+
33 Replies


P: n/a
* john:
I am reading TC++PL3 and in "21.3.3 Stream State", 4 member functions
returning bool are mentioned:
template <class Ch, class Tr= char_traits<Ch
class basic_ios: public ios_base {
public:
// ...
bool good() const; // next operation might succeed
bool eof() const; // end of input seen
bool fail() const; // next operation will fail
bool bad() const; // stream is corrupted

[...]
};

It is also mentioned:

"If the state is good() the previous input operation succeeded. If the
state is good(), the next input operation might succeed; otherwise, it
will fail.

==Applying an input operation to a stream that is not in the good()
state is a null operation as far as the variable being read into is
concerned."

Q1: What does the above mean?
It means that in an ungood state, stream input and output operations do
nothing at all (except possibly throwing exceptions, if you have turned
that on).
=="If we try to read into a variable v and the operation fails,"

Q2: Does this mean that fail() becomes true after this?
Yes.

"the value of v should be unchanged (it is unchanged if v is a variable
of one of the types handled by istream or ostream member functions). The
difference between the states fail() and bad() is subtle. When the state
is fail() but not also bad(), it is assumed that the stream is
uncorrupted and that no characters have been lost. When the state is
bad(), all bets are off".
Q3: When !good() is true, is fail() always true?
No.

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.

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.

Cheers, & hth.,

- Alf
Sep 8 '07 #2

P: n/a
On 2007-09-08 15:39, john wrote:
I am reading TC++PL3 and in "21.3.3 Stream State", 4 member functions
returning bool are mentioned:
template <class Ch, class Tr= char_traits<Ch
class basic_ios: public ios_base {
public:
// ...
bool good() const; // next operation might succeed
bool eof() const; // end of input seen
bool fail() const; // next operation will fail
bool bad() const; // stream is corrupted

[...]
};

It is also mentioned:

"If the state is good() the previous input operation succeeded. If the
state is good(), the next input operation might succeed; otherwise, it
will fail.

==Applying an input operation to a stream that is not in the good()
state is a null operation as far as the variable being read into is
concerned."

Q1: What does the above mean?
It means that if you try to read from a file into a variable 'value' and
good() == false the data in 'value' will not be changed.
=="If we try to read into a variable v and the operation fails,"

Q2: Does this mean that fail() becomes true after this?
Yes.
"the value of v should be unchanged (it is unchanged if v is a variable
of one of the types handled by istream or ostream member functions). The
difference between the states fail() and bad() is subtle. When the state
is fail() but not also bad(), it is assumed that the stream is
uncorrupted and that no characters have been lost. When the state is
bad(), all bets are off".
Q3: When !good() is true, is fail() always true?
Yes, there are three flags associated with the state of the stream, eof,
fail, and bad. If none of those are set then good() == true.

--
Erik Wikström
Sep 8 '07 #3

P: n/a
On 2007-09-08 16:17, Erik Wikström wrote:
On 2007-09-08 15:39, john wrote:
>I am reading TC++PL3 and in "21.3.3 Stream State", 4 member functions
returning bool are mentioned:
template <class Ch, class Tr= char_traits<Ch
class basic_ios: public ios_base {
public:
// ...
bool good() const; // next operation might succeed
bool eof() const; // end of input seen
bool fail() const; // next operation will fail
bool bad() const; // stream is corrupted

[...]
};

It is also mentioned:

"If the state is good() the previous input operation succeeded. If the
state is good(), the next input operation might succeed; otherwise, it
will fail.

==Applying an input operation to a stream that is not in the good()
state is a null operation as far as the variable being read into is
concerned."

Q1: What does the above mean?

It means that if you try to read from a file into a variable 'value' and
good() == false the data in 'value' will not be changed.
>=="If we try to read into a variable v and the operation fails,"

Q2: Does this mean that fail() becomes true after this?

Yes.
>"the value of v should be unchanged (it is unchanged if v is a variable
of one of the types handled by istream or ostream member functions). The
difference between the states fail() and bad() is subtle. When the state
is fail() but not also bad(), it is assumed that the stream is
uncorrupted and that no characters have been lost. When the state is
bad(), all bets are off".
Q3: When !good() is true, is fail() always true?

Yes, there are three flags associated with the state of the stream, eof,
fail, and bad. If none of those are set then good() == true.
Correction, the above sentence should be "No, there are three flags...".

--
Erik Wikström
Sep 8 '07 #4

P: n/a
Alf P. Steinbach wrote:
>
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.
So, do you suggest going back to the C subset fopen(), etc?
Sep 8 '07 #5

P: n/a
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?

>
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?
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 C subset functions return NULL in case of errors, we can check
"s.good()" alone too.
Sep 8 '07 #6

P: n/a
On Sat, 08 Sep 2007 23:33:10 +0300, john <jo**@no.spamwrote:
>Alf P. Steinbach wrote:
>It's
all very perplexing. But, remember, you can just say NO to iostreams.

So, do you suggest going back to the C subset fopen(), etc?
Have you found one real advantage of iostreams over the 'C subset'?
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Sep 8 '07 #7

P: n/a
Roland Pibinger wrote:
>
Have you found one real advantage of iostreams over the 'C subset'?

I am still reading TC++PL3, but so far I liked istreams and ostreams.
For example, the simplicity of getting whitespace separated strings:
string s;

do
{
cin>>s;

// ...
}while(cin);
or even this:

char v[4];

cin.width(4);

cin>v;

(it reads 3 characters max and adds 0 in the end).
Isn't this more high level and elegant than the C subset I/O facilities?
Sep 8 '07 #8

P: n/a
In article <1189289680.714224@athprx04>, jo**@no.spam says...

[ ... ]
I am still reading TC++PL3, but so far I liked istreams and ostreams.
For example, the simplicity of getting whitespace separated strings:
string s;

do
{
cin>>s;
scanf("%s", s);

does essentially the same thing, from the viewpoint of the stream. The
one real difference is attributable to the string -- that it resizes
itself as needed to accomodate the data being read.
or even this:

char v[4];

cin.width(4);

cin>v;
scanf("%3s", s);

or:

fgets(buffer, 4, stdin);

Don't get me wrong: I'm not arguing that iostreams lack advantages --
only that the things you've cited don't (directly) show much advantage
for them.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 8 '07 #9

P: n/a
Jerry Coffin wrote:
>
>string s;

do
{
cin>>s;

scanf("%s", s);

Yes, but this leaves room for overflow, while C++ new I/O facilities
together with the other high level facilities are more elegant, safe and
convenient (as far as I have read until now).

does essentially the same thing, from the viewpoint of the stream. The
one real difference is attributable to the string -- that it resizes
itself as needed to accomodate the data being read.
Yes, which is nice, safe and convenient. If string gets more than it can
accommodate it throws a length_error exception. No way for overflow here.

>
>or even this:

char v[4];

cin.width(4);

cin>v;

scanf("%3s", s);

or:

fgets(buffer, 4, stdin);

Don't get me wrong: I'm not arguing that iostreams lack advantages --
only that the things you've cited don't (directly) show much advantage
for them.

Well, the cin way looks more high level and convenient to me.
Sep 8 '07 #10

P: n/a
* 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. 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.

>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. If failbit were
equivalent to eofbit||badbit, then failbit would be redundant,
meaningless. 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.
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.
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!

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).

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.
Cheers, and sorry I don't have any more positive advice,

- Alf
Sep 9 '07 #11

P: n/a
Alf P. Steinbach wrote:
>

The C functions are simple and more efficient but not type safe.
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!
I think istream can be defined to input hex and other bases (there is a
flag basefield that is mentioned in later pages from where I am now). In
TC++PL3, in what I have read it is mentioned:

"The format expected for input is specified by the current locale
(21.7). By default, the bool values true and false are represented by 1
and 0, respectively. Integers must be decimal and floating-point numbers
of the form used to write them in a C++ program. By setting basefield
(21.4.2), it is possible to read 0123 as an octal number with the
decimal value 83 and 0xff as a hexadecimal number with the decimal value
255. The format used to read pointers is completely
implementation-dependent (have a look to see what your implementation
does)".

>
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).

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.
I think you gotta have a look at TC++PL3. Uppercasing is easy by using
toupper().
Sep 9 '07 #12

P: n/a
On 2007-09-09 03:03, Alf P. Steinbach 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. 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.

>>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. If failbit were
equivalent to eofbit||badbit, then failbit would be redundant,
meaningless. 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.
A rare day when I get to correct Alf, but fail() returns true if either
failbit or badbid is set. I'm not sure however, if badbit can be set
without failbit being set.
The C functions are simple and more efficient but not type safe.
It is my hope that using variadic templates will allow rewriting many of
the C IO-functions in a typesafe manner, Douglas Gregor hinted at this
in N2087 (A Brief Introduction to Variadic Templates).

--
Erik Wikström
Sep 9 '07 #13

P: n/a
* Erik Wikström:
On 2007-09-09 03:03, Alf P. Steinbach wrote:
>>
... but fail() only checks the failbit. If failbit were
equivalent to eofbit||badbit, then failbit would be redundant,
meaningless. 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.

A rare day when I get to correct Alf, but fail() returns true if either
failbit or badbid is set.
Mea culpa. Sorry. There is a note (in the standard) explaining that it
does that because of historical practice.

I'm not sure however, if badbit can be set
without failbit being set.
I'm not sure either. ;-)

Cheers, & thanks,

- Alf

Sep 9 '07 #14

P: n/a
* john:
Alf P. Steinbach wrote:
>>

The C functions are simple and more efficient but not type safe.
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!

I think istream can be defined to input hex and other bases (there is a
flag basefield that is mentioned in later pages from where I am now). In
TC++PL3, in what I have read it is mentioned:

"The format expected for input is specified by the current locale
(21.7). By default, the bool values true and false are represented by 1
and 0, respectively. Integers must be decimal and floating-point numbers
of the form used to write them in a C++ program. By setting basefield
(21.4.2), it is possible to read 0123 as an octal number with the
decimal value 83 and 0xff as a hexadecimal number with the decimal value
255. The format used to read pointers is completely
implementation-dependent (have a look to see what your implementation
does)".
Yes, it can do that.

The point is that if the user types something unexpected, the result is
(by the definitional reliance on fscanf) Undefined Behavior -- which
you can try out easily on e.g. older Visual C++ compilers, and perhaps
even 8.0.

UB on invalid input is just not the thing one would expect from a "type
safe" i/o facility.

>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).

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.

I think you gotta have a look at TC++PL3. Uppercasing is easy by using
toupper().
Uppercasing is one of the thorniest problems in data processing, in
general, because natural languages have all sorts of irrational rules.

But it is of course easy if you restrict yourself to the English
alphabet, /and/ is happy with using only the C library.

More general C++ standard library compatible uppercasing functionality
is provided by e.g. the Boost library.
Cheers, & hth.,

- Alf
Sep 9 '07 #15

P: n/a
Alf P. Steinbach wrote:
>

UB on invalid input is just not the thing one would expect from a "type
safe" i/o facility.
I suppose we do not have undefined behaviour since we have the
istream/ostream::good(),fail(),bad(),eof() etc facilities. So if an
hexadecimal is expected and a decimal is entered, we get

cin.good()==false.
>I think you gotta have a look at TC++PL3. Uppercasing is easy by using
toupper().

Uppercasing is one of the thorniest problems in data processing, in
general, because natural languages have all sorts of irrational rules.

Yes, however we have wchar_t and its facilities. In most systems
supporting Unicode, wchar_t is Unicode character type so in
<cwctype>/<wctype.hwe have towupper() which does the job.

Sep 9 '07 #16

P: n/a
Erik Wikström wrote:
>
A rare day when I get to correct Alf, but fail() returns true if either
failbit or badbid is set. I'm not sure however, if badbit can be set
without failbit being set.
TC++PL3 mentions: "When the state is fail() but not also bad(), it is
assumed that the stream is uncorrupted and that no characters have been
lost. When the state is bad(), all bets are off".

Based on this, I assume that fail() checks failbit only. So is this
TC++PL3 errata or something?
Sep 9 '07 #17

P: n/a
* john:
Alf P. Steinbach wrote:
>>

UB on invalid input is just not the thing one would expect from a
"type safe" i/o facility.

I suppose we do not have undefined behaviour since we have the
istream/ostream::good(),fail(),bad(),eof() etc facilities. So if an
hexadecimal is expected and a decimal is entered, we get

cin.good()==false.
Sorry, your supposition is incorrect. First, a decimal number
specification is also valid as a hexadecimal one. Second, there is UB.

>>I think you gotta have a look at TC++PL3. Uppercasing is easy by
using toupper().

Uppercasing is one of the thorniest problems in data processing, in
general, because natural languages have all sorts of irrational rules.


Yes, however we have wchar_t and its facilities. In most systems
supporting Unicode, wchar_t is Unicode character type so in
<cwctype>/<wctype.hwe have towupper() which does the job.
Sorry, again (although it depends on what you mean by "does the job"):
for the general case that function has too little information to go on,
and has a too limited signature to be able to do the job in principle.

As an example, uppercase of German "ß" (small letter sharp s) is "SS"
which, as you may note, consists of /two/ characters, whereas towupper
is a function that at most can produces /one/ character. With at least
one implementation it just produces "ß" as uppercase. And ß" is lowercase.

Cheers, & hth.,

- Alf
Sep 9 '07 #18

P: n/a
On 2007-09-09 15:11, john wrote:
Erik Wikström wrote:
>>
>A rare day when I get to correct Alf, but fail() returns true if either
failbit or badbid is set. I'm not sure however, if badbit can be set
without failbit being set.

TC++PL3 mentions: "When the state is fail() but not also bad(), it is
assumed that the stream is uncorrupted and that no characters have been
lost. When the state is bad(), all bets are off".

Based on this, I assume that fail() checks failbit only. So is this
TC++PL3 errata or something?
Nope, it is just you interpretation that is wrong. Note the word *also*,
which says that the failbit can be set without badbit, but tells us
nothing about the reverse.

--
Erik Wikström
Sep 9 '07 #19

P: n/a
Alf P. Steinbach wrote:
>
>I suppose we do not have undefined behaviour since we have the
istream/ostream::good(),fail(),bad(),eof() etc facilities. So if an
hexadecimal is expected and a decimal is entered, we get

cin.good()==false.

Sorry, your supposition is incorrect. First, a decimal number
specification is also valid as a hexadecimal one. Second, there is UB.
In my system (CentOS, GCC and Anjuta) the code:

#include <iostream>

int main()
{
using namespace std;

int x;

cin>x;

cout<< boolalpha<< cin.good()<< endl;

cin>x;

cout<< boolalpha<< cin.good()<< endl;

if( cin.good() )
cout<< "x= "<< x<< endl;
}

At first I enter a decimal, in second an hexadecimal (while decimal is
expected):
[john@localhost src]$ ./foobar-cpp
1
true
0xff
true
x= 0

[john@localhost src]$

It looks like it reads the first digital character.
[john@localhost src]$ ./foobar-cpp
1
true
xff
false

[john@localhost src]$

I think there is no more space for UB, than the C subset I/O.
>Yes, however we have wchar_t and its facilities. In most systems
supporting Unicode, wchar_t is Unicode character type so in
<cwctype>/<wctype.hwe have towupper() which does the job.

Sorry, again (although it depends on what you mean by "does the job"):
for the general case that function has too little information to go on,
and has a too limited signature to be able to do the job in principle.

As an example, uppercase of German "ß" (small letter sharp s) is "SS"
which, as you may note, consists of /two/ characters, whereas towupper
is a function that at most can produces /one/ character. With at least
one implementation it just produces "ß" as uppercase. And ß" is lowercase.

OK. In any case the C subset I/O doesn't provide something more than
itself, and as far as I know iostreams do not provide something
equivalent (and more inferior) either.
Sep 9 '07 #20

P: n/a
Erik Wikström wrote:
>
>Based on this, I assume that fail() checks failbit only. So is this
TC++PL3 errata or something?

Nope, it is just you interpretation that is wrong. Note the word *also*,
which says that the failbit can be set without badbit, but tells us
nothing about the reverse.
OK, thanks for the clarification.

In this way, checking an istream in the style "while(cin)" is equivalent
to "while(cin.rdstate() ^ istream::badbit || cin.rdstate() ^
istream::failbit)", that is if both are inactive.

It is more broad than Alf said.

Sep 9 '07 #21

P: n/a
john wrote:
>
Correction:

Erik Wikström wrote:
>>
>>Based on this, I assume that fail() checks failbit only. So is this
TC++PL3 errata or something?

Nope, it is just you interpretation that is wrong. Note the word
*also*, which says that the failbit can be set without badbit, but
tells us nothing about the reverse.

OK, thanks for the clarification.

In this way, checking an istream in the style "while(cin)" is equivalent
== to "while(cin.rdstate() ^ istream::badbit && cin.rdstate() ^
istream::failbit)", that is if both are inactive.

It is more broad than Alf said.
Sep 9 '07 #22

P: n/a
On 2007-09-09 16:58, john wrote:
john wrote:
>>

Correction:

>Erik Wikström wrote:
>>>
Based on this, I assume that fail() checks failbit only. So is this
TC++PL3 errata or something?

Nope, it is just you interpretation that is wrong. Note the word
*also*, which says that the failbit can be set without badbit, but
tells us nothing about the reverse.

OK, thanks for the clarification.

In this way, checking an istream in the style "while(cin)" is equivalent

== to "while(cin.rdstate() ^ istream::badbit && cin.rdstate() ^
>istream::failbit)", that is if both are inactive.

It is more broad than Alf said.
Actually, as Alf said in his reply to the OP, "while(cin)" is equivalent
to "while(!cin.fail())", or as the standard puts it: "If fail() then a
null pointer; otherwise a non-null pointer to indicate success."

--
Erik Wikström
Sep 9 '07 #23

P: n/a
On Sep 8, 4:02 pm, "Alf P. Steinbach" <al...@start.nowrote:
* john:
I am reading TC++PL3 and in "21.3.3 Stream State", 4 member functions
returning bool are mentioned:
template <class Ch, class Tr= char_traits<Ch
class basic_ios: public ios_base {
public:
// ...
bool good() const; // next operation might succeed
bool eof() const; // end of input seen
bool fail() const; // next operation will fail
bool bad() const; // stream is corrupted
[...]
};
It is also mentioned:
"If the state is good() the previous input operation succeeded. If the
state is good(), the next input operation might succeed; otherwise, it
will fail.
==Applying an input operation to a stream that is not in the good()
state is a null operation as far as the variable being read into is
concerned."
Q1: What does the above mean?
It means that in an ungood state, stream input and output
operations do nothing at all (except possibly throwing
exceptions, if you have turned that on).
It might also change the state.

I'm not sure I actually like the way the statement is formulated
(supposing it was quoted correctly, and there is no missing
context). While it's true that if good() is true, the previous
operation succeeded, it's not necessarily true that if good() is
false, it failed. When good() returns true, it tells you
nothing, and when it returns false, it only tells you that the
next operation will fail; it says nothing about the preceding
operation. (And in the C++ I/O model, it is the results of the
preceding operation which interest us.)
=="If we try to read into a variable v and the operation fails,"
Q2: Does this mean that fail() becomes true after this?
Yes.
"the value of v should be unchanged (it is unchanged if v is a variable
of one of the types handled by istream or ostream member functions). The
difference between the states fail() and bad() is subtle. When the state
is fail() but not also bad(), it is assumed that the stream is
uncorrupted and that no characters have been lost. When the state is
bad(), all bets are off".
Q3: When !good() is true, is fail() always true?
No.
It helps to consider that fail() checks one bit in a set of possible
problem flags: badbit, eofbit and failbit.
Fail() checks both badbit and failbit. Bad() checks only
badbit, eof() only eofbit(), and good() all three.
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.
The problem is that even if eofbit is true, it's still alles in
Ordnung. Until the next attempt to read something.
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.
There's a very important difference. Any time the istream sees
an EOF, it sets eofbit. Including when looking ahead to find
the end of an input element. Thus, if the stream contains just
"123" (no final newline), and you use >to input into an int,
eofbit will be set (and eof() will return true, and good()
false), even though the input succeeded, fail() returns false,
because the parser for int must read ahead until the first
character which is not part of the int.
Also note that operator void* (used for conversion to logical
boolean) and operator! (ditto) just check the failbit.
No, they check fail(), which checks failbit and badbit.
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.
And what do you use in their place? <stdio.his broken to the
point of being unusable. The overal abstraction for iostream
isn't really that bad---it's better than any of the alternatives
I've seen proposed, at any rate. It is regrettable that the
state functions are so poorly named (and in fact, that more
state information isn't always available), but that's a minor
detail.

--
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

Sep 9 '07 #24

P: n/a
On Sep 8, 11:47 pm, rpbg...@yahoo.com (Roland Pibinger) wrote:
On Sat, 08 Sep 2007 23:33:10 +0300, john <j...@no.spamwrote:
Alf P. Steinbach wrote:
It's
all very perplexing. But, remember, you can just say NO to iostreams.
So, do you suggest going back to the C subset fopen(), etc?
Have you found one real advantage of iostreams over the 'C subset'?
They work, they're usable, and they're relatively reliable.
None of which is true for the C subset.

--
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

Sep 9 '07 #25

P: n/a
On Sep 9, 3:00 pm, john <j...@no.spamwrote:
Alf P. Steinbach wrote:
UB on invalid input is just not the thing one would expect from a "type
safe" i/o facility.
I suppose we do not have undefined behaviour since we have the
istream/ostream::good(),fail(),bad(),eof() etc facilities. So if an
hexadecimal is expected and a decimal is entered, we get
cin.good()==false.
And how is the system to know that 10 was meant to be decimal,
and not hexadecimal?

The problem Alf is referring to is the fact that undefined
behavior occurs if the value read is too large to fit into the
target type.
I think you gotta have a look at TC++PL3. Uppercasing is easy by using
toupper().
Uppercasing is one of the thorniest problems in data processing, in
general, because natural languages have all sorts of irrational rules.
Yes, however we have wchar_t and its facilities. In most systems
supporting Unicode, wchar_t is Unicode character type so in
<cwctype>/<wctype.hwe have towupper() which does the job.
I suggest you find out a bit more about case handling before
making such blanket statements. It's a non-trivial operation,
and requires considerable thought and effort to be handled
correctly in the general case.

--
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

Sep 9 '07 #26

P: n/a
On Sep 9, 4:16 pm, "Alf P. Steinbach" <al...@start.nowrote:

[...]
As an example, uppercase of German "ß" (small letter sharp s) is "SS"
which, as you may note, consists of /two/ characters, whereas towupper
is a function that at most can produces /one/ character. With at least
one implementation it just produces "ß" as uppercase. And ß" is lowercase.
In every implementation I've seen, it produces "ß". I think
that this is required, in fact. According to the standard,
std::ctype::toupper returns "the corresponding upper-case
character if it is known to exist, or its argument if not."

--
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

Sep 9 '07 #27

P: n/a
On Sep 9, 12:46 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2007-09-09 03:03, Alf P. Steinbach wrote:
I'd think so, but fail() only checks the failbit. If failbit were
equivalent to eofbit||badbit, then failbit would be redundant,
meaningless. 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.
A rare day when I get to correct Alf, but fail() returns true if either
failbit or badbid is set. I'm not sure however, if badbit can be set
without failbit being set.
It's rather the opposite: there is no case when both should be
set. Generally speaking, badbit represents a real hardware
error, failbit represents either a formatting error or a lack of
data (end of file before having started reading the element).

--
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

Sep 9 '07 #28

P: n/a
* James Kanze:
On Sep 9, 3:03 am, "Alf P. Steinbach" <al...@start.nowrote:
>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.
Ah, language, James, language! I don't know where you got the idea that
I might be stupid. After all, I'm pretty smart. :-)

And of course I've tried it, and you do risk getting an exception on
(first detection of) EOF if you ask for exceptions on failbit. And if
you only ask for exceptions on badbit, you're not guaranteed to get an
exception when an input operation fails to read what you requested[1],
so that's not exceptions on failure. In short, to use your chosen
descriptive word here, it's "stupid", and you're wrong.

Treating detection of EOF as an exceptional failure (and more generally,
coupling detection of EOF to failure to read what's asked for) is very
ungood design. For that matter, sticky EOF state, hidden modes, silent
failure, etc. etc. associated with this particular little aspect of
iostreams, it's so bad that even "badbit" and "failbit" don't adequately
convey how badly it fails.
>>>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.
Erik Wikström corrected that misimpression earlier, else-thread. Now
you're so upset that you're harking on and on about it, as if it
mattered anything at all, and as if it was an additional point every
time you mention it... You're grasping at a straw here, by going to
personal attack and drawing the grandest conclusions from nothing,

[snip]
In sum, you're arguing about something you know nothing about.

Cheers, & hth.,

- Alf
Notes:
[1] E.g. this program

<code>
#include <iostream>
#include <ostream>

#include <cstddef>
#include <stdexcept>
#include <string>

void cppMain()
{
using namespace std;
cin.exceptions( ios::badbit ); // James' recommendation.

// Are we guaranteed that non-throwing input = successful input?
while( !cin.fail() )
{
int x;
cin >x;
cout << "* " << x << endl;
}
}

int main()
{
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( std::exception const& x )
{
std::cerr << "!" << x.what() << std::endl;
return EXIT_FAILURE;
}
}
</code>

produces with MSVC 7.1 and input 666 plus next line EOF,

<output>
666
* 666
^Z
* 666
</output>

where the last line exemplifies the statement that referred to this note.
Sep 9 '07 #29

P: n/a
On Sep 10, 12:56 am, "Alf P. Steinbach" <al...@start.nowrote:
* James Kanze:
On Sep 9, 3:03 am, "Alf P. Steinbach" <al...@start.nowrote:
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.
Ah, language, James, language! I don't know where you got the
idea that I might be stupid. After all, I'm pretty smart. :-)
I know you are. But even smart people don't know everything.
The smartest, of course, know enough to know what they don't
know. That's why I don't understand your posting.
And of course I've tried it, and you do risk getting an
exception on (first detection of) EOF if you ask for
exceptions on failbit.
With what compiler? I've never encountered this.
And if
you only ask for exceptions on badbit, you're not guaranteed to get an
exception when an input operation fails to read what you requested[1],
so that's not exceptions on failure. In short, to use your chosen
descriptive word here, it's "stupid", and you're wrong.
No I'm not. The exception mask is exactly identical with the
bits: if you ask for an exception on eofbit, you get one on
eofbit (which is totally useless). If you ask for one on
failbit, then you get one on failbit, and only on failbit. (At
least according to the standard---I've obviously not tried every
library in existance. But it works correctly with the g++
implementation of the library, Rogue Wave's, the STL port and
Dinkumware.)
Treating detection of EOF as an exceptional failure (and more
generally, coupling detection of EOF to failure to read what's
asked for) is very ungood design.
I'm not particularly happy about the fact that you cannot easily
distinguish between failure due to end of file, and failure due
to a format error. Regretfully, the old C style I/O isn't
particulary good about this either.
For that matter, sticky EOF state, hidden modes, silent
failure, etc. etc. associated with this particular little
aspect of iostreams, it's so bad that even "badbit" and
"failbit" don't adequately convey how badly it fails.
The sticky error states are a good point (and also inherited
from the C I/O). Under Unix, for various reasons, EOF state
also has to be sticky at some level; I agree that it would have
been perhaps better to say that if filebuf::sgetc() returns EOF
once, it must return EOF always. (This is not totally without
problems, either, but problems which could potentially be solved
by addiing some state manipulation functions to streambuf.)

There is a real, very fundamental, problem with both C and C++
I/O: they are too Unix centric.
[1] E.g. this program
<code>
#include <iostream>
#include <ostream>

#include <cstddef>
#include <stdexcept>
#include <string>
void cppMain()
{
using namespace std;
cin.exceptions( ios::badbit ); // James' recommendation.
// Are we guaranteed that non-throwing input = successful input?
while( !cin.fail() )
{
int x;
cin >x;
cout << "* " << x << endl;
}
Obviously not. If you have a hard error (a disk read error, for
example), I would expect an exception. But only if you have a
hard error. (And whether the system detects such errors is a
quality of implementation issue---I think most Unix based
systems would just treat them as end of file, in the great Unix
tradition of sticking your head in the sand.)

You don't want an exception for the failure errors. If the
failure is due to no more data, it's a "normal" condition, and
if it is due to a format error in the file, it's also an
"expected" condition, and not exceptional---typically, too, it
will be handled locally by outputting an error message, then
clearing the error status, and skipping ahead to some
resynchronization point where you can resume reading the file.
Usually, the only time you want an exception is when a really
exceptional condition occurs: a hardware read error from the
disk, for example.

Exceptionally, of course, you may feel sure enough about the
format of the file to decide that a format error *is* an
exceptional condition. (If, for example, it is, or should be, a
file written by your program sometime earlier.) You know, for
example, that it contains three integers. In such cases, it
might make sense to request exceptions for failbit as well. And
of course, you will get the exception if the file doesn't
actually contain three integer values.
}
If your claim is simply that the error states don't provide as
much information as they should, then I totally agree, although
the C++ I/O is slightly better than the C in this regard. (C++
does allow disinguishing between hardware errors and the others,
which is usually fairly important. In most cases, it's also
possible to distinguish between format errors and a real eof,
but it does require more programming than it should, and it
isn't 100% reliable.)

--
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

Sep 10 '07 #30

P: n/a
Alf P. Steinbach wrote:
>

produces with MSVC 7.1 and input 666 plus next line EOF,

<output>
666
* 666
^Z
* 666
</output>

This is very bad. It is good for you to try and avoid such references.
Sep 10 '07 #31

P: n/a
* john:
Alf P. Steinbach wrote:
>>

produces with MSVC 7.1 and input 666 plus next line EOF,

<output>
666
* 666
^Z
* 666
</output>


This is very bad. It is good for you to try and avoid such references.
No, it isn't very bad, it's an illustration of a minor technical point
in a discussion.

Cheers, & hth.,

- Alf
Sep 10 '07 #32

P: n/a
Alf P. Steinbach wrote:
>
* john:
>Alf P. Steinbach wrote:
>>>

produces with MSVC 7.1 and input 666 plus next line EOF,

<output>
666
* 666
^Z
* 666
</output>


This is very bad. It is good for you to try and avoid such references.

No, it isn't very bad, it's an illustration of a minor technical point
in a discussion.

It is very bad. It is the number of the antichrist, rather than a
randomly chosen number for illustration purposes.

We should try to avoid making our Father Jesus Christ Who Loves us
without limits, to be sorry about our actions.
Sep 10 '07 #33

P: n/a
On Sep 10, 8:16 am, john <j...@no.spamwrote:
Alf P. Steinbach wrote:
* john:
Alf P. Steinbach wrote:
>produces with MSVC 7.1 and input 666 plus next line EOF,
><output>
666
* 666
^Z
* 666
</output>
This is very bad. It is good for you to try and avoid such references.
No, it isn't very bad, it's an illustration of a minor technical point
in a discussion.

It is very bad. It is the number of the antichrist, rather than a
randomly chosen number for illustration purposes.

We should try to avoid making our Father Jesus Christ Who Loves us
without limits, to be sorry about our actions.
oh no!
NOT HERE, please!

please, leave and take this f***ing Jesus Christ with you that loves
us without limits and transforms their disciples into boring assholes

Sep 10 '07 #34

This discussion thread is closed

Replies have been disabled for this discussion.