检查 C++ 输入是否为整数的现代方法
Modern Way of checking if C++ input is integer or not
我想添加用户无法在 reg 中输入非整数值的签入我的 c++ 代码。如果他输入,则会再次提示他。我在 2011 年 (How to check if input is numeric in C++) 的堆栈溢出中看到了解决方案。现在有一些现代的或好的方法还是一样?
我尝试在 ctype.h
中使用 ifdigit()
// Example program
#include <iostream>
#include <ctype.h>
using namespace std;
int main()
{
int x;
cout<<"Type X";
cin>>x;
if(!isdigit(x))
{
cout<<"Type Again";
cin>>x;
}
}
但没用
这是我要添加检查的实际问题。
cout << "Type Reg # of Student # " << i + 1 << endl;
do
{
cin >> arr[i][j];
} while (arr[i][j] < 999 || arr[i][j] > 9999);
其中 i 和 j 在十二月。在 for 循环中。我只想添加检查输入是否不是字符串或类似的东西。不能依赖 2011 年的答案
看看下面的例子。
所有魔法都发生在 to_num()
内部,它将处理数字前后的白色 space。
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
auto to_num(const std::string& s)
{
std::istringstream is(s);
int n;
bool good = (is >> std::ws >> n) && (is >> std::ws).eof();
return std::make_tuple(n, good);
};
int main()
{
int n;
bool good;
std::cout << "Enter value: ";
for(;;)
{
std::string s;
std::getline(std::cin, s);
std::tie(n, good) = to_num(s);
if(good) break;
std::cout << s << " is not an integral number" << std::endl;
std::cout << "Try again: ";
}
std::cout << "You've entered: " << n << std::endl;
return 0;
}
解释里面发生了什么to_num()
:
(is >> std::ws >> n)
从 is
中提取(可选)前导白色 space 和一个整数。在布尔上下文中,is
的 operator bool() 将启动,如果提取成功,return 为真。
(is >> std::ws).eof()
提取(可选)尾随白色 space 并且如果末尾没有垃圾则 return 为真。
更新
这里是使用 c++17 中可用的 Structured binding declaration and Class template argument deduction 的稍微更简洁的版本:
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
auto to_num(const std::string& s)
{
std::istringstream is(s);
int n;
bool good = (is >> std::ws >> n) && (is >> std::ws).eof();
return std::tuple(n, good); // look ma, no make_tuple
};
int main()
{
std::cout << "Enter value: ";
for(;;)
{
std::string s;
std::getline(std::cin, s);
auto [n, good] = to_num(s); // structured binding
if(good)
{
std::cout << "You've entered: " << n << std::endl;
break;
}
else
{
std::cout << s << " is not an integral number" << std::endl;
std::cout << "Try again: ";
}
}
return 0;
}
如果你正确处理错误,你最终会得到一个提示/输入循环,看起来像这样:
#include <iostream>
#include <limits>
int getInput() {
while (true) {
std::cout << "Please enter a number between 80 and 85: ";
int number = 0;
std::cin >> number;
std::cout << "\n";
if (std::cin.eof()) {
std::cout << "Unexpected end of file.\n";
std::cin.clear();
continue;
}
if (std::cin.bad() || std::cin.fail()) {
std::cout << "Invalid input (error reading number).\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (number < 80 || number > 85) {
std::cout << "Invalid input (number out of range).\n";
continue;
}
return number;
}
// unreachable
return 0;
}
int main() {
int number = getInput();
std::cout << number << std::endl;
}
如果不需要,我们可以省略范围检查。
我们将 std::cin.eof()
(例如,用户在 Windows 上按 ctrl+Z)与其他条件分开处理,因为对于 eof 没有什么可忽略的。
这遵循空白和数字转换的标准 C++ 流行为(即,它将接受带有额外空白的输入,或仅以数值开头的输入)。
如果我们想要更好地控制我们想要接受的内容,或者不希望转换依赖于语言环境,我们必须使用 std::getline
从 std::cin
读取输入,然后自己进行字符串转换(使用 std::stringstream,如 , or using std::strtol
, or std::from_chars
)。
我想添加用户无法在 reg 中输入非整数值的签入我的 c++ 代码。如果他输入,则会再次提示他。我在 2011 年 (How to check if input is numeric in C++) 的堆栈溢出中看到了解决方案。现在有一些现代的或好的方法还是一样?
我尝试在 ctype.h
中使用 ifdigit()// Example program
#include <iostream>
#include <ctype.h>
using namespace std;
int main()
{
int x;
cout<<"Type X";
cin>>x;
if(!isdigit(x))
{
cout<<"Type Again";
cin>>x;
}
}
但没用
这是我要添加检查的实际问题。
cout << "Type Reg # of Student # " << i + 1 << endl;
do
{
cin >> arr[i][j];
} while (arr[i][j] < 999 || arr[i][j] > 9999);
其中 i 和 j 在十二月。在 for 循环中。我只想添加检查输入是否不是字符串或类似的东西。不能依赖 2011 年的答案
看看下面的例子。
所有魔法都发生在 to_num()
内部,它将处理数字前后的白色 space。
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
auto to_num(const std::string& s)
{
std::istringstream is(s);
int n;
bool good = (is >> std::ws >> n) && (is >> std::ws).eof();
return std::make_tuple(n, good);
};
int main()
{
int n;
bool good;
std::cout << "Enter value: ";
for(;;)
{
std::string s;
std::getline(std::cin, s);
std::tie(n, good) = to_num(s);
if(good) break;
std::cout << s << " is not an integral number" << std::endl;
std::cout << "Try again: ";
}
std::cout << "You've entered: " << n << std::endl;
return 0;
}
解释里面发生了什么to_num()
:
(is >> std::ws >> n)
从is
中提取(可选)前导白色 space 和一个整数。在布尔上下文中,is
的 operator bool() 将启动,如果提取成功,return 为真。(is >> std::ws).eof()
提取(可选)尾随白色 space 并且如果末尾没有垃圾则 return 为真。
更新
这里是使用 c++17 中可用的 Structured binding declaration and Class template argument deduction 的稍微更简洁的版本:
#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
auto to_num(const std::string& s)
{
std::istringstream is(s);
int n;
bool good = (is >> std::ws >> n) && (is >> std::ws).eof();
return std::tuple(n, good); // look ma, no make_tuple
};
int main()
{
std::cout << "Enter value: ";
for(;;)
{
std::string s;
std::getline(std::cin, s);
auto [n, good] = to_num(s); // structured binding
if(good)
{
std::cout << "You've entered: " << n << std::endl;
break;
}
else
{
std::cout << s << " is not an integral number" << std::endl;
std::cout << "Try again: ";
}
}
return 0;
}
如果你正确处理错误,你最终会得到一个提示/输入循环,看起来像这样:
#include <iostream>
#include <limits>
int getInput() {
while (true) {
std::cout << "Please enter a number between 80 and 85: ";
int number = 0;
std::cin >> number;
std::cout << "\n";
if (std::cin.eof()) {
std::cout << "Unexpected end of file.\n";
std::cin.clear();
continue;
}
if (std::cin.bad() || std::cin.fail()) {
std::cout << "Invalid input (error reading number).\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
if (number < 80 || number > 85) {
std::cout << "Invalid input (number out of range).\n";
continue;
}
return number;
}
// unreachable
return 0;
}
int main() {
int number = getInput();
std::cout << number << std::endl;
}
如果不需要,我们可以省略范围检查。
我们将 std::cin.eof()
(例如,用户在 Windows 上按 ctrl+Z)与其他条件分开处理,因为对于 eof 没有什么可忽略的。
这遵循空白和数字转换的标准 C++ 流行为(即,它将接受带有额外空白的输入,或仅以数值开头的输入)。
如果我们想要更好地控制我们想要接受的内容,或者不希望转换依赖于语言环境,我们必须使用 std::getline
从 std::cin
读取输入,然后自己进行字符串转换(使用 std::stringstream,如 std::strtol
, or std::from_chars
)。