This the right way to check input?

I want to know if I catch invalid inputs correctly. On line 18 is how I test if non-integers are entered. I need to know if it's the correct way of doing that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int getUserInput()
{
    int input;
    char cInput;

    cout << ">>>";
    cin >> input;
    if(!cin.fail() && input >= 1  && input <= 3)
    {
        return input;
    }
    else if(!cin.fail() && (input < 1  || input > 3))
    {
        cout << "Invalid input: " << input << endl;
        cout << "Must be 1, 2, 3, or Q" << endl;
        return getUserInput();
    }
    if(cin.fail())
    {
        cin.clear();
        cin >> cInput;
        if(cInput == 'q' || cInput == 'Q')
        {
            return -1;
        }
        else
        {
            cout << "Invalid input: " << cInput << endl;
            cout << "Must be 1, 2, 3, or Q" << endl;
            return getUserInput();
        }
    }
}


The function does its job, I am not sure cin.clear(); is what I need to use. Also ignore that it does not catch doubles.
Last edited on
in cin.fail()
you can use a goto command to re-enter character...
And If you use characters 1 is not 1 it is 49 ain ascii table
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int read_int( int min, int max )
{
    int value ;
    std::cout << "enter an integer in the range [" << min << '-' << max << "]: " ;
    if( std::cin >> value && value >= min && value <= max ) return value ;
    else
    {
        std::cout << "error in input.\n" ; // inform the user
        std::cin.clear() ; // clear the error state of the stream
        std::cin.ignore( 1024, '\n' ) ; // throw away the junk in the input buffer
        return read_int( min, max ) ; // and try again
    }
}
I have to nit-pick here.

When asking the user to "enter" something, you can repeat in your head the mantra:

The user will always press the ENTER key at the end of every input.

When I write programs that expect user input from the console, I always write a little function to get input. But it also always involves using getline() and a std::stringstream:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <algorithm>
#include <cctype>
#include <ciso646>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>

int read_int( 
    int min = std::numeric_limits <int> ::min(),
    int max = std::numeric_limits <int> ::max(),
    int default_ = 0 )
{
    // Ask the user for the input desired
    std::cout << "Enter an integer in the range [" << min << "," << max << "]";
    if ((default_ >= min) and (default_ <= max))
        std::cout << ", default=" << default_;
    std::cout << ": ";

    while (true)
    {
        // Get user's input
        std::string s;
        std::getline( std::cin, s );

        // User chooses default (or wants to quit)
        if (s.empty()) return default_;

        // Get rid of any trailing whitespace
        s.erase( std::find_if_not( s.rbegin(), s.rend(), (int (*)(int))std::isspace ).base(), s.end() );

        // Convert it to integer
        int n;
        std::istringstream ss( s );
        ss >> n;

        // Check to see that all went well
        if (ss.eof() and (n >= min) and (n <= max)) return n;

        // Complain
        std::cout << "That was not an integer in the range [" << min << "," << max << "]. Please try again: ";
    }
    return 0;
}

This code just gives you an idea of how to use it. It also provides an 'out', so that the user can just press ENTER and get a default value (which you can also use to signal that the user just wants to escape, if the default value returns something out of range).


An important note also is that you avoid playing directly with cin and offload as many of the error possibilities to another stream as possible.

This is plenty of information to play with. Good luck!
Okay thank you all, I think I am now starting to get how it all works.
Topic archived. No new replies allowed.