Validating User Input

Hi, everyone. I'm having trouble trying to build a function which validates user input as follow... I think I know where the problem is, but I have no idea how to fix it.

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
45
46
47
#include <iostream>
#include <sstream>

float getInt(int &num, std::string prompt, bool condition)
{
	float retInt;
	std::string strNum;
	
	while (true)
	{
		
		std::getline(std::cin, strNum);
		std::stringstream convert(strNum);
		
		if (convert >> retInt && !(convert >> strNum))
		{
			num = std::stoi(strNum);
			if (condition == false)
			{
				return retInt;
			}
			else
			{
				std::cerr << prompt;
			}
		}
		else
		{
			std::cerr << prompt;
		}
		std::cin.clear();
	}
}

int main()
{	
	std::cout << "Enter a number: ";
	std::string prompt = "Bad input. Try again: ";
	int num;
	bool condition = num != 1 && num != 2;
	num = getInt(num, prompt, condition);
	
	std::cout << "num = " << num;
	
	std::cin.get();
	return 0;
}


So in the main function I declare a string, an int and a boolean condition, with which I call the getInt function, which would validate the input. Inside the getInt function I enter a string and I check that.

Then I assign the contents of the string to num, by converting it with stoi. I do that in order for the condition to work, because otherwise "num" wouldn't have a value. And after that it's straightforward.

Everything works great but I feel like the condition doesn't do its job, because whatever I input I always get the prompt printed out or if I change the condition, every single number goes through and that still is not what I want.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>

template< typename CONDITION > int get_int( std::string prompt, CONDITION cond )
{
    std::cout << prompt << ": " ;
    int v ;
    if( std::cin >> v && cond(v) ) return v ; // ok, return value entered by the user

    std::cin.clear() ; // clear possible error state
    std::cin.ignore( 1000, '\n' ) ; // throw away characters in the input buffer
    std::cerr << "invalid input. try again\n" ; // inform the user of the error
    return get_int( prompt, cond ) ; // and try again
}

int main()
{
    int v = get_int( "enter an integer between 1 and 10", // prompt
                     []( int v ) { return v > 0 && v < 11 ; } ) ; // condition
    std::cout << "you entered: " << v << '\n' ;
}
Thanks for answering, your code works, but the problem is that when you enter something like "2asfasf" it will take "2" and still act as if the input is correct and the program will terminate with no error.
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
#include <iostream>
#include <string>
#include <algorithm>

template< typename CONDITION > int get_int( std::string prompt, CONDITION cond )
{
    std::cout << prompt << ": " ;

    std::string line ;
    std::getline( std::cin, line ) ;

    try // stoi may throw on error
    {
        std::size_t pos ;
        const int v = std::stoi( line, std::addressof(pos) ) ;

        // if the entire line was consumed (unparsed part is all white space)
        if( std::all_of( line.begin()+pos, line.end(), [] ( char c ) { return std::isspace(c) ; } )
            && cond(v) ) return v ; // and the condition is satisfied
    }
    catch( const std::exception& ) {}

    std::cerr << "invalid input '" << line << "'. try again\n" ; // inform the user of the error
    return get_int( prompt, cond ) ; // try again
}

int main()
{
    int v = get_int( "enter an integer between 1 and 10", // prompt
                     []( int v ) { return v > 0 && v < 11 ; } ) ; // condition
    std::cout << "you entered: " << v << '\n' ;
}
Yup, now it works perfectly, thanks a lot! :)
Topic archived. No new replies allowed.