dabadaba
dabadaba

Reputation: 9532

Clean istream when input is not correct

I am looking through the istream class and I don't see a method that cleans completely the buffer and sets the input to be ready for a next "clean" input.

I defined the extraction operator for my class, and in my main program I ask the user for an input, like this:

while (true) {
    try {
        cout << "Enter input: ";
        MyClass c;
        cin >> c;
        return c;
    } catch(const MyException& e) {
        cerr << "Error\n";
    }
}

If I enter an unexpected incorrect input I am trapped in an infinite loop.

In my overriden extractin method I control when the input is not correct and the exception is thrown, all this is ok. I just want to also clean the istream object so I prevent the infinite loop.

Upvotes: 0

Views: 436

Answers (1)

David G
David G

Reputation: 96835

Firstly, the inserters/extrators for your classes shouldn't throw exceptions. IOStreams were designed not to throw exceptions by default and to remain consistent I would recommend that you not throw custom exceptions from your I/O operators.

As Dieter said, you're better off setting the std::ios_base::failbit flag in the stream state instead of throwing. You can do this using the setstate() method. Once you do that, you can check for a valid extraction with an if() statement. To answer your question, once you determine if the input is invalid, you clear the stream state, and clear the buffer for new input by calling ignore() discard the rest of the characters:

while (std::cout << "Enter input: ")
{  
    X x;
    if (!(std::cin >> x))
    {
        std::cout << "Invalid. Try again.\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        continue; // or break if needed
    }
    // handle good input and break if needed
}

Upvotes: 1

Related Questions