C++ 将字符串转换为无符号整数会返回错误的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18037835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:40:32  来源:igfitidea点击:

Converting string to unsigned int returns the wrong result

c++type-conversion

提问by tmighty

I have the following string:

我有以下字符串:

sThis = "2154910440";

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

However the result is

然而结果是

iStart = 2147483647

Does anybody see my mistake?

有人看到我的错误吗?

回答by Benjamin Lindley

atoiconverts a string to an int. On your system, an intis 32 bits, and its max value is 2147483647. The value you are trying to convert falls outside this range, so the return value of atoiis undefined. Your implementation, I guess, returns the max value of an intin this case.

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

You could instead use atoll, which returns a long long, which is guaranteed to be at least 64 bits. Or you could use a function from the stoi/stol/stollfamily, or their unsigned counterparts, which will actually give useful error reports on out of range values (and invalid values) in the form of exceptions.

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

Personally, I like boost::lexical_cast. Even though it appears a bit cumbersome, it can be used in a more general context. You can use it in templates and just forward the type argument instead of having to have specializations

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

回答by Ben Voigt

You should instead use std::strtoul, found in <cstdlib>, which is designed for unsigned numbers, has a larger range, and reports errors better.

您应该改为使用std::strtoul, found in <cstdlib>,它是为无符号数设计的,具有更大的范围,并且可以更好地报告错误。

If you want to use std::stringfor input and exceptions for error handling, use std::stoul. A short, highly efficient implementation would be as follows:

如果要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;
}

This will be much faster than istringstream, culture-invariant (so no unexpected changes to behavior when run in an unusual locale), completely portable, and using the third argument, you can support different numeric bases or even perform detection of 0xand 0prefixes.

这将比 快得多istringstream,文化不变(因此在不寻常的语言环境中运行时不会发生意外的行为变化),完全可移植,并且使用第三个参数,您可以支持不同的数字基础,甚至可以执行0x0前缀的检测。

But unsigned intisn't necessarily big enough to hold your value, so use unsigned long, and then you won't need the above wrapper.

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

回答by helloworld922

atoi returns a signed int, which on your platform has a max value of 2^31-1.

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

It doesn't matter what you're assigning that result to, it will be bounded by the return type.

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

C++ streams can read unsigned ints.

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

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

回答by Oleksiy

Don't forget, you can always write your own function that does exactlywhat you want.

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

This code will work with any number between -9223372036854775806 (2^63+1) and 9223372036854775807 (2^63-1) inclusive.

此代码适用于 -9223372036854775806 (2^63+1) 和 9223372036854775807 (2^63-1) 之间的任何数字

Something like this:

像这样的东西:

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;
}

回答by Madan Ram

you can use atol which convert string to long int . To read more see the man atol in Linux.

您可以使用 atol 将 string 转换为 long int 。要了解更多信息,请参阅 Linux 中的 man atol。

the prototype

原型

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

回答by Sergey

Unfortunately C++ has no embedded implementation for parsing unsigned int and this is really strange.

不幸的是,C++ 没有用于解析 unsigned int 的嵌入式实现,这真的很奇怪。

Here is a code which can help you:

这是一个可以帮助您的代码:

#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;
}

回答by David Elliman

An unsigned int is often a 32 bit value in C++ which has a maximum of 4,294,967,295. 2,154,710,440 can therefore be represented as an unsigned int. However, atoi converts to an int which is signed and has a maximum value of 2,147,483,647 - so you string overflows the value range whichis why your answer is incorrect. You could use atoll which converts your string to a long long which will be at least 64 bits. Integer sizes are compiler dependent in C++. It is often better to include the header file stdint.h and then use uint32_t or uint64_t and so on, so that you know the size you are dealing with.

unsigned int 通常是 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 等,以便您知道要处理的大小。

回答by GizMoCuz

This code will convert it with C++11:

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

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

std::stoulwill return an unsigned long, which is larger than an unsigned int.

std::stoul将返回 an unsigned long,它大于 an unsigned int

static_castwill convert it to the right type.

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