簡體   English   中英

將字符串轉換為unsigned int會返回錯誤的結果

[英]Converting string to unsigned int returns the wrong result

我有以下字符串:

sThis = "2154910440";

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

但結果是

iStart = 2147483647

有人看到我的錯誤嗎?

atoi將字符串轉換為int 在您的系統上, int是32位,其最大值是2147483647.您嘗試轉換的值超出此范圍,因此atoi的返回值未定義。 我想,你的實現在這種情況下返回int的最大值。

你可以使用atoll ,它返回一個long long,保證至少為64位。 或者您可以使用stoi/stol/stoll系列中的函數或其未簽名的對應函數,這些函數實際上會以異常的形式提供有關超出范圍值(和無效值)的有用錯誤報告。

就個人而言,我喜歡boost::lexical_cast 即使它看起來有點麻煩,但它可以用於更一般的上下文中。 您可以在模板中使用它,只需轉發類型參數,而不必具有特化

您應該使用在<cstdlib>找到的std::strtoul ,它是為無符號數設計的,具有更大的范圍,並且可以更好地報告錯誤。

如果要使用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 ,culture-invariant(因此在異常語言環境中運行時沒有意外的行為更改),完全可移植以及使用第三個參數快得多,您可以支持不同的數字基礎甚至執行0x0前綴的檢測。

但是unsigned int不一定足以保存你的值,所以使用unsigned long ,然后你就不需要上面的包裝器了。

atoi返回一個signed int,它在你的平台上的最大值為2^31-1

你將結果分配給什么並不重要,它將受到返回類型的限制。

C ++流可以讀取無符號的整數。

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

無符號整數通常是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等,以便您知道要處理的大小。

不要忘記,你總是可以編寫自己的功能, 完全符合你的要求。

此代碼適用於-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;
}

你可以使用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 ,大於unsigned int

static_cast會將其轉換為正確的類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM