1

文字列に大きな数が格納されていて、1桁を抽出しようとしています。しかし、それらの呼び出しの違いは何ですか?

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

これにより、次の出力が生成されます。

桁:7

桁2:2147483647

桁3:57230

最初のものは望ましい結果です。2つ目は乱数のようですが、文字列では見つかりません。3つ目は文字列の終わりですが、予想どおり1桁だけでなく、12番目のインデックスから文字列の終わりまでです。誰かが私にさまざまな出力を説明できますか?

編集:これは許容できる解決策でしょうか?

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
4

5 に答える 5

5

2番目の数字が表示される理由がわかりました。

アトイ参照より。

正しい値が表現可能な値の範囲外の場合、INT_MAXまたは INT_MIN が返されます。

2147483647 は INT_MAX です

于 2009-06-22T09:12:32.930 に答える
5

それは多かれ少なかれ説明可能です。

int main(){
    std::string bigNumber = "93485720394857230";

この行は、単一文字 '5' を文字変数にコピーします。atoiこれを正しく変換します。 atoiは、文字列パラメーターが有効な 0 で終了する文字列であることを期待しています。&tmp文字変数へのポインタにすぎません。メモリ内の文字の直後のメモリが不明であるため、この呼び出しの動作は未定義です。正確には、null で終了する文字列を作成して渡す必要があります。*

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

この行は、文字列内の位置 5 の文字へのポインターを取得します。これはたまたま、上記の元の大きな数値文字列へのポインターであるため、文字列パラメーターatoiは文字列 "5720394857230" のようになります。atoi32ビット整数がこれを保持しないため、これを整数に変換しようとすると明らかにオーバーフローします。

    int digit2 = atoi(&bigNumber.at(5))

この行は、位置 12 の文字列へのポインターを取得します。パラメーターatoiは文字列 "57230" です。これは整数 57230 に正しく変換されます。

    int digit3 = atoi(&bigNumber.at(12));

... }

C++ を使用しているため、文字列を整数に変換するためのより優れた方法があります。私が気に入っているのは、Boost lexical_cast ライブラリです。次のように使用します。

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

*厳密にatoiは、数字以外の文字が見つかるまで数字をスキャンします。それがいつ見つかるか、無効なメモリ位置を読み込んだときに何をするかは明らかに未定義です。

于 2009-06-22T09:13:58.467 に答える
3

bigNumber.at()単一の文字を含む新しい文字列を返すのではなく、文字列内の文字のアドレスを返します。したがって、2 番目の呼び出しは実際には次のようになります。

atoi("720394857230")

これにより、内部アルゴリズムがオーバーフローします。

また、最初の呼び出しは のメモリ内の (ランダムな) 値に依存するため、非常に危険(&tmp)+1です。

2文字の文字列を割り当て、1文字目bigNumber.at()を最初と2番目に割り当ててから、一時文字列のアドレスで\0呼び出す必要があります。atoi()

于 2009-06-22T09:12:24.740 に答える
3

への引数atoiは、ゼロで終わる文字列でなければなりません。

于 2009-06-22T09:12:56.067 に答える
3

関数atは、文字列内の char へのポインターを提供します。関数atoiは文字列を 1 つの文字だけでなく、int に変換します。

于 2009-06-22T09:13:59.730 に答える