how to ensure an input is an integer?

int age;
cout << "how old are you?" << endl;
cin >> age;


how could i edit this to make sure the age is actually an integer?
This is actually quite difficult and really requires some advanced C++ knowledge. The issue is that for stream extraction (>>) if a non-int is entered then the stream enters a fail state which has to be dealt with, then the input re-obtained etc.

To do this, something like:

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 <string>
#include <iostream>
#include <type_traits>
#include <charconv>

template<typename T = int>
typename std::enable_if_t< std::is_arithmetic_v<T>, T>
getInp(const std::string& prm) {
	T num {};

	for (std::string inp;;) {
		std::cin.clear();
		std::cout << prm;

		if (std::getline(std::cin, inp) && !inp.empty()) {
			const auto first {std::find_if(inp.begin(), inp.end(), [](unsigned ch) {return !std::isspace(ch); })};
			const auto end {std::find_if(inp.rbegin(), inp.rend(), [](unsigned ch) {return !std::isspace(ch); }).base()};
			const auto res {std::from_chars(std::to_address(first), std::to_address(end), num)};

			if (res.ec == std::errc {} && res.ptr == std::to_address(end))
				return num;
		}

		std::cout << "Invalid input. Not a(n) " << typeid(T).name() << '\n';
	}
}

int main() {
	const auto age {getInp("How old are you: ")};

	std::cout << "You are " << age << " years old\n";
}



How old are you:    q 45
Invalid input. Not a(n) int
How old are you:    45   e
Invalid input. Not a(n) int
How old are you: 0
You are 0 years old


Just treat getInp as a function that takes a string value for a prompt and returns a number of the requested type (default int).

if you wanted say age to be a double, then you'd use:

 
const auto age {getInp<double>("How old are you: ")};

Last edited on
The variable age will always be an int. What could happen is that the read operation cin >> age fails.

To check if it failed you can do:
1
2
3
4
5
cin >> age;
if (cin.fail())
{
	cout << "You didn't enter a valid integer!\n";
}
or
1
2
3
4
5
cin >> age;
if (!cin)
{
	cout << "You didn't enter a valid integer!\n";
}
or my preferred way:
1
2
3
4
if (!(cin >> age))
{
	cout << "You didn't enter a valid integer!\n";
}
(these will do the same thing)

After a read operation has failed the fail flag is set to true (cin.fail() returns true) and will cause any further attempt to read input from the user to also fail. In order to start reading again you need to clear the fail flag. This you can do by calling cin.clear(). You probably also want to remove the old input (unless you want to try and read the same input again in another way). You can use the ignore function for that.

The following code will keep asking for the age until the user has entered a valid integer:
1
2
3
4
5
6
7
8
9
int age;
cout << "How old are you? ";
while (!(cin >> age))
{
	cout << "Invalid age! Try again: ";
	cin.clear(); // clear fail flag
	cin.ignore(numeric_limits<streamsize>::max(), '\n'); // discard the whole line
}
cout << "Your are " << age << " years old!\n";

You might of course want to do more validation for things like negative numbers and such but this is a start.
Last edited on
Note that >> will extract a valid value if any can be extracted. So if the input is 75y then 75 will be successfully extracted leaving y in the input stream for next time extraction.

This may or may not be what is required. My code above will reject everything except a valid number (and spaces) on one line. Again, this may or may not be what is required.
That's why I said you might want to do more validation. You could call getline and check if there is any left over characters on the line and reject the input if there is (possibly ignoring whitespace) but it quickly becomes quite complicated.

If you don't care whether the user enters "75", "75y" or "75whatever" you could just call cin.ignore(numeric_limits<streamsize>::max(), '\n'); after you have successfully read the age too. This prevents any additional characters at the end of the line from interfering with future read operations. It's also an approach you can use if you want to mix >> and getline.

There are obviously many ways to do these things...
Last edited on
is there perhaps a simpler version where i could have something like this?:

bool cont = true;
string ageString;
int age;
cin >> ageString;
while cont == true
<>if age has a letter or symbol - how would i do this bit?
<><>"Please enter numbers only!" << endl;
<><>cin >> ageString;
<>else
<><>cont == false;

age = stoi(ageString);
User input is never "simple".

To do it correctly, understand that the user will press Enter after every prompted input. Get all input as a string, then try to convert the string to whatever it is you want (such as an int).

Here is my current example/response to validating user input:
https://stackoverflow.com/a/71135692/2706707
Topic archived. No new replies allowed.