【C言語】文字列を数値に変換する方法【危険なatoi関数、厳格なstrtol関数】


C言語で文字列型の数値表現を整数型や実数型の数値に変換する方法を紹介します。ato系の関数とstrto系の関数を用いる方法があります。厳格な変換を行う際にはstrto系の関数を用いる必要があります。

目次

スポンサーリンク

ato系(atoi, atol, atof)関数

文字列型からint型やdouble型の数値に変換する場合にはatoi関数やatof関数を用います。

int    i = atoi("9");
double f = atof("3.1");
long   l = atol("-1");

printf("%d, %f, %ld", i, f, l); // 9, 3.100000, -1
printf("%f", atof("1e3"));      // 1000.000000

多くの環境では、変換が失敗した場合には、値0が返されます。ただし処理系依存の動作となっているため注意が必要です。

printf("%lld", atoll("a")); // 0

変換関数一覧

変換関数定義
intatoiint atoi(const char *);
longatollong atol(const char *);
long longatolllong long atoll(const char *);
doubleatofdouble atof(const char *);

atoi関数

#include <stdlib.h>
int atoi(const char *nptr);
第一引数const char *nptr変換する文字列
戻り値int変換後の数値

atoi関数は第一引数に指定された文字列をint型の整数値に変換して返します。エラーが発生した場合の戻り値は処理系依存となっていますが、多くの環境では値0を返すことがほとんどです。エラー発生時のerrnoの書き換えについても処理系依存となっています。

エラーが発生した場合の動作を除けば、atoi関数は(int)strtol(nptr, (char **)NULL, 10)と同等の処理が行われることになります。

atoi関数には、値のオーバーフローを考慮した厳格な変換やエラー制御が行えないという問題があります。そのため、場合によっては次項で紹介するstrtol関数の利用が必要となります。

strto系(strtol, strtod, strtof)関数

より厳格な変換を行いたい場合にはatoi関数の代わりにstrtol関数を用いる必要があります。

long l = strtol("99yen", NULL, 10);
printf("%ld", l); // "90"

strtol関数の詳細は当ページの「# strtol関数」が参考になります。

オーバーフロー・アンダーフローの検知

strtol関数は変換時のエラーやオーバーフローを検知することもできます。

long l = strtol("50000000000000000000", NULL, 10);

if (errno == ERANGE) {
   puts("オーバーフローとアンダーフローのいずれかが発生しました");
}

if (l == LONG_MAX) {
   puts("オーバーフローが発生しました");
}

if (l == LONG_MIN) {
   puts("アンダーフローが発生しました");
}

文字列型からint型への変換

int型を返すstrtoi関数は存在しないため、strtolの結果をintにキャストして利用する必要があります。

// #include <stdlib.h>
const char *nptr = "yen";
char *endptr;

long l = strtol(nptr, &endptr, 10);

if (nptr == endptr) { // assert(l == 0);
   puts("数値に変換できませんでした。");
}

if (l > INT_MAX || INT_MIN > l) {
   puts("int型には変換できません。");
}

// 安全な場合のみキャスト
int i = (int)l;

変換関数一覧

long型やint型以外の変換を行う場合には、strtodやstrtof等、double型やfloat型に対応した個別の関数を用いる必要があります。

変換関数定義
longstrtollong strtol(const char *, char **, int);
unsigned longstrtoullong strtoul(const char *, char **, int);
long longstrtoqlong long strtoq(const char *, char **, int)
unsigned long longstrtouqunsigned long long strtouq(const char *, char **, int);
floatstrtofdouble strtof(const char *, char **);
doublestrtoddouble strtod(const char *, char **);
long doublestrtoldlong double strtold(const char *, char **)

strtol関数

// #include <stdlib.h>
long strtol(const char *nptr, char **endptr, int base);
引数仮引数名説明
第一引数nptr変換対象の文字列
第二引数endptr変換終了した位置
第三引数base基数

strtolはlong型の変換を行う関数です。第一引数nptrに指定された数値を第三引数baseで指定された基数で変換します。文字列の途中で変換が失敗した場合、その途中位置へのアドレスが、第二引数endptrが指すポインタへと格納されます。変換成功時には、nptrに指定された文字列の末尾文字(\0)または変換終了位置のアドレスがendptrへ格納されます。

char *endptr;
long result = strtol("99yen", &endptr, 10);
assert( result  == 99  );
assert( *endptr == 'y' );

変換が失敗した場合には戻り値として0が返されます。値のオーバーフローまたはアンダーフローが発生した場合にはそれぞれ定数値LONG_MAXLONG_MINを返し、errnoに定数ERANGEを格納します。

assert( strtol("yen", NULL, 10) == 0 );
  
long result = strtol("9999999999999999999999", NULL, 10);
assert( result == LONG_MAX );
assert( errno  == ERANGE   );

広告

関連するオススメの記事