我想验证字符串是否为有效整数。我可以使用64位整数和函数,如std::stoull
或std::stoll
,但我无法验证该值是否在给定范围之间。
例如,我想要一个介于0和UINT64_MAX之间的整数。如果字符串为"-1"
,我可以将其转换为long long
,并且我知道它是否定的。但是,如果字符串高于有符号长long (通常为INT64_MAX
)的最大值,则溢出会使其再次为负数,而字符串为正整数。
一位朋友首先建议我检查一个减号,但我不喜欢这个解决方案,然后我考虑使用双,但我知道使用双打的比较可能很棘手,所以这就是为什么我不确定这个解决方案。
template <typename T>
inline bool is_between(const string &str,
T min = numeric_limits<T>::min(),
T max = numeric_limits<T>::max()) noexcept
{
try {
double value = stod(str);
if (value < min || value > max)
return false;
} catch (...) {
return false;
}
return true;
}
这个功能安全吗?因为我害怕一串&#34; 1&#34;可以返回&#34; 0.9999999999&#34;的双倍值,然后它将不适合1到100之间的间隔。
然后我们可以使用这样的函数:
cout << is_between<uint16_t>("0") << endl;
cout << is_between<uint16_t>("65535") << endl;
cout << is_between<uint16_t>("65535", 0, 2000) << endl;
cout << is_between<uint16_t>("-1") << endl;
cout << is_between<uint16_t>("800000") << endl;
答案 0 :(得分:2)
您的函数对于您描述的错误是安全的,因为足够小的整数可以用浮点数精确表示。因此,1
的转换不能为0.99999
,因为如果0.99999
可以用双精度表示,则它们是不同的数字。可以将0.99999
转换为1
。
但是,如果数量足够大,则限制检查不起作用,因为64位双精度对于小数部分而言比64位整数具有更少的位(通常为54,但在标准中未定义)。例如,以下程序的输出为1
而不是0
,就像它具有更高的精确数一样。
#include <iostream>
#include <string>
int main(){
long long v=(1l << 54) +1;
std::cout << v-static_cast<long long>(std::stod(std::to_string(v))) << std::endl;
}
如果您真的需要接近UINT64_MAX
的数字,最好使用像Boost multiprecision这样的库。它具有任意精度整数cpp_int
,可以从std::string
构造。