私は次の文字列を持っています:
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
。少し面倒に見えますが、より一般的な状況で使用できます。テンプレートでそれを使用し、特殊化を持たなくても型引数を転送することができます
代わりに、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
、culture-invariant(通常とは異なるロケールで実行したときの動作に予期しない変更がない)よりもはるかに高速で、完全に移植可能です。 0x
および0
プレフィックスの。
ただし、unsigned int
は必ずしも値を保持するのに十分な大きさではないため、unsigned long
を使用すると、上記のラッパーは不要になります。
atoiは符号付きintを返します。プラットフォームでは、2^31-1
。
その結果を何に割り当てるかは関係ありません。戻り値の型によって制限されます。
C++ストリームは、符号なし整数を読み取ることができます。
std::istringstream reader(sThis);
unsigned int val;
reader >> val;
忘れないでください正確にしたいことをする独自の関数をいつでも書くことができます。
このコードは、-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;
}
多くの場合、符号なしintは最大4,294,967,295のC++の32ビット値です。したがって、2,154,710,440は符号なし整数として表すことができます。ただし、atoiは符号付きで最大値が2,147,483,647のintに変換されるため、文字列が値の範囲をオーバーフローするため、答えが正しくありません。文字列を少なくとも64ビットのlong longに変換する環礁を使用できます。 C++では、整数サイズはコンパイラに依存します。多くの場合、ヘッダーファイルstdint.hをインクルードしてからuint32_tまたはuint64_tなどを使用すると、処理しているサイズがわかります。
文字列をlong intに変換するatolを使用できます。詳細については、Linuxのman atolを参照してください。
プロトタイプ
#include <stdlib.h>
long atol(const char *nptr);
残念ながら、C++には符号なし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
は、適切なタイプに変換します。