1

プログラミングの助けが必要です。プログラムは、最終的に unsigned long になる文字列を受け入れる必要があります。しかし、ここにキャッチがあります.16進数と記号の組み合わせを入力するとa!!!!!!エラーが発生し、符号なしの長い変数4294967295FFFFFFFF. 私はこのコードセグメントを試しました:

char buffer[256];
unsigned long holder;
fgets(buffer,256,stdin);
holder = strtoul (buffer,NULL,16);

私の問題は、(8 F's)のFFFFFFFFF代わりに(9 F's)を入力すると、所有者はそれ以上であってもFFFFFFFF受け入れてしまうことです。4294967295もう 1 つのことは、16 進と のような記号の両方を組み合わせるとa!!!!!fgets16 進 A が考慮されることです。

これを行う方法についてアイデアを教えてください。このコード以外のアイデアを知っている場合は、お知らせください。ありがとう!

4

3 に答える 3

1

したがって、このドキュメントを見ると、セクションstrtoulの下にこれが表示されます。Return Value

変換された値が対応する戻り型の範囲外の場合、範囲エラーが発生し、ULONG_MAX または ULLONG_MAX が返されます。

したがって、範囲外のチェックには、次のようなコードが必要です。

if ( ( holder == ULONG_MAX || holder == ULLONG_MAX ) && errno == ERANGE)

a!!!!同じドキュメントを振り返ると、次のように表示されます。

関数は、str_end が指すポインターを、最後に解釈された文字の次の文字を指すように設定します。str_end が NULL の場合、無視されます。

現在渡してNULLいますが、引数を渡す場合:

char *p;
holder = strtoul (buffer,&p,16);

*pがNULL ターミネータであるかどうかを確認できます。そうである場合は、すべての文字を処理しました。そうでない場合は、問題があることがわかります。

変換を実行できず、変換された値が結果の型の範囲外になる場合はstoul、次の例外をスローする whichを使用するオプションもあります。std::invalid_argumentstd::out_of_range

たとえば、次のようにできます。

std::string str1(n) ;
size_t pos ;

try
{
   holder = std::stoul( str1, &pos, 16 ) ;
}
catch( std::invalid_argument e )
{
    std::cout << "Invalid argument" << std::endl ;
}
catch ( std::out_of_range  e )
{
    std::cout << "Out of range" << std::endl ;
}

posあなたの場合、pos != str1.length()文字列全体を処理できず、問題が発生した場合は、最後に処理された文字のインデックスになります。

于 2013-07-23T15:12:41.177 に答える