我有以下字符串:
sThis = "2154910440";
unsigned int iStart=atoi(sThis.c_str());
然而结果是
iStart = 2147483647
有人看到我的错误吗?
我有以下字符串:
sThis = "2154910440";
unsigned int iStart=atoi(sThis.c_str());
然而结果是
iStart = 2147483647
有人看到我的错误吗?
atoi
将字符串转换为int
. 在您的系统上,anint
为 32 位,其最大值为 2147483647。您尝试转换的值超出此范围,因此返回值atoi
未定义。int
我猜,您的实现在这种情况下会返回 an 的最大值。
您可以改为使用atoll
,它返回一个 long long ,保证至少为 64 位。或者,您可以使用该stoi/stol/stoll
系列中的一个函数,或者它们的无符号对应函数,这实际上会以异常的形式提供有关超出范围值(和无效值)的有用错误报告。
就个人而言,我喜欢boost::lexical_cast
. 尽管它看起来有点麻烦,但它可以在更一般的上下文中使用。您可以在模板中使用它,只需转发类型参数,而不必进行专门化
您应该改用std::strtoul
, found in <cstdlib>
,它专为无符号数设计,范围更大,报告错误更好。
如果您想使用std::string
输入和异常处理错误,请使用std::stoul
. 一个简短、高效的实现如下:
#include <string>
#include <stdexcept>
inline unsigned int stoui(const std::string& s)
{
unsigned long lresult = stoul(s, 0, 10);
unsigned int result = lresult;
if (result != lresult) throw std::out_of_range();
return result;
}
这将比istringstream
,文化不变(因此在不寻常的语言环境中运行时不会对行为发生意外更改)快得多,完全可移植,并且使用第三个参数,您可以支持不同的数字基数,甚至可以执行0x
和0
前缀的检测。
但unsigned int
不一定大到足以容纳您的价值,所以使用unsigned long
,然后您就不需要上面的包装器了。
atoi 返回一个带符号的 int,在您的平台上它的最大值为2^31-1
.
无论您将该结果分配给什么,它都会受到返回类型的限制。
C++ 流可以读取无符号整数。
std::istringstream reader(sThis);
unsigned int val;
reader >> val;
不要忘记,您始终可以编写自己的函数来完全满足您的需求。
此代码适用于 -9223372036854775806 (2^63+1) 和 9223372036854775807 (2^63-1) 之间的任何数字。
像这样的东西:
long long int myAtoi ( string str ) {
long long int value = 0;
for (int i = 0; i < str.size(); i++) {
if (str[i] != '-') {
value *= 10;
value += (int) ((str[i]) - '0');
}
}
if (str.size() > 0 && str[0] == '-')
return -value;
else
return value;
}
无符号整数通常是 C++ 中的 32 位值,最大值为 4,294,967,295。因此,2,154,710,440 可以表示为无符号整数。但是, atoi 转换为带符号的 int 并且最大值为 2,147,483,647 - 因此您的字符串溢出了值范围,这就是您的答案不正确的原因。您可以使用 atoll 将您的字符串转换为至少 64 位的 long long。整数大小在 C++ 中取决于编译器。通常最好包含头文件 stdint.h 然后使用 uint32_t 或 uint64_t 等等,这样你就知道你正在处理的大小。
您可以使用 atol 将字符串转换为 long int 。要阅读更多内容,请参阅 Linux 中的 man atol。
原型
#include <stdlib.h>
long atol(const char *nptr);
不幸的是,C++ 没有用于解析 unsigned int 的嵌入式实现,这真的很奇怪。
这是一个可以帮助您的代码:
#include <stdint.h>
#include <sstream>
inline unsigned int stoui(const std::string& s)
{
std::istringstream reader(s);
unsigned int val = 0;
reader >> val;
return val;
}
// This may be not the same as stoui on some platforms:
inline uint32_t stoui32(const std::string& s)
{
std::istringstream reader(s);
uint32_t val = 0;
reader >> val;
return val;
}
此代码将使用 C++11 对其进行转换:
std::string sThis = "2154910440";
unsigned int iStart = static_cast<unsigned int>(std::stoul(sThis));
std::stoul
将返回unsigned long
大于 a 的unsigned int
。
static_cast
将其转换为正确的类型。