3

I am trying to read an integer from terminal. Here's my code:

int readNumber()
{
    int x;
    std::cin >> x;
    while(std::cin.fail())
    {
        std::cin.clear();
        std::cin.ignore();
        std::cout << "Bad entry. Enter a NUMBER: ";
        std::cin >> x;
    }
    return x;
}

Whenever I run this code I get:

Type in the number for the newsgroup that shall be deleted:
joöä
Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: Bad entry.  Enter a NUMBER: 8

Why does it write "bad entry" multiple times? If I remove std::cin.clear(); or std::cin.ignore();, the program just keeps writing Enter a NUMBER: Bad entry. Can anyone explain why it does that?

7
  • try adding a break into your while loop. Should solve your problem Commented Apr 2, 2014 at 17:24
  • doesn't help i added a break inside a if(cin>>x) Commented Apr 2, 2014 at 17:28
  • My bad. Pretty tired, but anyway added in a proper answer which should work. (: Cheers Commented Apr 2, 2014 at 17:34
  • @user2975699, The short answer is that you are failing on each character and printing the error message for each failure. Commented Apr 2, 2014 at 17:34
  • @merlin2011, I thought so too, but there is 4 characters but the error message appears 6 times. Commented Apr 2, 2014 at 17:36

4 Answers 4

3

This is actually a partial duplicate of an old question, but it is phrased differently enough that I will address it briefly here.

  1. You get infinite printing without those two lines, because cin.clear() is required to clear the error flag that cin.fail() is reading. See the linked question for details.
  2. Why does it still print more than once when those lines are there? When you do std::cin >> x;, your code will read the first character in your input, and attempt to parse it as an int. It will fail, and then in the next iteration of the loop, it will attempt to parse the next character and fail again. For each failure (that is, each character in your input), it will print Bad entry. Enter a NUMBER:. If you type some bad input with fewer characters, you will see what I mean.

There are multiple ways to fix this problem, but one simple fix is to read the entire input into a string, and try to parse it, instead of using cin directly into an int. Here is some sample code which needs to be compiled with one of the various compiler-dependent flags for C++11. I have tested it with your input and it appears to achieve the effect you desire.

#include <iostream>
#include <string>
#include <stdexcept>

bool tryParse(std::string& input, int& output) {
    try{
        output = std::stoi(input);
    } catch (std::invalid_argument) {
        return false;
    }
    return true;
}
int main(){
    std::string input;
    int x;

    getline(std::cin, input);

    while (!tryParse(input, x))
    {
        std::cout << "Bad entry. Enter a NUMBER: ";
        getline(std::cin, input);
    }
    return x;
}
Sign up to request clarification or add additional context in comments.

Comments

1

Try this anyway... As I type this directly into stackoverflow might have compilation error

int readNumber()
{
   int x=0; 
   while(true)
   {
        std::cin >> x;
        if(!std::cin.fail()){
            break;
        }
        else{
            std::cout << "Bad entry. Enter a NUMBER: " << std::endl;
            std::cin.clear();
            std::cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
        }
    }
 }

Comments

0

cin.fail() returns true if the last cin command failed, and false otherwise.

Try this instead:

    while(1)
    {
        std::cin >> x;
        if (!std::cin.fail()) break;
        std::cin.clear();
        std::cin.ignore(10000,'\n');
        std::cout << "Bad entry. Enter a NUMBER: ";
    }

Comments

0
int main() {
    char* input;
    std::cin >> input;
    int x = std::atoi(input);
    while(x == 0 && strcmp(input, "0") != 0) {
        std::cout << "Bad entry. Enter a NUMBER: ";
        std::cin >> input;
        x = std::atoi(input);
    }
    return x;
}

Notice that when you have 3 non-int chars, it will repeat 3 times, when you have 5, it's repeated 5 times. It's because cin is tries the first char, fails, try the second char, fails and so on until all your input chars are parsed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.