7

私は試した

sscanf(str, "%016llX", &int64 );

しかし、安全ではないようです。型キャストを行うための高速で安全な方法はありますか?

ありがとう〜

4

3 に答える 3

10

scanf家族の機能を気にしないでください。それらを堅牢に使用することはほとんど不可能です。の一般的な安全な使用法は次のstrtoullとおりです。

char *str, *end;
unsigned long long result;
errno = 0;
result = strtoull(str, &end, 16);
if (result == 0 && end == str) {
    /* str was not a number */
} else if (result == ULLONG_MAX && errno) {
    /* the value of str does not fit in unsigned long long */
} else if (*end) {
    /* str began with a number but has junk left over at the end */
}

は、文字列のオプションのプレフィックス、およびオプションの最初の空白と記号文字 (または) をstrtoull受け入れることに注意してください。これらを拒否したい場合は、 を呼び出す前にテストを実行する必要があります。たとえば、次のようになります。0x+-strtoull

if (!isxdigit(str[0]) || (str[1] && !isxdigit(str[1])))

過度に長い数値表現 (先行ゼロ) も禁止したい場合は、 を呼び出す前に次の条件を確認できますstrtoull

if (str[0]=='0' && str[1])

もう 1 つ注意すべき点は、「負の数」は変換の範囲外と見なされないことです。代わりに、プレフィックスの-は、符号なし値に適用される C の単項否定演算子と同じように扱われるため、たとえば(を設定せずに)strtoull("-2", 0, 16)を返します。ULLONG_MAX-1errno

于 2010-11-09T10:59:15.080 に答える
2

あなたのタイトル(現在)は、あなたが提供したコードと矛盾しています。タイトルが元々あったこと(文字列を整数に変換する)を行いたい場合は、この回答を使用できます。


関数を使用できます。これは、数値のテキスト表現を読み取ることに特化した関数とはstrtoull異なります。sscanf

const char *test = "123456789abcdef0";

errno = 0;
unsigned long long result = strtoull(test, NULL, 16);

if (errno == EINVAL)
{
    // not a valid number
}
else if (errno == ERANGE)
{
    // does not fit in an unsigned long long
}
于 2010-11-09T10:00:20.013 に答える
0

私がこの回答を書いた時点で、あなたのタイトルは uint64_t を文字列に書き込むことを示唆していましたが、コードは反対のことを行いました (16 進文字列を uint64_t に読み込んでいます)。私は「両方の方法」と答えました:

<inttypes.h>ヘッダーには、..._t型を安全に処理するための変換マクロがあります。

#include <stdio.h>
#include <inttypes.h>

sprintf( str, "%016" PRIx64, uint64 );

または(それが実際にあなたがやろうとしていることである場合)、その逆:

#include <stdio.h>
#include <inttypes.h>

sscanf( str, "%" SCNx64, &uint64 );

scanf()関数ファミリでは幅などを強制できないことに注意してください。取得したものを解析しますが、入力が期待されるフォーマットに従っていない場合、望ましくない結果が生じる可能性があります。ああ、scanf()関数ファミリは (大文字の) "X" ではなく (小文字の) "x" しか認識しません。

于 2010-11-09T10:02:08.500 に答える