Connecting Tech Pros Worldwide Forums | Help | Site Map

cin error recovery

Roman Gavrilov
Guest
 
Posts: n/a
#1: Jul 22 '05
Have following snippet:

int i1, i2;
cin >> i1;
cin >> i2;
cout << i1 << ", " << i2;

If on first prompt I enter non-numeric value, then second value is not
prompted and i1, i2 are set to some weird value.

Q: is there something I can do to be able to enter second value even
if first value was invalid?

Note: cin.clear() - does not help.
Note: cin.clear() does help under Windows (WinXP), but does not work
under SunOS (5.2)

Thank you,
Regards,
Roman
Jonathan Turkanis
Guest
 
Posts: n/a
#2: Jul 22 '05

re: cin error recovery



"Roman Gavrilov" <clavrg@hotmail.com> wrote in message
news:fe75986a.0402071558.a4cc4e0@posting.google.co m...[color=blue]
> Have following snippet:
>
> int i1, i2;
> cin >> i1;
> cin >> i2;
> cout << i1 << ", " << i2;
>
> If on first prompt I enter non-numeric value, then second value is[/color]
not[color=blue]
> prompted and i1, i2 are set to some weird value.
>
> Q: is there something I can do to be able to enter second value even
> if first value was invalid?
>[/color]

Did you trying clearing the error state, then reading and discarding
the remainder of the line? E.g.

if (!(cin >> i1)) {
cin.clear();
std::string s;
cin >> s;
cout << "Did I tell you to write " << s << "?\n";
cout << "I said, input a *number*, stupid!\n";
}

Jonathan


Jon Bell
Guest
 
Posts: n/a
#3: Jul 22 '05

re: cin error recovery


In article <fe75986a.0402071558.a4cc4e0@posting.google.com> ,
Roman Gavrilov <clavrg@hotmail.com> wrote:[color=blue]
>Have following snippet:
>
>int i1, i2;
>cin >> i1;
>cin >> i2;
>cout << i1 << ", " << i2;
>
>If on first prompt I enter non-numeric value, then second value is not
>prompted and i1, i2 are set to some weird value.
>
>Note: cin.clear() - does not help.[/color]

Actually, cin.clear() *does* help, but it's not all you need to do.

When stream input encounters an illegal character, input stops at that
character, leaving it in the input stream so you can try to read it a
different way if you want. In your case, you probably want to skip past
it to the next hopefully valid input item.

cin.clear() resets the stream status flags, which allows further input to
take place, but it doesn't actually move the input point in the file. So
if you try to read again, you just hit the bad data again.

One common way to skip past the bad data is to assume that the items are
separated by newlines, and use something like cin.ignore(1000, '\n') which
skips to just past the next newline, or 1000 chars, whichever comes first.
This works better if you prompt for the two numbers separately so they
have to be on separate lines.

If the two numbers are supposed to be on the same line, you could probably
simply read the bad data into a dummy string using >>, which will read
until the next whitespace; then try to read the next number normally.

--
Jon Bell <jtbellm4h@presby.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA
Roman Gavrilov
Guest
 
Posts: n/a
#4: Jul 22 '05

re: cin error recovery


My bad, full text would be:

int i1, i2;
cin >> i1;
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin >> i2;
cout << i1 << " " << i2 << endl;

so, I do clear the rest of the input buffer. Problem goes even deaper - does
not matter how many times after the error I try to read cin - it always
returns an error.

while (true) {
int i1;
cin >> i1;
cout << i1;
}

if in the snippet above I enter error once, it will output the "weird" value
forever.

Regards,
Roman

