-2

I am trying to write a code to prompt user input from cin.

int main()
{
    int year;
    cout << "Enter a valid year: ";
    cin >> year;

    while (cin.fail())
    {
        cout << "Re-enter a valid value! ";
    }
}

However, the compiler keeps printing the line "Re-enter a valid value! " unterminatedly when I enter a non-integer type. I don't know what's wrong about my code! Can somebody please correct it? Thank you very much.

3
  • So many questions... why does "the compiler print" anything? That's not what compilers do. And why "enter a valid year"? Why not just "enter a year"? When would you ever need to specify that you want something valid? Commented Jan 5, 2017 at 1:27
  • @KerrekSB: I'm sorry for my lack of understanding of the terminologies, but can you specify what needs to be changed in my code? Commented Jan 5, 2017 at 1:30
  • This looks like a duplicate: stackoverflow.com/questions/5655142/… Commented Jan 5, 2017 at 1:33

3 Answers 3

5

Try this:

bool done = false;
int year;

for (std::string line;
     std::cout << "Enter a year: " && std::getline(std::cin, line); )
{
    std::istringstream iss(line);
    if (iss >> year >> std::ws && iss.get() == EOF) { done = true; break; }
    std::cerr << "Failed to parse input '" << line << "', please try again.\n";
}

if (!done) { std::cerr << "Premature end of input.\n"; }
else       { std::cout << "Input: " << year << "\n";   }
Sign up to request clarification or add additional context in comments.

9 Comments

You make my day. Finally someone do proper input handling on cin ;). And I am also sad for bffaf01 as probably he will not understand a thing from your code.
@Logman what's wrong with the more typical istream::clear() and istream::ignore() approach without an extra stream?
I know it's a command-line not a database or website, but isn't: '" << line << "' un-sanitized I/O? Maybe I've been writing web apps and worrying about cross site scripting too long?
@ebyrob I get this answer as a little joke. Answer is correct in every aspect, it's really well crafted but it's way too complicated for someone who do no know why while (cin.fail()) is not working.
@ebyrob it's not like we're doing "select * from " << line
|
4

This is my approach :

int main() {
    int year;

    while (true) {
        cout << "Enter a valid year: ";
        cin >> year;
        if (cin.fail()) {
            cin.clear(); cin.ignore();
            cout << "Re-enter a valid value! " << endl;
        } else break;
    }
    return 0;
}

2 Comments

I seem to recall something about if(cin) or if(!cin) somehow being superior to ios::good(), ios::bad(), and ios::fail() but it could be cin.fail() == !cin in all cases and I just forget that all the time.
Just as a note, this code accepts xyz1234abc as valid input. I don't know whether that behaviour is preferable over the alternative, but it's worth calling out the difference.
0

The problem you've described is here:

while (cin.fail())
{
    cout << "Re-enter a valid value! ";
}

It looks like you don't fully understand what's happening here yet, so I will break this down for you.

The code translates to something like this:

"While cin.fail() is true, output "Re-enter a valid value! " to the console"

Which it will do continuously because there is no way to break out of the loop.

I don't think cin.fail() is what you want to use here, it looks like you want an algorithm to tell you if the date is valid or not and, if it's not valid, to repeat the query to the user so they can enter good data. Conceptually this is good practice, you're on the right track, but you need to learn a bit more.

I would suggest reading some tutorials on input/output and also looking into input validation.

This is an excellent resource for learning C++ http://www.cplusplus.com/doc/tutorial/

And here is some info on input validation http://www.cplusplus.com/forum/beginner/121194/

1 Comment

Input validation is only half the story. If you attempt formatted input directly from cin, you also need to reset the error state on the stream object.

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.