我听说我应该使用strtol
代替atoi
,因为它有更好的错误处理能力。我想看看我是否可以使用此代码来检查字符串是否为整数:
#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;
}
我将ANYTHING
替换为5
并且效果很好:
testString = 5
errno = 0
Success.
testInt = 5
当我使用2147483648
,最大可能的int + 1时,它会返回:
testString = 2147483648
errno = 34
There was an error.
testInt = 2147483647
足够公平。但是,当我使用Hello world!
进行尝试时,会出现这种情况:
testString = Hello world!
errno = 0
Success.
testInt = 0
我打算在这做什么?请不要给我一些简单的东西,比如验证字符串是int。
使用:GNU GCC编译器,Code :: Blocks,Windows
“g ++遵循C ++ 11 ISO C ++语言标准[-std = c ++ 11]”已经在“编译器标志”中进行了检查。
答案 0 :(得分:3)
strtol在第一个非数字
上停止但如果您阅读了手册页http://man7.org/linux/man-pages/man3/strtol.3.html,则可以看到
如果endptr不为NULL,则strtol()存储第一个地址 * endptr中的无效字符。如果根本没有数字, strtol()将nptr的原始值存储在* endptr中(并返回 0)。 特别是,如果* nptr不是&#39; \ 0&#39;但是** endptr是&#39; \ 0&#39;上 返回,整个字符串有效。
即
string testString = "ANYTHING";
cout << "testString = " << testString << endl;
char *endptr;
int testInt = strtol(testString.c_str(),&endptr,0);
if(**endptr)
cout << "bad input";
答案 1 :(得分:2)
根据the man page of 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 == '\0';
}
在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
并简化代码。
答案 2 :(得分:0)
不要使用带有异常的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 (reference),其中包含空字符串。
编辑: 如果必须处理溢出,请使用上面的异常版本。只有您不能使用例外时才使用:
#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()));
}