Input Validation Loops: Strange Behavior

I don't understand why my console spams a bunch of couts when I input a character instead of a value. It works perfectly fine if I input a value not within the range (e.g. if I enter a number greater than 100 or less than 1, the input validation loop will inform me of an error. Inputting a string causes the console to be spammed with a bunch of couts). I thought characters are just "special" integer values.

1
2
3
4
5
6
7
8
9
cout << "Enter the value of resistor 1: ";
cin >> res1;
// resistor 1 input validation
while (res1 > 100 || res1 < 1)
{
    cout << "Invalid value for this resistor! Please ensure "
 		 << "that the value is between 1-100 Ohms! ";
 	cin >> res1;
}
Last edited on
When you use cin >> and type a non-number string when it expects a number, it puts your input stream (cin) into a bad state, where it will no longer accept input.

Here is the magical incantation to clear any errors from your input stream, and reset its state:

1
2
3
4
5
6
#include <limits>

// ...

cin.clear(); // clear error flag
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // ignores remainder of stream 


For example:
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
// Example program
#include <iostream>
#include <limits>

int main()
{
    using namespace std;
    
    double res1 = 0.0;
    
    cout << "Enter the value of resistor 1: ";
    cin >> res1;
    
    while (res1 > 100 || res1 < 1)
    {
        cout << "Invalid value for this resistor! Please ensure "
     		 << "that the value is between 1-100 Ohms! ";
     		 
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
	 
     	cin >> res1;
    }

    cout << "Resistor value has been validated\n";
}
Last edited on
Ah, thanks! However, would it be better to use <climits> instead? I thought limits is a deprecated C header
No, <limits> is the modern, C++ header.
<climits> is the equivalent of the <limits.h> C header.
The code will not compile as-is if you use <climits>.

Notice the c on the front. You'll see this pattern in headers like <cmath>, <cstdlib>, <cctype> etc. Those are all headers carried over from C. <climits> is by no means deprecated though; it will be supported by the standard for the foreseeable future, but it uses less-type-safe macros to achieve the same thing that <limits> can achieve.
Last edited on
Type-safe macros? No clue what that is and I think that's beyond my league at the moment, so I'll just follow your advice for now. Thanks again!
cin is how C++ interacts with standard input, which is essentially a buffer (storage, like you said) where the user or system feeds things into, and then get processed by your program.

When something goes wrong with this input stream, it gets put into a bad state where it will no longer accept input. cin.clear() clears any failure flags in the cin stream. So, OK, now cin will accept more input and once again attempt to feed that input into your variables.

But there could still be junk in your stream's buffer. For example, if you type in "blahdkdf dfadsf badfdslj", the first cin >> number; consumed the "blahdkdf" word, but the rest of the text is still in cin's buffer, waiting to be used.

That's where the cin.ignore() call comes in.

numeric_limits<streamsize>::max() is saying "ignore up to the maximum possible size that the stream itself could be", just in case the user typed a really long message in.

'\n' is saying ignore (discard) up until the next newline in the buffer, which would happen when the user presses enter to send the text.

So together, it clears any bad/remaining input from the previous thing you typed, to put your input stream in a fresh state.

_________________________________________

Type-safe macros
I just meant that, in general, one disadvantage of macros is that they can be less type-safe if not implemented carefully.
1
2
3
4
5
6
7
8
9
10
11
// Example program
#include <iostream>

#include <climits>
#include <limits>

int main()
{
    std::cout << sizeof(CHAR_MAX) << '\n';
    std::cout << sizeof(std::numeric_limits<char>::max()) << '\n';
}

will output:
4
1

because CHAR_MAX is just macro for an int literal, while std::numeric_limits<char>::max() is an actual char that is the maximum value that a char can be.

<limits> can also be used with templates easier, because you can insert any type into numeric_limits<T>.

[A lot of C++ features are like this; a bit more verbose than C but also safer and more extendable.]
Last edited on
Topic archived. No new replies allowed.