23

我有以下字符串:

sThis = "2154910440";

unsigned int iStart=atoi(sThis.c_str());

然而结果是

iStart = 2147483647

有人看到我的错误吗?

4

8 回答 8

41

atoi将字符串转换为int. 在您的系统上,anint为 32 位,其最大值为 2147483647。您尝试转换的值超出此范围,因此返回值atoi未定义。int我猜,您的实现在这种情况下会返回 an 的最大值。

您可以改为使用atoll,它返回一个 long long ,保证至少为 64 位。或者,您可以使用该stoi/stol/stoll系列中的一个函数,或者它们的无符号对应函数,这实际上会以异常的形式提供有关超出范围值(和无效值)的有用错误报告。

就个人而言,我喜欢boost::lexical_cast. 尽管它看起来有点麻烦,但它可以在更一般的上下文中使用。您可以在模板中使用它,只需转发类型参数,而不必进行专门化

于 2013-08-03T22:23:42.393 回答
15

您应该改用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,文化不变(因此在不寻常的语言环境中运行时不会对行为发生意外更改)快得多,完全可移植,并且使用第三个参数,您可以支持不同的数字基数,甚至可以执行0x0前缀的检测。

unsigned int不一定大到足以容纳您的价值,所以使用unsigned long,然后您就不需要上面的包装器了。

于 2013-08-03T22:26:45.833 回答
9

atoi 返回一个带符号的 int,在您的平台上它的最大值为2^31-1.

无论您将该结果分配给什么,它都会受到返回类型的限制。

C++ 流可以读取无符号整数。

std::istringstream reader(sThis);
unsigned int val;
reader >> val;
于 2013-08-03T22:24:08.140 回答
2

不要忘记,您始终可以编写自己的函数来完全满足您的需求。

此代码适用于 -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;
}
于 2013-08-03T23:01:42.517 回答
1

无符号整数通常是 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 等等,这样你就知道你正在处理的大小。

于 2013-08-03T22:31:28.870 回答
1

您可以使用 atol 将字符串转换为 long int 。要阅读更多内容,请参阅 Linux 中的 man atol。

原型

#include <stdlib.h>
long atol(const char *nptr);
于 2013-08-04T08:52:31.293 回答
1

不幸的是,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;
}
于 2015-06-08T14:46:10.200 回答
0

此代码将使用 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将其转换为正确的类型。

于 2018-07-11T13:54:03.577 回答