Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > cin and cin.clear() problem

Reply
Thread Tools

cin and cin.clear() problem

 
 
TaiwanNoWhere
Guest
Posts: n/a
 
      10-13-2003
// case 1
int Option = 0;

for(;
{
cin >> Option;

switch(Option)
{
case 1:
return Option;
break;
case 2:
return Option;
break;
case 3:
return Option;
break;
default:
cout <<"Please enter the valid input!";
}
}

// case 2
int Option = 0;

do{
cin >> Option;

if(cin.fail())
{
cout << "Error! Please enter integer value! " << endl;
cin.clear();
}
}while(!(Option>=1&&Option<=3));

return Option;



// I have made the two cases to cin valid Option,
// but both re-cin cannot work when loop repeats.
// Can anyone explain to me the reason?

// I have read the function of clear()
// and still do not get how clear(iostate state=goodbit) works.
// Do I need to declare goodbit before I use it?
// My instructor gives this code to me, but still cannot work

// Thanks
 
Reply With Quote
 
 
 
 
Mike Wahler
Guest
Posts: n/a
 
      10-13-2003
"TaiwanNoWhere" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...

> do{
> cin >> Option;
>
> if(cin.fail())
> {
> cout << "Error! Please enter integer value! " << endl;
> cin.clear();
> }
> }while(!(Option>=1&&Option<=3));
>
> return Option;
>
> // I have made the two cases to cin valid Option,
> // but both re-cin cannot work when loop repeats.
> // Can anyone explain to me the reason?


Yes. 'cin' goes into a 'fail' state if it encounters
invalid characters for the extracted type ('int' in
this case). E.g. if you type "ABC" instead of "123".
These offending characters are not extracted from the
stream, and will be presented again to the next input
request. Thus the 'endless loop' scenario. You need
to specifically extract and discard them. See below.

>
> // I have read the function of clear()
> // and still do not get how clear(iostate state=goodbit) works.


You don't really need any 'deep' knowledge of how it works.
cin.clear(); will reset the stream into a 'good' state.

> // Do I need to declare goodbit before I use it?


No. All you need is #include <iostream> for invoking
cin's member functions.

There are several possible ways to remove the unwanted
characters. Here's one:

cin.clear(); /* reset stream state to 'good' */
cin.ignore(numeric_limits<streamsize>::max(), '\n');

This means: "extract and discard all characters up
to the first newline character, or the maximum possible
number of characters in a stream, whichever occurs first."

You'll need to add:
#include <limits> // for declaration of 'numeric_limits'
#include <ios> // for declaration of 'streamsize'

> // My instructor gives this code to me, but still cannot work


Have you considered consulting with him/her about this?

-Mike


 
Reply With Quote
 
 
 
 
TaiwanNoWhere
Guest
Posts: n/a
 
      10-14-2003
> There are several possible ways to remove the unwanted
> characters. Here's one:
>
> cin.clear(); /* reset stream state to 'good' */
> cin.ignore(numeric_limits<streamsize>::max(), '\n');
>
> This means: "extract and discard all characters up
> to the first newline character, or the maximum possible
> number of characters in a stream, whichever occurs first."
>
> You'll need to add:
> #include <limits> // for declaration of 'numeric_limits'
> #include <ios> // for declaration of 'streamsize'
>
> > // My instructor gives this code to me, but still cannot work

>
> Have you considered consulting with him/her about this?
>
> -Mike



I tried to email him, but today is Thanksgiving in Canada. I can
understand why to use cin.ignore()function, but why cin.clear()? Do
you mean what the value we cin has 2 characteristics? abstract data
type? one is state and one is value; therefore, we have to use
cin.clear to reset the state and cin.ignore() to discard the value. Is
my gusess correct?

Thanks for your helping
 
Reply With Quote
 
Mike Wahler
Guest
Posts: n/a
 
      10-14-2003
"TaiwanNoWhere" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...
> > There are several possible ways to remove the unwanted
> > characters. Here's one:
> >
> > cin.clear(); /* reset stream state to 'good' */
> > cin.ignore(numeric_limits<streamsize>::max(), '\n');
> >
> > This means: "extract and discard all characters up
> > to the first newline character, or the maximum possible
> > number of characters in a stream, whichever occurs first."
> >
> > You'll need to add:
> > #include <limits> // for declaration of 'numeric_limits'
> > #include <ios> // for declaration of 'streamsize'
> >
> > > // My instructor gives this code to me, but still cannot work

> >
> > Have you considered consulting with him/her about this?
> >
> > -Mike

>
>
> I tried to email him, but today is Thanksgiving in Canada.


What, he won't work on holidays?

>I can
> understand why to use cin.ignore()function, but why cin.clear()?


When 'cin' encounters a character that is invalid for the
type being extracted, not only does it not read the invalid
character, it goes into a 'fail' state. This is how it
informs you that something went wrong. You check for it
with e.g. if(!cin). The stream remains in this 'fail'
state until explicitly reset. That's what 'clear()' does,
sets the state back to 'good'.

>Do
> you mean what the value we cin has 2 characteristics? abstract data
> type? one is state and one is value;


Yes, cin (as well as any stream) has a 'state'. One could
say that it has a 'value' as well, but this 'value' doesn't
really have a useful meaning to the programmer. When you
write an expression such as if(cin) or if(!cin), it looks
like you're evaluating it's value, but something is happening
'behind your back'

A special member function of 'cin' intercepts this attempt
to determine it's 'value' and returns the stream's 'state'
instead. When evaluating 'cin' (or any stream object) in
a boolean context, (as in an if() expression), it produces
a value of 'true' if the stream is in the 'good' state, and
'false' if it is not.

>therefore, we have to use
> cin.clear to reset the state and cin.ignore() to discard the value.


Yes.

>Is
> my gusess correct?


Well, I didn't think you'd need to guess, since I thought
I'd already explained it, but I suppose I might not have
explained it well enough. But yes, that's correct.

>
> Thanks for your helping


You're quite welcome.

-Mike


 
Reply With Quote
 
J. Campbell
Guest
Posts: n/a
 
      10-14-2003
This is a little off-topic to your original post, but may be useful.

Rather than dealing with cin errors, I've made 2 functions that I use
when I want to get numeric keyboard input from the user. The
functions gint() and gun() are simple to use...

cout << "please enter a number";
int a_number = gint();

which works like...

cout << "please enter a number";
int a_number;
cin >> a_number;

however it avoids the pitfalls that can occur with cin entering an
error state.

Anyway...here's a demo that uses my functions. Note there are other
ways to do the same. I choose the ascii code route rather than
"string-class" manipulations, and not to use atoi(). Also, my
requrements are pretty strict...only numbers and (optional) leading
sign are accepted.

#include <iostream>
#include <string>

using namespace std;
void wait(); // portable equivalent of system("pause");
int gint(); // Get int
unsigned int gun(); // Get unsigned int

int main(){

cout << "This program demos 2 failsafe \"int getter\" functions.\n"
<< "Enter an Integer ";
int i = gint();
cout << "Enter an Unsigned Integer ";
unsigned int ui = gun();
cout << "\nI've got 'em...\nyour int is " << i
<< "\nyour unsigned int is: " << ui << "\nover and out!\n";

wait(); return 0;
}

void wait(){
cout<<"<Enter> to continue..";
string z; getline(cin,z);
}


int gint(){ // get *int*eger
string a;
bool badNum;
int myint, tens, sign;
do{
badNum = false;
getline(cin, a);
sign = 1 - (2 * (a[0] == 45)); // sign depends on a[0]
a.erase(0,(a[0] == 45) || (a[0] == 43)); //strips sign-if
present
tens = 1;
myint = 0;
for(int i = a.size(); --i >= 0; ){ //starts at (a.size() - 1)
if((a[i] < 5 && (a[i] >= 4){
myint += ((a[i] & 15) * tens);
tens *= 10;
}else{
cout << "Input Error.\n"
<< "Please enter a valid INTEGER: ";
badNum = true;
a.erase(); //to prevent large num warning if a.size() > 10
break;
}
}
myint *= sign;
if(a.size() > 10) cout << "Large number warning\n";
}while(badNum == true);
return myint;
}


unsigned int gun(){ // get *un*signed int
string a;
int myuint, tens;
bool badNum;
do{
myuint = 0; tens = 1;
badNum = false;
getline(cin, a);
a.erase(0,(a[0] == 43));
for(int i = a.size(); --i >= 0; ){
if((a[i] < 5 && (a[i] >= 4){
myuint += ((a[i] & 15) * tens);
tens *= 10;
}else{
cout << "Input Error.\n"
<< "Please enter a valid UNSIGNED INTEGER: ";
badNum = true;
a.erase();
break;
}
}
if(a.size() > 10) cout << "Large number warning\n";
} while(badNum == true);
return myuint;
}
 
Reply With Quote
 
TaiwanNoWhere
Guest
Posts: n/a
 
      10-17-2003
Thanks everyone's response
I have not read campell's answer yet, but I will read it after I finish MT

I have try the cin.clear() cin.ignore().
They work quite well with one exception.
If I type 2.34, then cin will cin 2 instead of 2.34.
Anyways to avoid this user error?

 
Reply With Quote
 
Karl Heinz Buchegger
Guest
Posts: n/a
 
      10-17-2003


TaiwanNoWhere wrote:
>
> Thanks everyone's response
> I have not read campell's answer yet, but I will read it after I finish MT
>
> I have try the cin.clear() cin.ignore().
> They work quite well with one exception.
> If I type 2.34, then cin will cin 2 instead of 2.34.
> Anyways to avoid this user error?
>


Use a double to read in the number!!

double number
cin >> number;

--
Karl Heinz Buchegger
http://www.velocityreviews.com/forums/(E-Mail Removed)
 
Reply With Quote
 
TaiwanNoWhere
Guest
Posts: n/a
 
      10-17-2003
But all I want is integer input instead of double

I mean when user inputs 2.34,
the program will consider input is 2.

However, 2.34 is not correct input. My correct input is 1,2,and 3.
Therefore, in this program, 2.34 will become a valid input since
computer will not reject this input. And this is not what I want
 
Reply With Quote
 
P.J. Plauger
Guest
Posts: n/a
 
      10-17-2003
"TaiwanNoWhere" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) om...

> But all I want is integer input instead of double
>
> I mean when user inputs 2.34,
> the program will consider input is 2.
>
> However, 2.34 is not correct input. My correct input is 1,2,and 3.
> Therefore, in this program, 2.34 will become a valid input since
> computer will not reject this input. And this is not what I want


Then you want something beyond the standard extractors. Read the
entire candidate field into a string object, convert it with strtol,
and check the end pointer that strtol returns to ensure that the
entire field is consumed.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Using cin.get() and cin.eof() ends up in an endless loop Fernando C++ 4 11-16-2011 07:19 PM
Problem with cin, cout using shift left and right? Xoomer C++ 1 08-23-2007 10:56 AM
newbie problem with cin and getline Devendra_Vidhale C++ 20 07-19-2007 08:19 AM
cin and cin.getline() Aleander C++ 5 03-06-2005 03:57 PM
std::cin.ignore() and std::cin.clear() Chris Mantoulidis C++ 5 01-06-2004 11:08 PM



Advertisments