[英]Integer Input Validation in C++
I have a question about input validation in C++. 我对C ++中的输入验证有疑问。 Here is my code I am having trouble with: 这是我遇到麻烦的代码:
#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();
}
}
}
This code works fine unless two invalid entries are made in a row with the second input of the form '12hfhd'. 除非用第二个输入形式“ 12hfhd”连续输入两个无效条目,否则此代码行之有效。 Then it accepts this as input and I can't figure out why. 然后它接受此作为输入,但我不知道为什么。 I have searched on SO and have found a bunch of questions regarding input validation but can't seem to find any about their code accepting certain input. 我在SO上进行搜索,发现了许多有关输入验证的问题,但似乎找不到任何有关接受某些输入的代码的问题。
The main problem is that, when requesting an int
from std::cin
using the >>
operator, a sequence of numeric chars from the beginning of the input will be converted. 主要的问题是,当使用>>
运算符从std::cin
请求一个int
将从输入开始的一系列数字字符转换。 Examples: 例子:
2
will convert to 2
2
将转换为2
75$
will convert to 75
75$
将转换为75
12asdfgh
will convert to 12
12asdfgh
将转换为12
hello,world
will convert to 0
, because the first char is already not a number hello,world
将转换为0
,因为第一个字符已经不是数字 The best thing to do is to use some char
operations: 最好的办法是使用一些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
}
}
I'd use the following approach when dealing with user input: 处理用户输入时,我将使用以下方法:
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 */
}
In words, read a line and then parse and validate it using Boost's lexical_cast()
function template. 换句话说,读取一行,然后使用Boost的lexical_cast()
函数模板进行解析和验证。 Note that the first error, that getline()
fails, happens if someone reads input from a file (eg via shell redirect), but this can also be achieved with certain keypresses, depending on the shell. 请注意,如果有人(例如通过shell重定向)从文件中读取输入,则会发生第一个错误,即getline()
失败,但这也可以通过某些按键操作来实现,具体取决于shell。 This state can't be recovered from, so prompting for a different answer will result in an endless loop. 此状态无法恢复,因此提示输入不同的答案将导致无限循环。
If you look at the documentation of the >> extraction operator , for example here: 如果您查看>>提取运算符的文档,例如:
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
you will notice the following quote: 您会注意到以下报价:
(1) arithmetic types Extracts and parses characters sequentially from the stream to interpret them as the representation of a value of the proper type, which is stored as the value of val. (1)算术类型从流中顺序提取和解析字符,以将它们解释为适当类型的值的表示形式,该类型存储为val的值。
This essentially means that the program will try to treat all the data you pass as formatted in the format specified by the rvalue, in your case int. 从本质上讲,这意味着程序将尝试将您传递的所有数据均以rvalue指定的格式(在您的情况下为int)对待。 Simpler: in your case it will try to make ints of what you're passing into the stream and make the data as 'integerish' as it gets. 更简单:在您的情况下,它将尝试对要传递到流中的内容进行整数化,并使数据变得“整数”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.