3

In this loop the user should enter an int and program checks if it be odd it will go to next parts, but I can't understand why if the user enter a character that's not int, the program is falling in an infinite loop!

int num;
do {
    cout << "PLEASE enter the num: ";
    cin >> num;
    if (num % 2 == 0)
        cout << "Number should be odd!" << endl;
    else
        break;
} while (true);
//...

Cause anyway char/int != 0 and if it be ==0 too it should stop at next cin but it wont stop! I tried ws(cin) too but it didn't help me. Please tell me how I can fix that problem, and why that's happening.

Claudio
  • 10,614
  • 4
  • 31
  • 71
  • 2
    See [this](http://stackoverflow.com/questions/13378989/why-does-stringstream-change-value-of-target-on-failure). – LogicStuff Dec 22 '15 at 08:01

3 Answers3

4

Becasue your program does not check the result of cin >> num;. Since cin >> num; (where num is an integer) will read all available digits, and if the input is not a digit at all [and not a whitespace character, which are skipped over by cin >>], then it keeps repeatedly trying to read the input.

It's not clear from your question exactly what you want to do when the user has entered "askjhrgAERY8IWE" to your program - there are two solutions that come to mind:

Alt 1. Ask again after removing the errant input. This is probably right for this application as it is interactive, but a terrible idea for an automated program that reads its input from a file.

if(!(cin >> num))
{
     cout << "That deoesn't seem to be a number..." << endl;
     cin.clear();
     cin.ignore(10000, '\n');
}

Alt 2. Exit with an error message. This is clearly the right thing when the typical input is a datafile.

 if(!(cin >> num))
 {
      cout << "That deoesn't seem to be a number..." << endl;
      exit(1); 
 }

You should also add code to deal with end of file in this code - for file-input that should be acceptable [unless the file has specific data to mark the end]. For interactive input (where the user is typing directly to the program), end of file may or may not be considered an error - really depends on what happens next.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • I think you accidentally some words at the end of your answer. – BoBTFish Dec 22 '15 at 08:05
  • @BoBTFish: Thanks, usual "premature posting". – Mats Petersson Dec 22 '15 at 08:07
  • I tried what you told but `!cin >> num` was not `True` when I entered `abcd` too – Danial Razavi Dec 22 '15 at 08:19
  • @DanialRazavi: Ah, missed a couple of brackets - should be `if (!(cin >> num))` - and I also missed the required `cin.clear();` before `cin.ignore()` - this clears the error state that `cin` gets into when the input is not a valid number, and in the error state, no further input will be accepted, so it keeps printing "Error" all the way through. – Mats Petersson Dec 22 '15 at 08:27
  • @DanialRazavi: How do you mean? – Mats Petersson Dec 22 '15 at 10:10
  • @MatsPetersson If input be `non numeric` the condition is `True` but if input be `int` condition is not `False` and program will not pass up to `else` it just stop working! – Danial Razavi Dec 22 '15 at 11:11
  • Right, I wasn't going to rewrite your entire program to work correctly, but just show "how do I detect bad input" - it's up to you to make that work with the rest of your code. – Mats Petersson Dec 22 '15 at 11:21
  • @MatsPetersson I can't understand why value of condition won't be `False` when I enter a numeric , but it take `True` when I enter an non-numeric input. – Danial Razavi Dec 22 '15 at 12:04
0

In your program, the standard input stream is expecting an integer. When you give it a character, cin cannot put it in the integer variable, ie it fails(error flag is set) and leaves the entered character in the buffer (for next cin assignments). cin repeatedly considers the character as input and keeps failing and the integer variable is assigned the value 0.

To prevent that you can modify your program as

int num;
    do{
        cout << "PLEASE enter the num: ";
        while(!(cin>>num)){
        cin.clear();
        cin.ignore(INT_MAX,'\n');
        cout<<"Invalid. Enter a number";
    }
        if (num % 2 == 0)
            cout << "Number should be odd!" << endl;
        else
            break;
    }
while(true);

include limits.h for using INT_MAX or you can use a large value like 10000.

The cin.clear clears the error flag and makes it ready for taking input. cin.ignore(INT_MAX,'\n') ignores everything(upto INT_MAX characters) until the next new line. This makes sure that the program will work fine if the user inputs a long line instead of a number.

  • That wont help cause if the user write `1abc` the program will accept it and will pass the loop, but i need to only when the input is NUMBER and ODD pass the loop. – Danial Razavi Dec 22 '15 at 12:23
0

i found a way to fix my problem,I changed input type to string and made a function as blow:

int isNum(string input)
{
    int digit, value = 0;
    for (int i = 0; i < input.length(); i++)
    {
        digit = input[i] - '0';
        if (digit >= 0 && digit <= 9)
            value = value * 10 + digit;
        else
        {
            value = 0;
            break;
        }
    }
    return value;
}

it will return the input as int if all characters be between 0 and 9, and else it will return 0; to me, so i use that returned int as my num.