質問

文字列に大きな数字を保存していて、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

     

digit2:2147483647

     

digit3:57230

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

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

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
役に立ちましたか?

解決

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

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

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

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

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

    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 は、数字以外の数字が見つかるまで数字をスキャンします。無効なメモリの場所を読み取った場合とそれがどうなるかは、明らかに定義されていません。

他のヒント

2番目の数字が表示される理由はわかっています。

atoiリファレンスから。

  

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

2147483647はINT_MAX

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

atoi("720394857230")

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

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

2文字の文字列を割り当て、 bigNumber.at()の最初の文字と \ 0 の1文字を2番目の文字に割り当ててから、< code> atoi()に一時的な文字列のアドレスを指定します。

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top