C++:使用 "strtol" 检查字符串是否为有效整数
C++: check if string is a valid integer using "strtol"
我听说我应该使用strtol
而不是atoi
,因为它可以更好地处理错误。我想通过查看是否可以使用此代码来检查字符串是否为整数来测试strtol
:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
string testString = "ANYTHING";
cout << "testString = " << testString << endl;
int testInt = strtol(testString.c_str(),NULL,0);
cout << "errno = " << errno << endl;
if (errno > 0)
{
cout << "There was an error." << endl;
cout << "testInt = " << testInt << endl;
}
else
{
cout << "Success." << endl;
cout << "testInt = " << testInt << endl;
}
return 0;
}
我用5
替换了ANYTHING
,它工作得很好:
testString = 5
errno = 0
Success.
testInt = 5
当我使用2147483648
执行此操作时,最大可能的int
+ 1 (2147483648),它返回以下内容:
testString = 2147483648
errno = 34
There was an error.
testInt = 2147483647
很公平。但是,当我尝试使用Hello world!
时,它错误地认为它是一个有效的int
并返回0
:
testString = Hello world!
errno = 0
Success.
testInt = 0
笔记:
- 我正在使用 Code::Blocks with GNU GCC Compiler on Windows
- "让 g++ 遵循 C++11 ISO C++ 语言标准 [-std=c++11]"在"编译器标志"中选中。
根据strtol
的手册页。您必须定义您的函数,例如:
bool isNumeric(const std::string& str) {
char *end;
long val = std::strtol(str.c_str(), &end, 10);
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) {
// if the converted value would fall out of the range of the result type.
return false;
}
if (end == str) {
// No digits were found.
return false;
}
// check if the string was fully processed.
return *end == ' ';
}
在 C++11 中,我更喜欢使用std::stol
而不是std::strtol
,例如:
bool isNumeric(const std::string& str) {
try {
size_t sz;
std::stol(str, &sz);
return sz == str.size();
} catch (const std::invalid_argument&) {
// if no conversion could be performed.
return false;
} catch (const std::out_of_range&) {
// if the converted value would fall out of the range of the result type.
return false;
}
}
std::stol
调用std::strtol
,但您直接使用std::string
并且代码得到了简化。
strtol 在第一个非数字上停止
但是,如果您阅读手册页 http://man7.org/linux/man-pages/man3/strtol.3.html 您可以看到
如果 endptr 不是 NULL,strtol() 存储第一个的地址 *endptr 中的字符无效。 如果根本没有数字, strtol() 将 NPTR 的原始值存储在 *endptr 中(并返回 0).特别是,如果 *nptr 不是 '\0' 但 **endptr 是 '\0' 返回,则整个字符串有效。
即
string testString = "ANYTHING";
cout << "testString = " << testString << endl;
char *endptr;
int testInt = strtol(testString.c_str(),&endptr,0);
if(**endptr)
cout << "bad input";
不要使用 C++11 方式解决方案,因为它速度较慢。这是一个快速的 C++11 版本:
#include <algorithm>
bool is_decimal(const std::string& s)
{
return !s.empty() && std::find_if(s.begin(), s.end(), [](char c){ return !std::isdigit(c); }) == s.end();
}
如果您确定字符串大部分不为空,则可以删除!s.empty()。如果你不是,请保留它,因为!s.empty()(!(s.length()==0)) 比使用空字符串调用find_if(引用)便宜。
编辑: 如果必须处理溢出,请使用上面的异常版本。仅当您不能使用异常时才使用以下命令:
#include <string>
#include <sstream>
#include <limits>
template <class T>
bool is_decimal_and_fit(const std::string& s)
{
long double decimal = 0;
return (!(std::istringstream(s) >> decimal).fail() && (decimal >= std::numeric_limits<T>::lowest()) && (decimal <= std::numeric_limits<T>::max()));
}
- 如果变量名称不跟在 char* 后面,const char* 是否有效?
- 钳制迭代器是否有效
- 检查由括号、方括号和大括号组成的一组方括号是否有效?
- 在函数内创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- 模板签名解析为 void(void) 被 GCC 拒绝;这是否有效C++?
- 我如何知道作为参数的size_t在函数中是否有效?
- 我的运算符重载是否有效<<(流插入)左操作数不是 ostream
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 此递归模板类型定义是否有效C++?
- 将 C 函数转换为 C++ 以检查数字是否有效
- 函数参数的名称与调用函数时使用的变量相同是否有效?
- 如何检查输入是否有效?
- 如何检查用户的输入是否有效以及我正在寻找的数字?
- 在函数中按值传递 unordered_map/unordered_set 是否有效? C++
- 如何检查isupper(cstr)是否有效?
- 将 std::transform 与 std::back_inserter 一起使用是否有效?
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 如何检查字符串格式在读取C++文本文件时是否有效?
- 在 c++ 中将对象设置为等于同一类的构造函数是否有效?
- 创建加密安全密码.并验证它是否有效