0

I have this snippets of code from my original long program, and as much as it looks simple, it doesn't work correctly! I am brand-new to c++ language, but I know in Java that would be the way to do it (Regardless of the syntax).

Simply put, this should ask the user for an input to answer the following multiplication (5*5), however, it should also check if the user entered a wrong input (not number), keep asking the user again and again... Somehow, it keeps running forever without taking a new input!!

I hope to get, not only an answer, but also a reason for such an error!

int main() {
  int userAnswer;
  bool isValidAnswer = true;

  cout << 5 << " * " << 5 << " = ";
  cin >> userAnswer;
  cin.ignore();

  do {
    if (cin.fail()) { //user input is not an integer
      cout << "Your answer is not valid! Please enter only a natural number: ";
      cin >> userAnswer;
      cin.ignore();
    } else {
      isValidAnswer = false;
    }
  } while (isValidAnswer);

  return 0;
}
bad
  • 92
  • 10

2 Answers2

2

Well you need to clear the error state before accepting new input. Call cin.clear() then cin.ignore() before trying to read input again.

I would do something like.

cout << "Enter a number: ";
cin >> number;
while(cin.fail())
{
    cin.clear();
    cin.ignore(1000, '\n'); //some large number of character will stop at new line
    cout << "Bad Number Try Again: ";
    cin >> number;
}
chasep255
  • 11,745
  • 8
  • 58
  • 115
  • I tried to use cin.clear() but nothing changed. Your code is having the same problem too!! It never excepts the new input and I keep pressing enter without ending the loop! – bad Oct 11 '15 at 22:40
  • Oops. It actually needs to be cin.ignore(1000, '\n'); You need to tell it to ignore up to the new line. – chasep255 Oct 11 '15 at 22:45
  • what fail() and clear() exactly do, so that it caused such a problem? – bad Oct 11 '15 at 22:55
  • fail is a way of checking if cin failed. It returns a boolean. Clear clears the error state so that you can continue to use the stream. When cin fails that bad input is left in the stream so after you clear the error state you need to ignore the bad input. – chasep255 Oct 11 '15 at 22:56
  • What if I did something like that `123B`, then what is going to happen? Is it going to fail or not? – bad Oct 11 '15 at 23:04
  • It will fail. You need to have white space after the number. – chasep255 Oct 11 '15 at 23:05
  • Well I guess I mixed that up with java. It will read in the 123 and leave the B in the stream which will be the first char when you try to read something again. – chasep255 Oct 11 '15 at 23:07
  • is there is away of fixing it so it doesn't accept it as a valid input? – bad Oct 11 '15 at 23:10
  • You could use getline to read an entire line but it will only read it as a string. You would then need to convert it to an int using the strtol function. http://www.cplusplus.com/reference/cstdlib/strtol/ – chasep255 Oct 11 '15 at 23:11
  • [This](http://stackoverflow.com/a/16575025/1601729) answer goes into detail about using strtol to detect if the string is a number (and is put into my answer). – Ironcache Oct 11 '15 at 23:56
0

First, cin.fail() is not going to adequately check if your answer is a natural number or not with the type set to int (could also be negative).

Second, your boolean isValidAnswer is really checking if it's is an invalid answer.

Third (and most importantly), as another answer suggests, you should put in cin.clear() to clear the failure state, and then followed by cin.ignore(), which will remove the failed string from cin.

Fourth, cin will only check if an int exists somewhere in the string. You'll need to perform your own string comparison to determine if the entire input is a int (see answer below, based on this answer).

Updated:

#include <iostream>
#include <string>
#include <cstdlib>                                                                                                                                                                                    
using namespace std;

bool isNum(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}

int main() {
  int userAnswer;
  string input;
  bool isInvalidAnswer = true;
  cout << 5 << " * " << 5 << " = ";
  while (isInvalidAnswer) {
    if (!(cin >> input) || !isNum(input)) {
      cout << "Answer is not a number! Please try again:\n";
      cin.clear();
      cin.ignore();
    }
    else {
      userAnswer = atoi(input.c_str());
      if (userAnswer < 0) { //user input is not an integer
        cout << "Answer is not a natural number! Please try again:\n";
      } else {
        isInvalidAnswer = false;
      }
    }
  }
  cout << "Question answered!\n";
  return 0;
}
Community
  • 1
  • 1
Ironcache
  • 1,719
  • 21
  • 33