如何验证数字输入 C++
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/514420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to validate numeric input C++
提问by Raúl Roa
I'd like to know how to limit an input value to signed decimals using std::cin
.
我想知道如何使用std::cin
.
采纳答案by Raúl Roa
double i;
//Reading the value
cin >> i;
//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}
This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.
这也给出了输入 -1a2.0 的错误消息,避免将 -1 分配给 i。
回答by arul
If the backing variable of the cin
is a number, and the string provided is not a number, the return value is false, so you need a loop:
如果 的后备变量cin
是数字,而提供的字符串不是数字,则返回值为false,因此需要一个循环:
int someVal;
while(!(cin >> someVal)) {
cin.reset();
cout << "Invalid value, try again.";
}
回答by Michael Kristofik
cin's >> operator works by reading one character at a time until it hits whitespace. That will slurp the whole string -1a2.0
, which is obviously not a number so the operation fails. It looks like you actually have three fields there, -1, a, and 2.0. If you separate the data by whitespace, cin will be able to read each one without problem. Just remember to read a char
for the second field.
cin 的 >> 操作符一次读取一个字符,直到遇到空格。这将吞掉整个 string -1a2.0
,这显然不是数字,因此操作失败。看起来您实际上有三个字段,-1、a 和 2.0。如果用空格分隔数据,cin 将能够毫无问题地读取每个数据。请记住阅读char
第二个字段的 a 。
回答by Eva
Combining the techniques from the top answer hereand thiswebsite, I get
input.h
输入.h
#include <ios> // Provides ios_base::failure
#include <iostream> // Provides cin
template <typename T>
T getValidatedInput()
{
// Get input of type T
T result;
cin >> result;
// Check if the failbit has been set, meaning the beginning of the input
// was not type T. Also make sure the result is the only thing in the input
// stream, otherwise things like 2b would be a valid int.
if (cin.fail() || cin.get() != '\n')
{
// Set the error state flag back to goodbit. If you need to get the input
// again (e.g. this is in a while loop), this is essential. Otherwise, the
// failbit will stay set.
cin.clear();
// Clear the input stream using and empty while loop.
while (cin.get() != '\n')
;
// Throw an exception. Allows the caller to handle it any way you see fit
// (exit, ask for input again, etc.)
throw ios_base::failure("Invalid input.");
}
return result;
}
Usage
用法
inputtest.cpp
输入测试文件
#include <cstdlib> // Provides EXIT_SUCCESS
#include <iostream> // Provides cout, cerr, endl
#include "input.h" // Provides getValidatedInput<T>()
int main()
{
using namespace std;
int input;
while (true)
{
cout << "Enter an integer: ";
try
{
input = getValidatedInput<int>();
}
catch (exception e)
{
cerr << e.what() << endl;
continue;
}
break;
}
cout << "You entered: " << input << endl;
return EXIT_SUCCESS;
}
Sample run
样品运行
Enter an integer: a
Invalid input.
Enter an integer: 2b
Invalid input.
Enter an integer: 3
You entered: 3.
输入一个整数:一个
无效的输入。
输入一个整数:2b
无效输入。
输入一个整数:3
您输入了:3。
回答by Eva
I'm not trying to be rude. I just wanted to share a solution I provided which I believe is more robust and allows for better input validation.
我不是想变得粗鲁。我只是想分享我提供的一个解决方案,我认为它更健壮,并允许更好的输入验证。
Please refer to: My Solution to Input Validation
请参考:我的输入验证解决方案
回答by Notinlist
I tried many techniques for reading integer input from the user using the >>
operator, but in a way or another all my experiments have failed.
我尝试了许多使用>>
运算符从用户读取整数输入的技术,但在某种程度上,我的所有实验都失败了。
Now I think that getline()
function (not the method with the same name on std::istream
) and the strtol()
function from the include cstdlib
is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:
现在我认为该getline()
函数(不是 上的同名方法std::istream
)和strtol()
来自 include的函数cstdlib
是该问题唯一可预测的一致解决方案。如果有人证明我错了,我将不胜感激。这是我使用的类似的东西:
#include <iostream>
#include <cstdlib>
// @arg prompt The question to ask. Will be used again on failure.
int GetInt(const char* prompt = "? ")
{
using namespace std; // *1
while(true)
{
cout << prompt;
string s;
getline(cin,s);
char *endp = 0;
int ret = strtol(s.c_str(),&endp,10);
if(endp!=s.c_str() && !*endp)
return ret;
}
}
- *1: Placing
using namespace whatever;
to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects! - Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
- Be warned that using
>>
andgetline()
in the same program oncin
will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
- *1:放置
using namespace whatever;
到全局范围可能会导致较大项目上的“统一构建”(google!)中断,因此应避免。练习不要使用这种方式,即使是在较小的项目中! - 从文件中读取整数是另一回事。Raúl Roa 的方法如果处理得当的话会很有用。我还建议不应容忍错误的输入文件,但这确实取决于应用程序。
- 请注意
>>
,getline()
在同一个程序中使用和cin
会导致一些问题。只使用其中之一,或谷歌知道如何处理这个问题(不要太难)。
回答by Marcos Lara
Something like:
就像是:
double a;
cin >> a;
Should read your signed "decimal" fine.
应该阅读您签名的“十进制”罚款。
You'll need a loop and some code to make sure it handles invalid input in a sensible way.
您需要一个循环和一些代码来确保它以合理的方式处理无效输入。
Good luck!
祝你好运!