Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

cin.fail() , ignore() , clear()...

1,325 views
Skip to first unread message

TheGunslinger

unread,
Feb 7, 2011, 2:54:39 PM2/7/11
to

I have a programming assignment that is to utilize (a class in
OOP/C++)

cin.fail()
cin.ignore()
cin.clear()

These are to be used within a do/while if(cin.fail()) conditional.

In my 2010 C++ reference, I could only find a reference to one of
these functions.

Whereas in my 2000 reference, I can find documentation for all 3 and
a couple more.

My questions are:
1) Are these functions currently deprecated under the 2003 ISO
Standard and the ISO Draft to be confirmed and standardized this year?

2) I can find numerous references to cin.fail() within the ISO draft
(I d/l'd a copy for reference.), BUT none for cin.clear() and
cin.ignore()??? Are these other functions being carried over strictly
for portability and compatibility issues for legacy program support?

BTW, the reference texts I've mentioned are:

a) Absolute C++, 4th Edition, Savitch, 2010

b) Standard C++ Bible, Stevens and Walnum, 2000

TIA,

MJR


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

ptyxs

unread,
Feb 8, 2011, 5:39:12 AM2/8/11
to
On Feb 7, 8:54 pm, TheGunslinger <mikiesrunsbaal....@sbcglobal.net>
wrote:

> I have a programming assignment that is to utilize (a class in
> OOP/C++)
>
> cin.fail()
> cin.ignore()
> cin.clear()
>
> These are to be used within a do/while if(cin.fail()) conditional.
>
> In my 2010 C++ reference, I could only find a reference to one of
> these functions.
>
> Whereas in my 2000 reference, I can find documentation for all 3 and
> a couple more.
>
> My questions are:
> 1) Are these functions currently deprecated under the 2003 ISO
> Standard and the ISO Draft to be confirmed and standardized this year?
>
> 2) I can find numerous references to cin.fail() within the ISO draft
> (I d/l'd a copy for reference.), BUT none for cin.clear() and
> cin.ignore()??? Are these other functions being carried over strictly
> for portability and compatibility issues for legacy program support?
>
> BTW, the reference texts I've mentioned are:
>
> a) Absolute C++, 4th Edition, Savitch, 2010
>
> b) Standard C++ Bible, Stevens and Walnum, 2000
>
> TIA,

{ quoted signature and banner removed - please do it yourself. -mod }


And for cin.ignore(), have a look here :

http://www.cplusplus.com/reference/iostream/istream/ignore/

ptyxs

unread,
Feb 8, 2011, 5:39:03 AM2/8/11
to
On Feb 7, 8:54 pm, TheGunslinger <mikiesrunsbaal....@sbcglobal.net>
wrote:
> I have a programming assignment that is to utilize (a class in
> OOP/C++)
>
> cin.fail()
> cin.ignore()
> cin.clear()
>
> These are to be used within a do/while if(cin.fail()) conditional.
>
> In my 2010 C++ reference, I could only find a reference to one of
> these functions.
>
> Whereas in my 2000 reference, I can find documentation for all 3 and
> a couple more.
>
> My questions are:
> 1) Are these functions currently deprecated under the 2003 ISO
> Standard and the ISO Draft to be confirmed and standardized this year?
>
> 2) I can find numerous references to cin.fail() within the ISO draft
> (I d/l'd a copy for reference.), BUT none for cin.clear() and
> cin.ignore()??? Are these other functions being carried over strictly
> for portability and compatibility issues for legacy program support?
>
> BTW, the reference texts I've mentioned are:
>
> a) Absolute C++, 4th Edition, Savitch, 2010
>
> b) Standard C++ Bible, Stevens and Walnum, 2000
>
> TIA,

{ quoted signature and banner removed - please do it yourself. -mod }


>From Programming Principles and Practise Using C++ by Bjarne
Stroustrup (probably the best book for beginners), Chapter 10, Section
10.6 :
"The possibilities for input errors are limitless! However an istream
reduces all to four cases, called stream state :
good() The operations succeeded.
eof() We hit end of input ('end of file').
fail() Something unexpected happened.
bad() Something unexpected and serious happened."

and later in the same section :

