将字符串转换为unsigned int会返回错误的结果

时间:2013-08-03 22:18:49

标签: c++ type-conversion

我有以下字符串:

sThis = "2154910440";

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

但结果是

iStart = 2147483647

有人看到我的错误吗?

8 个答案:

答案 0 :(得分:33)

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

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

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

答案 1 :(得分:9)

您应该使用std::strtoul中的<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,然后您将不需要上述包装。

答案 2 :(得分:7)

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

将结果分配给什么并不重要,它将受到返回类型的限制。

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

std::istringstream reader(sThis);
unsigned int val;
reader >> val;

答案 3 :(得分:1)

unsigned int通常是C ++中的32位值,最大值为4,294,967,295。 因此,2,154,710,440可以表示为unsigned int。但是,atoi会转换为一个有符号的int,其最大值为2,147,483,647 - 所以你的字符串会溢出值范围,这就是你的答案不正确的原因。你可以使用环礁将你的字符串转换成一个长的长度,至少是64位。 整数大小在C ++中依赖于编译器。通常最好包含头文件stdint.h,然后使用uint32_t或uint64_t等,以便了解您正在处理的大小。

答案 4 :(得分:1)

不要忘记,你总是可以编写自己的功能完全你想要的。

此代码适用于-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;
}

答案 5 :(得分:1)

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

原型

#include <stdlib.h>
long atol(const char *nptr);

答案 6 :(得分: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;
}

答案 7 :(得分:0)

此代码将使用C ++ 11对其进行转换:

std::string sThis = "2154910440";
unsigned int iStart = static_cast<unsigned int>(std::stoul(sThis));

std::stoul将返回一个unsigned long,它比unsigned int大。

static_cast会将其转换为正确的类型。