Search code examples
c++validation

How can i ensure the user enter the good input type?


I want to create a code that will be a base for input checking on all of my future code.

I'm struggling at the point when I ask the user to re-enter his input. I don't understand why my std::cin >> var in the if (is_var_an_int == false) statement doesn't work. It just gets ignored and I can't change it, and then if I used a while loop it will just print infinitely.

I want to understand why my std::cin statement doesn't work.

Here is the code I wrote:

#include <iostream>

int main()
{
    std::cout << "Demo on !" << std::endl;

    int var{};

    bool is_var_an_int{};

    std::cout << "Var: "; std::cin >> var;

    if (std::cin.good())
    {
        is_var_an_int = true;
        std::cin.clear();
    }
    
    else
    {
        is_var_an_int = false;
        std::cin.clear();
    }

    if (is_var_an_int == false)
    {
        std::cout << "in the loop" << "\n";

        std::cin.clear();

        std::cout << "New var: "; std::cin >> var;

        if (std::cin.good())
        {
            is_var_an_int = true;
            std::cin.clear();
        }
    
        else
        {
            is_var_an_int = false;
            std::cin.clear();
        }
    }
    
    std::cout << is_var_an_int;
}

Know that I just started to learn C++.

I tried to see if there was a way to detect if the user input isn't the same type as the awaited type. This is solved with the std::cin.good(). But now, after the user entered an input like "hqjdhbqj", what I want my code to do is say to the user that the input he gave is not corresponding to the type and he (the user) needs to retry.


Solution

  • clear() only clears the error flag. The next time you read, you will read again from the position that failed, and fail again.

    In order to avoid repeating the same error over and over, you also need to move the read position ahead in the input stream.

    You need much less code than you think.

    Something like this should do:

    #include <limits>
     
    // ...
    
    std::cout << "Enter an integer: "; 
    while (!(std::cin >> var)) // This is true when reading fails.
    {
        // Clear error flag.
        std::cin.clear(); 
        // Discard rest of line. (Write a function of your own that does this.)
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        // Prompt again.   
        std::cout << "Please enter an integer: ";
    }
    // When you reach this point you know that 'var' was successfully read.