Advertisement

Strange Console behaviour has be stumped!

Started by June 13, 2002 08:53 PM
4 comments, last by Raskolnikov 22 years, 8 months ago
#include using namespace std; int main() { int choice= 0; while (choice <1 || choice > 5) { cout << "Choose 1-5\n"; cin >> choice; if (choice < 1 || choice > 5) { cout << "\nInvalid Choice, please try again.\n\n"; } } return 0; } I compiled this using Visual C++ 6, Service Pack 5, Windows Xp When I type a number it works fine, but when a letter is typed the program loops without waiting for input. What am I doing wrong and how can I fix it.
Choice is an integer, as in, it only stores fixed point numbers (ie: 1, 2, 3, 4...). As such, cin is checking for fixed point numbers. If you want it to check for a character, use the char data type for choice instead.


      char choice;/* Instead of... */int choice;      


[edited by - Johnny_W on June 13, 2002 10:00:01 PM]
Advertisement
An integer is what I want. The user is not supposed to enter a number, the problem is that the program goes goes into a wierd loop if the user, contrary to instructions types a letter anyway.

I ran the debugger and once a letter is typed the cin >> choice line is being executed, but the program does not wait for user input and the old value is kept.
You need to check your input before you start acting on it. There's a method in cin called peek() that lets you look at the current item in the input stream without removing it.

So, you need to do something like this:

  #include <cctype> // C++ version of ctype.h// etc...// before you read in anythingchar check; // used to check inputcheck = cin.peek();if(isdigit(check)) // it's a digit so it's ok to read in{   cin >> someVariable;}else   // eat thru the characters until you hit a digit or newline{   while(!isdigit(check) && (check != '\n'))   {      check = cin.get(); // eat the character      check = cin.peek(); // check out the next one   }      if(check != '\n') // if check isn't a newline, you've got a #   {      cin >> someVariable   }}   


You need to do this every time you read in data from the user.

Hope this helps!

/*=========================================*/
/* Chem0sh */
/* Lead Software Engineer & Tech Support */
/* http://www.eFaces.biz */
/*=========================================*/

[edited by - Chem0sh on June 13, 2002 10:57:58 PM]
/*=========================================// Chem0sh// Lead Software Engineer & Tech Support// http://www.eFaces.biz=========================================*/
The problem is that you only have an integer variable to store your data. The program will work if you enter a number because the program has no problem extracting an integer from the input stream and storing it into an integer variable.

However, if the user enters a null terminated string (or any character for that matter), cin will attempt to extact the first digit (e.g. character). Since it will encounter a character (when it expects a integer) the cin fails and the "extraction pointer" will stay pointing at that particular character. The next time around, cin will once again try to extract that same character off the input stream, however it will fail again (we are expecting a integer, not a char remember).

This cycle (loop) continues and continues, and the only way to get rid of it is to either advanced the input stream pointer (could cause errors if you overrun the input stream buffer or you could just end up encountering another integer). Or you could extract the character data into a character array.

That is why if you enter "5f" the program will succeed. The program extracts the 5 (no problem), but then sees the 'f' character after the 5 and only ends up extracting the 5.

In my opinion a better alternative is to cin into a character array or string, then cast that to an integer using the atoi function. If the user entered a character or array of characters, and you call atoi on those characters then atoi will return a 0.

Or you can do what Chem0sh said, I've never tried it that way.


------

Shop for the Lowest Price!
Then, Check a Reseller's Rating Before You Purchase!

[edited by - aNonamuss on June 13, 2002 11:17:30 PM]
------Shop for the Lowest Price!Then, Check a Reseller's Rating Before You Purchase!
Thank everyone I think the best solution is just to input a character and then convert it to a number. BTW this is microsofts take on the problem.


"If the user inputs a non-numeric value, the stream''s fail bit is set, and the cin object becomes unusable. All subsequent extractions result in an immediate return with no value stored. Consequently, the program hangs (stops responding) in the while loop. "

#include <iostream.h>

int ClearError(istream& isIn) // Clears istream object
{
streambuf* sbpThis;
char szTempBuf[20];
int nCount, nRet = isIn.rdstate();

if (nRet) // Any errors?
{
isIn.clear(); // Clear error flags
sbpThis = isIn.rdbuf(); // Get streambuf pointer
nCount = sbpThis->in_avail(); // Number of characters in buffer

while (nCount) // Extract them to szTempBuf
{
if (nCount > 20)
{
sbpThis->sgetn(szTempBuf, 20);
nCount -= 20;
}
else
{
sbpThis->sgetn(szTempBuf, nCount);
nCount = 0;
}
}
}

return nRet;
}

This topic is closed to new replies.

Advertisement