"Jon Bell" <jtbellj3p@presby.edu> wrote in message
news:c047jb$svv$1@jtbell.presby.edu...[color=blue]
> In article <fe75986a.0402071558.a4cc4e0@posting.google.com> ,
> Roman Gavrilov <clavrg@hotmail.com> wrote:[color=green]
> >Have following snippet:
> >
> >int i1, i2;
> >cin >> i1;
> >cin >> i2;
> >cout << i1 << ", " << i2;
> >
> >If on first prompt I enter non-numeric value, then second value is not
> >prompted and i1, i2 are set to some weird value.
> >
> >Note: cin.clear() - does not help.[/color]
>
> Actually, cin.clear() *does* help, but it's not all you need to do.
>
> When stream input encounters an illegal character, input stops at that
> character, leaving it in the input stream so you can try to read it a
> different way if you want. In your case, you probably want to skip past
> it to the next hopefully valid input item.
>
> cin.clear() resets the stream status flags, which allows further input to
> take place, but it doesn't actually move the input point in the file. So
> if you try to read again, you just hit the bad data again.
>
> One common way to skip past the bad data is to assume that the items are
> separated by newlines, and use something like cin.ignore(1000, '\n') which
> skips to just past the next newline, or 1000 chars, whichever comes first.
> This works better if you prompt for the two numbers separately so they
> have to be on separate lines.
>
> If the two numbers are supposed to be on the same line, you could probably
> simply read the bad data into a dummy string using >>, which will read
> until the next whitespace; then try to read the next number normally.
>
> --
> Jon Bell <jtbellm4h@presby.edu> Presbyterian College
> Dept. of Physics and Computer Science Clinton, South Carolina USA[/color]


Jonathan Turkanis
Guest
 
Posts: n/a
#5: Jul 22 '05

re: cin error recovery


"Roman Gavrilov" <clavrg@hotmail.com> wrote in message
news:8bSdnRQOJeiGULjdRVn-gg@comcast.com...[color=blue]
> My bad, full text would be:
>
> int i1, i2;
> cin >> i1;
> cin.clear();
> cin.ignore(cin.rdbuf()->in_avail());
> cin >> i2;
> cout << i1 << " " << i2 << endl;
>
> so, I do clear the rest of the input buffer. Problem goes even[/color]
deaper - does[color=blue]
> not matter how many times after the error I try to read cin - it[/color]
always[color=blue]
> returns an error.
>[/color]

What compiler/standard library are you using?

Jonathan


E. Robert Tisdale
Guest
 
Posts: n/a
#6: Jul 22 '05

re: cin error recovery


Roman Gavrilov wrote:
[color=blue]
>
> while (true) {
> int i1;
> cin >> i1;
> cout << i1;
> }
>
> if in the snippet above
> I enter error once, it will output the "weird" value forever.[/color]

Of course. That's what it's supposed to do. Try this:

[color=blue]
> cat main.cc[/color]
#include <iostream>

int main(int argc, char* argv[]) {
int i1 = 666;
while (std::cin >> i1) {
std::cout << i1 << std::endl;
}
std::cout << i1 << std::endl;
return 0;
}
[color=blue]
> g++ -Wall -ansi -pedantic -o main main.cc
> ./main[/color]
www
666[color=blue]
> ./main[/color]
777
777
www
777

The input function

istream& operator>>(istream&, int&)

looks at the first character of "www" and knows that
it can't be part of an int so it returns with i1 unchanged.
It doesn't actually read any characters so "www"
will still be there the next time that you try to read.
Notice that if I enter 777 operator>> succeeds
and i1 is set to 777.

David Harmon
Guest
 
Posts: n/a
#7: Jul 22 '05

re: cin error recovery


On Sat, 7 Feb 2004 21:45:41 -0800 in comp.lang.c++, "Roman Gavrilov"
<clavrg@hotmail.com> was alleged to have written:[color=blue]
>cin.clear();
>cin.ignore(cin.rdbuf()->in_avail());[/color]

in_avail() is probably not useful for this purpose (maybe any purpose.)

Suggest you try our instead:
std::cin.ignore(std::numeric_limits<std::streamsiz e>::max(), '\n');

Roman Gavrilov
Guest
 
Posts: n/a
#8: Jul 22 '05

re: cin error recovery


David,

Thank you, you were right - in_avail was returning a 0.

Works now as expected

Regards,
Roman

David Harmon <source@netcom.com> wrote in message news:<40472dfd.78975162@news.west.earthlink.net>.. .[color=blue]
> On Sat, 7 Feb 2004 21:45:41 -0800 in comp.lang.c++, "Roman Gavrilov"
> <clavrg@hotmail.com> was alleged to have written:[color=green]
> >cin.clear();
> >cin.ignore(cin.rdbuf()->in_avail());[/color]
>
> in_avail() is probably not useful for this purpose (maybe any purpose.)
>
> Suggest you try our instead:
> std::cin.ignore(std::numeric_limits<std::streamsiz e>::max(), '\n');[/color]
Closed Thread