Client input check

I have the template to get user input in a console application, I found out that this acually allow this to happen:
 
int age = GetUserInput<int>("please tell me your age: ");

it will accept even the user typed in a char, string, and so on... as long as the bits can be interpreted as int, I wounder how can I check if the client actually typed in an int.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	template<typename T>
	T GetUerInput(std::string info, std::string errorIfWrongType = "You didn't give me what I am asking for..\n Please Try Again:")
	{
		std::cout << info << "\n";
		T input;
		if (std::cin.fail())
		{
			input = GetUerInput<T>(errorIfWrongType);
		}
		else
		{
			std::cin >> input;
		}
		return input;
	}


Thanks,
Try

 
isdigit(input);


You'll need to include <cctpe>.
See more about isdigit() here: http://www.cplusplus.com/reference/cctype/isdigit/
Last edited on
There are various approaches to input validation, I find the following particularly robust - it checks leading and following characters, white-space and because it uses getline() the newline character is not left in the stream for later clear-up. You can wrap it in a function and call that function in just one statement:
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
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    bool fQuit = false;
    while (!fQuit)
    {
        std::cout << "Give me an integer ONLY\n";
        std::string choice;
        getline (std::cin, choice);
        std::stringstream stream(choice);
        int int_choice;
        if(!(stream>>int_choice) || stream.peek() != std::char_traits<int>::eof())
        {
            std::cout<<"Incorrect entry, try again\n";
        }
        else
        {
            std::cout << "Succes!!\n";
            fQuit = true;
            break;
        }
    }
}

Regex (http://www.cplusplus.com/reference/regex/) can also be used as an alternative for input validation through the following steps:

1. create a std::regex object that defines the pattern to be matched
2. pass the target to be matched to the program (here through std::cin)
3. call the regex algorithm regex_match with the arguments from 2 and 1 above respectively
4. if regex_match() only then pass the target to std::stringstream to create the integer (notice the difference with previous approach where we pass the object to stringstream first to check if it is an int or not)

Now the code and then some additional explanation on creating the appropriate regex object:
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
#include <iostream>
#include <sstream>
#include <string>
#include <regex>

int main()
{
    int int_good;
    std::regex int_checker("(\\+|-)?[[:digit:]]+");
    bool fQuit = false;
    while (!fQuit)
    {
        std::cout << "Give me an integer ONLY\n";
        std::string choice;
        getline (std::cin, choice);
        if(regex_match(choice,int_checker))
        {
            std::stringstream stream(choice);
            stream >> int_good;
            fQuit = true;
            std::cout << "Done! Got: " << int_good << '\n';
        }
        else
        {
            std::cout << "Try again!\n";
        }
    }
}

How to create the regex object for input int validation:
1
2
3
4
5
6
7
8
9
(\\+|-)?[[:digit:]]+
	- (\\+|-)
		- (...): creates a sub-pattern group ...
		- \\+|-: ... to check for leading + or -  
		- ?: tests if first position is + or - 
	- [[:digit:]]+
		- [...]: creates a character class i.e. a category of characters to be matched ...
		- [:digit:] ..' which in this case is the decimal (single) digit character class 
		- + : extends the regex to a string of digits 

The above is a brief outline though and there are some additional details in the expression like escape characters that I haven't touched upon. Regex is a very powerful tool and do it look-up if you found this useful.




Last edited on
Topic archived. No new replies allowed.