文字列から数値への変換
呼称: 文字列から数値への変換
目的: 文字列を数値へ変換する
特徴: strtol()/strtoul() を使用するとエラーを検出できる
用例: どこでも、いつでも
備考: errno を検査する必要がある*1
C 言語で文字列から数値への変換はよく使う処理です。数値として計算する必要はなくても、数値にしておくことで関数への値渡しが可能であったり、桁数を考慮する必要がなかったり、何かを便利なことがあります。シンプルな処理なので標準関数を呼び出せばそれで良いと考えがちですが、きちんとエラーを検出しようとすると考慮が必要です。
例えば、以下のようなケースにエラーを検出するかどうかがあります。
- 数値ではない文字列が指定されている
- 数値と数値ではない文字列が混在している
- 扱う数値型の範囲を超えた文字列が指定されている
man を調べると atoi() は*2
strtol(nptr, (char **) NULL, 10);
と同じとあります。atoi() ではエラーを検出できないことに注意する必要があります。
#include <stdio.h> #define __USE_ISOC99 #include <limits.h> #include <stdlib.h> #include <inttypes.h> #include <string.h> #include <errno.h> #define BASE_NUM 10 void usage() { printf("./str2num 538528\n"); } int main(int argc, char *argv[]) { int i; unsigned int ui; char *num_str, *endptr; if (argc < 2) { usage(); return EXIT_SUCCESS; } num_str = argv[1]; printf("int max : %d\n", INT_MAX); printf("uint max : %u\n", UINT_MAX); printf("---------------------------\n"); i = atoi(num_str); printf("use atoi() : %d\n", i); errno = 0; i = strtol(num_str, &endptr, BASE_NUM); if (*endptr != '\0' || (i == INT_MAX && errno == ERANGE)) { fprintf(stderr, "strtol() error : %s\n", num_str); } else { printf("use strtol() : %d\n", i); } errno = 0; ui = strtoul(num_str, &endptr, BASE_NUM); if (*endptr != '\0' || (ui == UINT_MAX && errno == ERANGE)) { fprintf(stderr, "strtoul() error: %s\n", num_str); } else { printf("use strtoul() : %u\n", ui); } return EXIT_SUCCESS; }
実行結果。
$ gcc -Wall str2num.c -o str2num $ ./str2num 123 int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 123 use strtol() : 123 use strtoul() : 123 $ ./str2num 123abc int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 123 strtol() error : 123abc strtoul() error: 123abc $ ./str2num "" int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 0 use strtol() : 0 use strtoul() : 0 $ ./str2num a int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 0 strtol() error : a strtoul() error: a $ ./str2num 2147483647 int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 2147483647 use strtol() : 2147483647 use strtoul() : 2147483647 $ ./str2num 2147483648 int max : 2147483647 uint max : 4294967295 --------------------------- use atoi() : 2147483647 strtol() error : 2147483648 use strtoul() : 2147483648