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