"When a stream has failed, we might be able to recover. To try to
recover, we explicitly take the stream out of the fail() state, so
that we can look at characters from it again; clear() does that -
after cin.clear() the state of cin is good()"

James Kanze

unread,
Feb 9, 2011, 8:46:49 AM2/9/11
to

On Feb 7, 7:54 pm, TheGunslinger <mikiesrunsbaal....@sbcglobal.net>
wrote:

> I have a programming assignment that is to utilize (a class in
> OOP/C++)

> cin.fail()
> cin.ignore()
> cin.clear()

> These are to be used within a do/while if(cin.fail()) conditional.

> In my 2010 C++ reference, I could only find a reference to one of
> these functions.

> Whereas in my 2000 reference, I can find documentation for all 3 and
> a couple more.

> My questions are:
> 1) Are these functions currently deprecated under the 2003 ISO
> Standard and the ISO Draft to be confirmed and standardized this year?

No.

> 2) I can find numerous references to cin.fail() within the ISO draft
> (I d/l'd a copy for reference.), BUT none for cin.clear() and
> cin.ignore()??? Are these other functions being carried over strictly
> for portability and compatibility issues for legacy program support?

I'm not sure what you're looking for. cin is an object, and the
functions are members of the class type of the object. Or, in
this case, of one of its base classes: try looking under
basic_ios.

--
James Kanze

James Kanze

unread,
Feb 9, 2011, 9:49:06 AM2/9/11
to

On Feb 8, 10:39 am, ptyxs <kerl...@gmail.com> wrote:
> On Feb 7, 8:54 pm, TheGunslinger <mikiesrunsbaal....@sbcglobal.net>
> wrote:

[...]


> >From Programming Principles and Practise Using C++ by Bjarne

> Stroustrup (probably the best book for beginners), Chapter 10, Section
> 10.6 :
> "The possibilities for input errors are limitless! However an istream
> reduces all to four cases, called stream state :
> good() The operations succeeded.
> eof() We hit end of input ('end of file').
> fail() Something unexpected happened.
> bad() Something unexpected and serious happened."

This is somewhat misleading: good(), for example, may return
false even if the operations have succeeded, and eof() means
that the end of input has been encountered internally (possibly
while reading ahead). It's probably best to consider the
underlying state, and what it means, and then how the functions
work. The state consists of three bits:

eofbit:
The stream has encountered end of file internally. The
preceding access may or may not have succeeded; all we know
is that the next one will fail, and that if the previous
failed, it was probably due to trying to read beyond the
end.

failbit:
The access failed for some "non-serious" condition. When
reading, the two usual reasons are a format error in the
input stream (e.g. "abc" when trying to read an int) or
there was no data (end of file condition). In the latter
case, eofbit will be true, and in the former, it will
usually be false (but it's possible to construct cases where
it is true).

badbit:
The access failed for some serious reason: no space on disk
if writing, a hardware read error, etc.

good():
Returns true if and only if all three bits are false. The
fact that eof may be true even though the read succeeded
means that this function is generally useless: all you can
conclude if that if it returns false, all future accesses
will fail (but it tells you nothing about previous
accesses), and if it returns true, all previous accesses
have succeeded (but it tells you nothing about future
accesses).

eof():
Returns the eofbit. If it returns false, then all future
accesses have succeeded (but the previous access may or may
not have succeeded). It's really only useful after you know
that an access has failed, when it can be used to determine
whether the failure was due to end of file or some other
reason.

fail():
Returns failbit | badbit. This is by far the most useful:
it returns exactly whether all previous accesses have
succeeded or not.

bad():
Returns badbit. Mainly used after failure, to determine
why.

The operator! and the conversion to a boolean type are based on
fail(). Either directly or through one of these overloads,
fail() is always the first function you use. The others become
interesting once fail() has returned true, e.g.:

if ( stream.bad() )
// Hard IO error...
else if ( !stream.eof() )
// Formatting error (e.g. "abc" for an int)
else
// Normal end of file encountered

Finally, all of the bits are "sticky". That is, once set, they
stay set until explicitly cleared (and any further operations on
the stream are no-ops).

--
James Kanze

TheGunslinger

unread,
Feb 9, 2011, 6:24:10 PM2/9/11
to

On Wed, 9 Feb 2011 07:46:49 CST, James Kanze <james...@gmail.com>
wrote:


James,

Thanks for your insights.

The problem was that since I couldn't find any references to these
functions in my newest reference, dated 2010.

However, in continuing my search for information, I was able find a
copy of the latest Draft of the C++ specifications that is to be
released later this year, and ALL the references to my questions
regarding deprecation, and your insights were, of course, answered in
there.

I do hope someone puts together a better reference than the one I paid
good money for this year. As it turns out, it was a complete waste of
money, IMHO.

I finally went with the following code snippet:

//-------------------------------------
do{
try{
cout<<"How many days to be rented?\n";
cin>>daysRented;
if(cin.fail()){
throw false;
}else{goodInput=true;}
}catch(bool IOerror){
goodInput=false;
cin.clear();
cin.ignore(20,'\n');
} //End try/throw/catch
}while(goodInput==false);
//--------------------------------------

which was most effective in catching bad user input errors.

IMHO,

MJR

Seungbeom Kim

unread,
Feb 10, 2011, 5:58:12 PM2/10/11
to

On 2011-02-09 15:24, TheGunslinger wrote:
>
> I finally went with the following code snippet:
>
> //-------------------------------------
> do{
> try{
> cout<<"How many days to be rented?\n";
> cin>>daysRented;
> if(cin.fail()){
> throw false;
> }else{goodInput=true;}
> }catch(bool IOerror){
> goodInput=false;
> cin.clear();
> cin.ignore(20,'\n');
> } //End try/throw/catch
> }while(goodInput==false);
> //--------------------------------------
>
> which was most effective in catching bad user input errors.

It's not a good practice to throw an exception and catch it locally;
exceptions are better suited when you don't know from the throwing site
who will catch the exception and handle it.

The code snippet above can be rephrased in a much simpler form:

while (true) {


cout << "How many days to be rented?\n";

if (cin >> daysRented) // true iff !cin.fail()
break;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

These are fine in a usual interactive setting, but when the user hits
EOF (Ctrl+D on Unix, Ctrl+Z on Windows) or when the input is redirected
from a file whose EOF is hit, you get an infinite loop.
So this is better:

while (true) {


cout << "How many days to be rented?\n";

if (cin >> daysRented) // true iff !cin.fail()
break;
if (cin.eof()) {
// It depends what you can do here,
// but let's assume it's meaningless to continue:
abort();
}
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

In summary, if you want a "keep-asking-until-valid" behaviour,
you always have to consider three cases:

(a) A good input was read. - break; keep going
(b) A bad input was read. - clear stream and retry input
(c) No input was read. (EOF) - stop and exit to a higher layer

--
Seungbeom Kim

Suncho

unread,
Feb 10, 2011, 5:58:46 PM2/10/11
to

Your code is redundant. There's no need to use exceptions here. This does the exact same thing:

do {


cout << "How many days to be rented?\n";
cin >> daysRented;
if (cin.fail()) {

goodInput=false;
cin.clear();
cin.ignore(20,'\n');

} else {
goodInput=true;
}
} while(goodInput==false);

Note, however, that the "goodInput=false;" statement is also redundant if you initialize goodInput to false.

But there's another error here. You don't test for a bad stream. If there's something seriously wrong with the stream that causes it never to be able to read from the input, you're stuck in an infinite loop. This is what exceptions are for:

do {


cout << "How many days to be rented?\n";
cin >> daysRented;
if (cin.fail()) {

if (cin.bad())
throw 0; // throw whatever you want.
cin.clear();
cin.ignore(20,'\n');
} else {
goodInput=true;
}
} while(goodInput==false);

You could alternatively set the badbit exception flag for cin:

cin.exceptions (ios::badbit);

If you do this before your loop, the stream will automatically throw std::failure when it enters a bad state and your loop looks like this again:

do {


cout << "How many days to be rented?\n";
cin >> daysRented;
if (cin.fail()) {

cin.clear();
cin.ignore(20,'\n');
} else {
goodInput=true;
}
} while(goodInput==false);

Much simpler, huh?

Anyway, exceptions should not be used to control loops. As a general rule, only throw exceptions when something occurs that you don't know how to handle. If your code has both throws and try blocks in the same function, you're doing it wrong.

P.S. cin.ignore(20,'\n'); only ignores 20 characters. If you'd like to ignore everything up to the new line use this:

#include <numeric>
....
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');

James Kanze

unread,
Feb 10, 2011, 6:05:46 PM2/10/11
to

On Feb 9, 11:24 pm, TheGunslinger <mikiesrunsbaal....@sbcglobal.net>
wrote:

[...]


> I finally went with the following code snippet:

> //-------------------------------------
> do{
> try{
> cout<<"How many days to be rented?\n";
> cin>>daysRented;
> if(cin.fail()){
> throw false;
> }else{goodInput=true;}
> }catch(bool IOerror){
> goodInput=false;
> cin.clear();
> cin.ignore(20,'\n');
> } //End try/throw/catch
> }while(goodInput==false);
> //--------------------------------------

> which was most effective in catching bad user input errors.

I'm not sure what you mean by "most effective" (and I can easily
enter text for which it would fail), but it certainly looks like
serious abuse of exceptions. If I could afford to ignore end of
file and possible hard errors, I'd use something like:

int
getInt( std::istream& source )
{
int result;
source >> result;
while ( !source ) {
source.clear();
source.ignore(INT_MAX, '\n');
source >> result;
}
return result;
}

A more realistic version would be:

Fallible<int>
getInt( char const* promptInCaseOfError, std::istream& source )
{
Fallible<int> result;
bool fatalErrorSeen = false;
while ( !fatalErrorSeen && !result.isValid() ) {
int tmp;
source >> tmp;
if ( source ) {
result.validate( tmp );
} else if ( source.bad() || source.eof() ) {
fatalErrorSeen = true;
} else {
source.clear();
source.ignore( INT_MAX, '\n' );
if ( promptInCaseOfError != NULL ) {
std::cout << prompt;
std::cout.flush();
}
}
}
return result;
}

--
James Kanze

ptyxs

unread,
Feb 10, 2011, 6:05:24 PM2/10/11
to

On Feb 9, 3:49 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Feb 8, 10:39 am, ptyxs <kerl...@gmail.com> wrote:
> eofbit:
> The stream has encountered end of file internally.

Could you please explain what do you mean by that and under what
circumstances it does happen in the case where the last access was
successful ? Thanks.

(and BTW I guess that your :


eof():
Returns the eofbit. If it returns false, then all future
accesses have succeeded (but the previous access may or may
not have succeeded).

has to be modified in some way (as "all future accesses have succeded"
doesn't mean anything to my ear), could you tell how ?. Thanks again.
)

James Kanze

unread,
Feb 11, 2011, 12:18:32 PM2/11/11
to

On Feb 10, 11:05 pm, ptyxs <kerl...@gmail.com> wrote:
> On Feb 9, 3:49 pm, James Kanze <james.ka...@gmail.com> wrote:

> > On Feb 8, 10:39 am, ptyxs <kerl...@gmail.com> wrote:
> > eofbit:
> > The stream has encountered end of file internally.

> Could you please explain what do you mean by that and under what
> circumstances it does happen in the case where the last access was
> successful ?

Just about any time the istream has to parse input. Try
something like:

istringstream in("3.14159");
double d;
in >> d;

You'll almost certainly find in.eof() true, but the input will
have succeeded (in.fail() will return false).

> (and BTW I guess that your :
> eof():
> Returns the eofbit. If it returns false, then all future
> accesses have succeeded (but the previous access may or may
> not have succeeded).
> has to be modified in some way (as "all future accesses have succeded"
> doesn't mean anything to my ear), could you tell how ?. Thanks again.
> )

Something got mangled, that's for sure. It should be "all
future accesses will fail (but the previous access may or may
not have succeeded)".

--
James Kanze

Jens Schmidt

unread,
Feb 12, 2011, 9:11:51 AM2/12/11
to

ptyxs wrote:

>
> On Feb 9, 3:49 pm, James Kanze <james.ka...@gmail.com> wrote:
>> On Feb 8, 10:39 am, ptyxs <kerl...@gmail.com> wrote:
>> eofbit:
>> The stream has encountered end of file internally.
>
> Could you please explain what do you mean by that and under what
> circumstances it does happen in the case where the last access was
> successful ? Thanks.

I'm not James, but my best guess:

assuming a stream s has "123" as its contents at the end and reading
resumes from just before that. If you use

int i;
s >> i;

then the operation will succeed, i now contains 123. But at the same
time s.eof() will return true, because internally operator>> had to
check for more digits.

> (and BTW I guess that your :
> eof():
> Returns the eofbit. If it returns false, then all future
> accesses have succeeded (but the previous access may or may
> not have succeeded).
> has to be modified in some way (as "all future accesses have succeded"
> doesn't mean anything to my ear), could you tell how ?. Thanks again.
> )

Just swap future and previous, adjusting any dependent grammar:
Returns the eofbit. If it returns false, then all previous
accesses have succeeded (but future accesses may or may
not succeed).
--
Greetings,
Jens Schmidt

ptyxs

unread,
Feb 12, 2011, 12:42:55 PM2/12/11
to

{ quoted signature and quoted banner removed. please always remove signatures,
the banner text, and other extraneous material. yes, you can! :) -mod }

Thank you very much for this simple example. Quite right (and much
surprising to me...). A programm like :

_____________________________
#include <iostream>
#include <sstream>

int main()
{
std::istringstream in("3.14159");
double d;
in >> d;
std::cout << d << std::endl;
std::cout << in.fail() << std::endl;
std::cout << in.eof() << std::endl;
}
________________________________

gives an output like :


3.14159
0
1

On the other hand if you read a simple text file say 'testule.txt'
containing exactly three characters say 'a', 'e' and 'i'. Immediately
after reading 'i' the in stream's eof() is false, it gives a true
value only after an unsuccesful attempt to read a character.

The following programm :

________________________

#include <iostream>
#include <fstream>

int main()
{
std::ifstream is("testule.txt");

for(int i = 0; i < 4; i++) {
char c = '\0';
is >> c;
std::cout << i + 1 << " :" << std::endl;
std::cout << " c = " << c << std::endl;
if (is.eof())
std::cout << " EOF" << std::endl;
}
}


__________________________

gives :

1 :
c = a
2 :
c = e
3 :
c = i
4 :
c =
EOF

I am not quite sure I understand the reason for these differences.

Bo Persson

unread,
Feb 13, 2011, 10:57:53 AM2/13/11
to

The difference is that when reading a char, the input operator knows
how much to read (a single character :-), but when trying to read an
integer it has to continue reading until it runs out of digits or hits
the end of file.


Bo Persson

James Kanze

unread,
Feb 13, 2011, 10:58:09 AM2/13/11
to

> Thank you very much for this simple example. Quite right (and much


> surprising to me...). A programm like :

> _____________________________
> #include <iostream>
> #include <sstream>

> int main()
> {
> std::istringstream in("3.14159");
> double d;
> in >> d;
> std::cout << d << std::endl;
> std::cout << in.fail() << std::endl;
> std::cout << in.eof() << std::endl;
> }

> ________________________________
>
> gives an output like :

> 3.14159
> 0
> 1

> On the other hand if you read a simple text file say 'testule.txt'
> containing exactly three characters say 'a', 'e' and 'i'. Immediately
> after reading 'i' the in stream's eof() is false, it gives a true
> value only after an unsuccesful attempt to read a character.

Formally, the results of eof() immediately after reading 'i' are
unspecified. Practically, it depends on what << is used.

> The following programm :

> __________________________

> gives :

If the extractor function (the <<) must read ahead to know
whether it has finished, then eof() will return true. If it
doesn't, eof() will return false. (In practice, anyway.) In
the case of "is >> c", where c has type char, the istream knows
that it has finished as soon as it has extracted a non-space
character ('i'). When inputting a lot of types, however, the
length is not known in advance; the istream must read ahead to
determine whether the next character could be part of the input.
If it encounters the end of file when doing so, eof() will
return true, even though the input succeeds.

--
James Kanze

0 new messages