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

A stubborn cin

0 views
Skip to first unread message

Gary

unread,
Jan 8, 2003, 9:51:21 PM1/8/03
to
I have the following code:

#include <iostream>
using namespace std;

int main()
{
float a;

// read floats until we get an EOF from the input
while (!cin.eof())
{
// print the output as long as it's a float
while (cin >> a)
cout << a * 2 << endl;

// this is *supposed* to clear the failbit and thus restore cin to
normal...
cin.clear(cin.rdstate(), ~ios::failbit);
}
return 0;
}

The code compiles fine. The program works as if I enter only floats. But
when I enter a string, every entry thereafter doesn't display the output,
even if it's a float. For example, here is a sample running of the program:

Input: 3.4
Output: 6.8
Input: 2
Output: 4
Input: hello
Output: <none>
Input: 3.4
Output <none>

Any help would be appreciated.


Jon Bell

unread,
Jan 9, 2003, 12:16:53 AM1/9/03
to
In article <Js5T9.28418$Mb.8...@twister.southeast.rr.com>,

Gary <gi...@email.com> wrote:
>
> // read floats until we get an EOF from the input
> while (!cin.eof())

First of all, although this isn't the problem you're asking about, this
isn't a correct way to check for end of data. You can detect the end of
data only after you have tried and failed to read past the end of input.
A loop set up like this will usually try to read once more past the last
data item, giving you garbage as input.

> {
> // print the output as long as it's a float
> while (cin >> a)
> cout << a * 2 << endl;
>
> // this is *supposed* to clear the failbit and thus restore cin to
>normal...
> cin.clear(cin.rdstate(), ~ios::failbit);

You also need to skip past the bad input. Otherwise you just keep bumping
into it over and over again.

> }

Try this (untested, I'm living dangerously tonight):

cout << "Input: ";
cin >> a;
while (!cin.eof())
{
while (cin.bad())
{
cin.clear(); // this suffices to restore the status bits
cin.ignore(1000, '\n'); // skip 1000 chars or past next
// newline, whichever comes first
cout << "Invalid input, try again: ";
cin >> a;
}
cout << "Output: " << a*2 << endl;
cout << "Input: ";
cin >> a;
}

--
Jon Bell <jtbe...@presby.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA

Robbie Hatley

unread,
Jan 9, 2003, 3:04:03 AM1/9/03
to

"Gary" <gi...@email.com> wrote in message
news:Js5T9.28418$Mb.8...@twister.southeast.rr.com...

I see several problems.

Firstly, clear() takes at most one argument.
You can use just "cin.clear();" to clear all the status bits.

Secondly, what if badbit is set? You need to handle that.
And I believe eof always sets fail as well, so you need to
distinguish between "real" fail and "eof" fail.

Thirdly, clearing the bits won't flush the bad characters from
the stream; you'll need to use ignore() for that.

Fourthly, why nested loops? Only one is needed. Use "continue"
and "break".

Fifthly, you provide no way to brake out. Testing for eof()
would work only if you had some way to cause eof to occur.
But just hitting "Enter" won't cause eof(), because cin's
">>" operator ignores white space. Ctrl-z works (it puts an
overt "eof" character in the stream), but is rather obscure,
so you need to warn the user to enter it.

I tried this, and it works:


#include <iostream>
using namespace std;

int main()
{
float a;
for ( ; ; )
{
cout << "Input? (Ctrl-z, Enter to end) ";
cin >> a;
if (cin.eof())
{
break;
}
else if ( cin.fail() || cin.bad() )
{
cout << "Error: bad input, try again." << endl;
cin.clear();
cin.ignore(100, '\n');
continue;
}
else
{
cout << "Result = " << 2*a << endl;
}
}
return 0;
}


I hope that helps.


Cheers,
Robbie Hatley
Tustin, CA, USA
(no-spam: remove both Xs to send email)
lonewo...@pacXbell.net
http://home.pacbell.net/earnur/


Osmium

unread,
Jan 8, 2003, 11:06:47 PM1/8/03
to
Gary writes:

> I have the following code:
>
>#include <iostream>
>using namespace std;
>
>int main()
>{
> float a;
>
> // read floats until we get an EOF from the input
> while (!cin.eof())
> {
> // print the output as long as it's a float
> while (cin >> a)
> cout << a * 2 << endl;
>
> // this is *supposed* to clear the failbit and thus restore cin to
>normal...
> cin.clear(cin.rdstate(), ~ios::failbit);

Clearing the fail state is not enough. You have to empty the input buffer too.
Something like

cin.ignore(cin.rdbuf()->in_avail() );

0 new messages