atol() と strtol() の違いは何ですか?
彼らのマニュアルページによると、それらは同じ効果と一致する引数を持っているようです:
long atol(const char *nptr);
long int strtol(const char *nptr, char **endptr, int base);
一般的なケースで、引数を使用したくない場合base
(10 進数しかない場合)、どの関数を使用すればよいですか?
strtol
文字列全体が整数に変換されたかどうかを実際に知ることができるため、柔軟性が向上します。atol
は、文字列を数値に変換できない場合 ( のようにatol("help")
)、 と区別できない 0 を返しますatol("0")
。
int main()
{
int res_help = atol("help");
int res_zero = atol("0");
printf("Got from help: %d, from zero: %d\n", res_help, res_zero);
return 0;
}
出力:
Got from help: 0, from zero: 0
strtol
引数を使用してendptr
、変換が失敗した場所を指定します。
int main()
{
char* end;
int res_help = strtol("help", &end, 10);
if (!*end)
printf("Converted successfully\n");
else
printf("Conversion error, non-convertible part: %s", end);
return 0;
}
出力:
Conversion error, non-convertible part: help
したがって、本格的なプログラミングでは、 を使用することを強くお勧めしstrtol
ます。使い方は少しトリッキーですが、上で説明したように、これには正当な理由があります。
atol
非常に単純で制御されたケースにのみ適している場合があります。
atol
機能は、使用可能なエラー処理機能を提供しないことをstrtol
除いて、機能のサブセットです。atol
関数の最も顕著な問題ato...
は、オーバーフローの場合に未定義の動作が発生することです。注: これは、エラーが発生した場合に有益なフィードバックが得られないというだけではありません。これは未定義の動作です。つまり、通常は回復不能な障害です。
これは、atol
関数 (および他のすべてのato..
関数) が、実際の実用的な目的にはほとんど役に立たないことを意味します。これは設計ミスであり、その場所は C の歴史のジャンクヤードにあります。strto...
変換を実行するには、グループの関数を使用する必要があります。それらは、とりわけ、ato...
グループの機能に固有の問題を修正するために導入されました。
man ページによると、atoi
によって廃止されましたstrtol
。
IMPLEMENTATION NOTES
The atoi() and atoi_l() functions have been deprecated by strtol() and strtol_l()
and should not be used in new code.
atol(str)
と同等です
strtol(str, (char **)NULL, 10);
エンド ポインターが必要な場合 (読み取る文字が他にあるかどうか、または実際に読み取った文字があるかどうかを確認するため)、または 10 以外の基数が必要な場合は、strtol を使用します。それ以外の場合は、atol で問題ありません。
新しいコードでは、常にstrtol
. エラー処理があり、endptr
引数により、文字列のどの部分が使用されたかを確認できます。
C99 標準では、ato*
関数について次のように述べられています。
エラー時の動作を除いて、それらは同等です
atoi: (int)strtol(nptr,(char **)NULL, 10)
atol: strtol(nptr,(char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)
メモリが機能する場合、変換できなかった最初の文字を指すようにstrtol()
(オプション) を設定するという追加の利点があります。endptr
の場合NULL
は無視されます。そうすれば、数字と文字が混在する文字列を処理している場合でも、続行できます。
例えば、
char buf[] = "213982 and the rest";
char *theRest;
long int num = strtol(buf, &theRest, 10);
printf("%ld\n", num); /* 213982 */
printf("%s\n", theRest); /* " and the rest" */
strtol の man ページには、次のように記載されています。
ERRORS
EINVAL (not in C99) The given base contains an unsupported value.
ERANGE The resulting value was out of range.
The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned).
次のコードは、範囲エラーをチェックします。(Eli のコードを少し変更)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main()
{
errno = 0;
char* end = 0;
long res = strtol("83459299999999999K997", &end, 10);
if(errno != 0)
{
printf("Conversion error, %s\n", strerror(errno));
}
else if (*end)
{
printf("Converted partially: %i, non-convertible part: %s\n", res, end);
}
else
{
printf("Converted successfully: %i\n", res);
}
return 0;
}