![]() |
EFNet #C++ FAQ
Performing input validation |
In general, programs are supposed to make things easier for users. Spitting out an offensive error message if the user makes an innocent mistake is usually a poor design, and contributes to the intimidation of new computer users. That having been said, it is often the case where the restrictions on user input are laid down by a class assignment or other criteria, so this section will explain how to implement them.
The simplest approach to take involves using the formatted I/O operations in the C++ standard library. For example, if you want to input an integer from the user, you can use cin's integer extractor to read the value. This will fail if the user enters something that cannot be parsed as an integer.
#include <iostream> using namespace std; int main() { int x = 0; cout << "Enter an integer: "; if (! (cin >> x)) cout << "Not an integer.\n"; else cout << "You entered: " << x << "\n"; return 0; }
You might, however, want to require that the input consist of _only_ an integer, with no trailing characters. The way to do this is to use the unformatted input operation 'ignore()' and check the extraction count. You specify that you want to ignore all characters until the end of the line (the newline character) and then check to see that the extraction count is not greater than 1 (the extraction count includes the newline character, which is extracted from the buffer).
#include <iostream> #include <limits> using namespace std; int main() { int x = 0; cout << "Enter an integer: "; cin >> x; cin.ignore(numeric_limits<int>::max(), '\n'); if (!cin || cin.gcount() != 1) cout << "Not an integer.\n"; else cout << "You entered: " << x << "\n"; return 0; }
Inputting strings is fairly simple, using the std::getline function. If you are using MSVC, you may need to patch your getline function, see the notes about this at Microsoft Support.
#include <string> #include <iostream> using namespace std; int main() { cout << "Enter a string: "; string s(""); getline(cin, s); if (!cin) cout << "Failed to read input.\n"; else cout << "You entered: " << s << "\n"; return 0; }
If you need to loop until the user enters something acceptable, you may need to clear fail conditions out of your input stream each iteration. The following example shows how to loop input until the user enters a integer between 6 and 31, and then loop input until the user enters a string containing more than fifteen letters.
#include <iostream> #include <string> #include <limits> using namespace std; int main() { // Integer between 6 and 31 int i(0); bool valid(false); while (!valid) { cout << "Enter an integer between 6 and 31: "; int x(0); cin >> x; if (cin) // an int was read { cin.ignore(numeric_limits<int>::max(), '\n'); if (cin.gcount() == 1) // nothing followed the int { if ((x >= 6) && (x <= 31)) { i = x; valid = true; } } } else // input failed { cin.clear(); cin.ignore(numeric_limits<int>::max(), '\n'); } } // String longer than 15 letters string s(""); valid = false; while (!valid) { cout << "Enter a string of more than 15 letters: "; string x(""); getline(cin, x); if (cin) // a line was read { if (x.size() > 15) { s.assign(x); valid = true; } } else // input failed { cin.clear(); cin.ignore(numeric_limits<int>::max(), '\n'); } } cout << "Your number was " << i << "\n"; cout << "Your string was " << s << "\n"; return 0; }