下面是一个演示这个问题的简单程序。
#include <iostream>
using namespace std;
double d;
int main() {
cin >> d;
if (cin.fail()) {
cout << "Input is invalid" << endl;
}
else {
cout << d << endl;
}
return (0);
}
输入像adsfasdf
或!@#$!*@#(&Adf
这样的值会打印出Input is invalid
。输入像13.52
这样的数值返回13.52
,也如预期的那样。
但是输入以数字开头,后面跟着字符串的东西,比如13.52asdfasdf!#@$!@#$!#A
打印出13.52
。那么为什么这种输入不打印Input is invalid
呢?
我如何让这个输入被视为无效,而不是仅仅打印数字部分?
在c++中,当你尝试从流中读取一个值时,它会从流中读取尽可能多的值,只要它符合预期的格式,其他的都不动。如果读取根本无法读取任何值,那么它将在流上设置失败位。这就解释了为什么如果你输入的是总垃圾,你会得到一个错误,而如果你输入一个数字后面跟着垃圾,你会读到有效的数据,但仍然有垃圾留在流中。
解决这个问题的一种方法是使用std::getline
函数从cin
读取一行文本,这将获取用户输入的所有内容,然后通过std::istringstream
运行它来解析它。这里有一种方法,基于我们在斯坦福大学的介绍课上使用的一些代码:
int readInt() {
while (true) {
std::string input;
std::getline(cin, input); // Read a line of text from the user
/* Set up an istringstream to read the data */
std::istringstream converter(input);
/* Try to read an int. If we succeed, make sure there wasn't
* any trailing data.
*/
int value;
if (converter >> value) {
char leftover;
if (converter >> leftover) {
std::cout << "Please enter an integer." << std::endl;
} else {
return value;
}
} else {
std::cout << "Please enter an integer." << std::endl;
}
}
}
你可以很容易地自定义/模板化它来读取任何类型的数据。