我对C ++中的输入验证有疑问。这是我遇到问题的代码:
#include <iostream>
using namespace std;
int main()
{
int in;
while(true)
{
if(cin >> in)
{
if(in < 0 || in > 2)
{
cout << "Invalid input. Number needs to be 0, 1, or 2.";
cin.clear();
while(cin.get() != '\n');
cin.ignore();
}
else
{
cout << "Output: " << in;
break;
}
}
else
{
cout << "Invalid input. Please enter a number.";
cin.clear();
while(cin.get() != '\n');
cin.ignore();
}
}
}
此代码正常工作,除非使用表格&#39; 12hfhd&#39;的第二个输入连续创建两个无效条目。然后它接受这个作为输入,我无法弄清楚原因。我搜索了SO并找到了一些关于输入验证的问题,但似乎无法找到任何有关其代码接受某些输入的信息。
答案 0 :(得分:6)
主要问题是,当使用int
运算符从std::cin
请求>>
时,将转换输入开头的一系列数字字符。例子:
2
将转换为2
75$
将转换为75
12asdfgh
将转换为12
hello,world
会转换为0
,因为第一个字母已经不是数字最好的办法是使用一些char
操作:
int getNumber() {
char input;
std::cin >> input;
if(input > '2' || input < '0') { // yes, chars act like ASCII numbers
// handle this problem
return -1; //error
} else {
return int(input - '0'); // input's code - '0''s code = number
}
}
答案 1 :(得分:0)
在处理用户输入时我会使用以下方法:
string l;
if(!getline(cin, l))
/* handle error that no input could be read at all */
try
{
int const res = boost::lexical_cast<int>(l);
/* numerically validate input here */
return res;
}
catch(exception const&)
{
/* handle parsing error here */
}
单词中,读取一行,然后使用Boost的lexical_cast()
函数模板进行解析和验证。请注意,如果有人从文件中读取输入(例如,通过shell重定向),则会发生getline()
失败的第一个错误,但这也可以通过某些按键来实现,具体取决于shell。此状态无法恢复,因此提示输入不同的答案将导致无限循环。
答案 2 :(得分:0)
如果您查看&gt;&gt;的文档提取运算符,例如:
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
你会注意到以下引用:
(1)算术类型 从流中按顺序提取和解析字符,将它们解释为正确类型值的表示, 它存储为val的值。
这实际上意味着程序将尝试将您传递的所有数据视为以rvalue指定的格式进行格式化,在您的情况下为int。更简单:在您的情况下,它会尝试对您传入流中的内容进行整理,并使数据变为“整数”。