问题
What is the best way in C++11 (ie. using C++11 techniques) to validate cin input? I've read lots of other answers (all involving cin.ignore, cin.clear, etc.), but those methods seem clumsy and result in lots of duplicated code.
Edit: By 'validation', I mean that both well-formed input was provided, and that it satisfies some context-specific predicate.
回答1:
I'm posting my attempt at a solution as an answer in the hopes that it is useful to somebody else. It is not necessary to specify a predicate, in which case the function will check only for well-formed input. I am, of course, open to suggestions.
//Could use boost's lexical_cast, but that throws an exception on error,
//rather than taking a reference and returning false.
template<class T>
bool lexical_cast(T& result, const std::string &str) {
std::stringstream s(str);
return (s >> result && s.rdbuf()->in_avail() == 0);
}
template<class T, class U>
T promptValidated(const std::string &message, std::function<bool(U)> condition = [](...) { return true; })
{
T input;
std::string buf;
while (!(std::cout << message, std::getline(std::cin, buf) && lexical_cast<T>(input, buf) && condition(input))) {
if(std::cin.eof())
throw std::runtime_error("End of file reached!");
}
return input;
}
Here's an example of its usage:
int main(int argc, char *argv[])
{
double num = promptValidated<double, double>("Enter any number: ");
cout << "The number is " << num << endl << endl;
int odd = promptValidated<int, int>("Enter an odd number: ", [](int i) { return i % 2 == 1; });
cout << "The odd number is " << odd << endl << endl;
return 0;
}
If there's a better approach, I'm open to suggestions!
回答2:
If by validation you mean that when you want an int
you want to know if an int
was really entered, then just put the input in an if
condition:
int num;
while (!(std::cin >> num))
{
std::cout << "Whatever you entered, it wasn't an integer\n";
}
std::cout << "You entered the integer " << num << '\n';
来源:https://stackoverflow.com/questions/17864877/c11-cin-input-validation