cin.ignore not working: further inputs get skipped even with clear()

I am trying to make a checked bool input, but for some reason it keeps getting into an infinite loop, or (if I move std::cin.ignore() to be first thing executed after std::cin.clear()) asks for phantom input. I tried simple ignore() and ignore(std::numeric_limits<std::streamsize>::max(),'\n') and it still gets into an infinite loop, seemingly skipping cin input

Code:

#include <cstdlib>
#include <iostream>
#include <limits>

int main()
{
    std::string testString = "testvar";
    bool value = false;
    do
    {
        std::cin.clear();
        std::cout << "Enter " << testString << " value (true/false)\n";
        std::cin >> std::boolalpha >> value;
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        if(!std::cin.fail())
        {
            break;
        }
        std::cout << "Error! Input value is not boolean! Try again.\n";
    }while(true);

    std::cout << value;
}

Upvotes: 1

Views: 208

Answers (1)

NathanOliver
NathanOliver

Reputation: 180630

Your problem here is your order of operations. With

std::cin.clear();
std::cout << "Enter " << testString << " value (true/false)\n";
std::cin >> std::boolalpha >> value;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');

You call clear, get input, and then ignore the leftovers. The issue with that is if the get input part fails, then the ignore the leftovers will also fail as the stream is in a failed state. What you need to do is get the input, clear any error away, and then ignore an extra input. That would look like

std::cout << "Enter " << testString << " value (true/false)\n";
std::cin >> std::boolalpha >> value;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');

but this will break how your loop works. To get that working, you can use

do
{
    std::cout << "Enter " << testString << " value (true/false)\n";
    if (std::cin >> std::boolalpha >> value)
        break;
        
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
    std::cout << "Error! Input value is not boolean! Try again.\n";
} while(true);

Upvotes: 4

Related Questions