-
Weird cin behavior
Hi. I'm having trouble with this overloaded >> function.
Code:
//Uses iostream.h, ctype.h, stdlib.h, and constants TRUE and FALSE:
istream& operator >>(istream& ins, Money& amount)
{
char one_char, decimal_point,
digit1, digit2; //digits for the amount of cents
long dollars;
int cents,
negative;//set to TRUE if input is negative.
ins >> one_char;
if (one_char == '-')
{
negative = TRUE;
ins >> one_char; //read '$'
}
else
negative = FALSE;
//if input is legal, then one_char == '$'
ins >> dollars >> decimal_point >> digit1 >> digit2;
if ( one_char != '$' || decimal_point != '.'
|| !isdigit(digit1) || !isdigit(digit2) )
{
cout << "first";
cin.get();
cin.get(one_char);
cout << one_char;
cin.get();
cin.get();
cin.get();
cin.get();
cin.get();
cin.get();
cout << "last";
cin.get();
cout << "Error illegal form for money input. Try again\n";
system("PAUSE");
exit(1);
}
cents = digit_to_int(digit1)*10 + digit_to_int(digit2);
amount.all_cents = dollars*100 + cents;
if (negative)
amount.all_cents = -amount.all_cents;
return ins;
}
This is code from my book(without the cin.gets of course), and my program compiles fine. I'm was trying to modify it so that the user can reenter input if he messes up, instead of using exit(1). I think i got it working for some input, but If i input like '1' and then 'a' or 'a' and then 'd'...basicly, if i enter a character as my second input, which i believe goes into the variable dollars, the program doesn't let me input the rest of the variables, skips every cin.get(), and goes straight for the exit(1). Why? Sorry if this is easy, but I can't figure it out. I know 'dollars' is a 'long int' variable, but my book does say you can store a letter in an int. (I don't want to, but this behavior is prevented from allowing the user to reenter inputs sometime.)
Thanks. :\
-
Once cin attempts to read a letter into an integer variable and fails, it sets a flag to indicate it has failed. You need to clear that flag before trying again, or every single attempt to read after that will fail.
Generally, you would call cin.clear() to clear the flags and cin.ignore(some big number, '\n') to ignore any bad data leftover in the stream (maybe that's what you were trying to do with all the cin.get()'s).
-
Ah, ok. So why did it fail, or does that always fail? I thought it was legal, but...
Anyway, i was using the cin.get()'s to try to get the program to stop before exiting when i put in that bad input. I did write this though to clear the buffer...
Code:
void clrbuff(void)
{
char x;
cin.get(x);
while(x != '\n')
{
cin.get(x);
}
}
...which got caught in an infinite loop with that bad input. Is that function fine, even if there are integers, ect in the buffer, or should i just use cin.ignore?
-
No, you're not understanding...
When you do something an istream doesn't like, it sets its fail bit true. This makes it unuseable until you call clear on the stream. Since it's unuseable, all calls to cin are ignored. That's why you get an infinite loop.
This is the common practice after you get bad input.
Code:
#include <limits>
void clear_cin() {
std::cin.clear();
std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
}
Code:
while(!(std::cin >> myInput;)) {
clear_cin();
std::cout << "Bad Input, please re-enter:";
}
...or something of the likes.
-
Sorry i guess i should have worded it differently. I understand now that the stream fails and thus why my loop failed. I was just telling why i had those cin.get(), and asking if my clrbuff() was fine(when the stream hasn't failed). I hadn't known about that cin.ignore function. anyway thanks you two.