Linux講座にようこそ。このページは「C言語プログラミング入門 - 第14章.ライブラリ関数 - 一般ユーティリティライブラリ」です。

C言語プログラミング入門

14. ライブラリ関数(30/36) - ユーティリティライブラリ(3/5)

14.42 文字列の数値変換関数

14.42.1 atof関数、atoi関数、atol関数

atof関数は文字列をdouble型の数値に、atoi関数は文字列をint型の数値に、atol関数は文字列をlong int型の数値に変換します。指定した文字列が数字でない場合は返り値として0が返りますが、数字の0の場合も返り値が0になりますので区別が付きませんので、これらの関数を使う場合は注意してください。

変換する文字列の先頭は空白(スペースやタブ、等)でも構いませんし、+や-は正・負の符号とみなします。また、atof関数は途中の.は小数点とみなします。これらの記号や数字以外が現れた時点で変換を終了します。

【表14-7-5】 atof関数、atoi関数、atol関数
形式#include <stdlib.h>
double atof(const char *nptr);
int atoi(const char *nptr);
long atol(const char *nptr);
返り値数値に変換した値を返します。変換出来なかった場合は0を返します。
引数
const char *nptr
変換する文字列を指定します。

14.42.2 strtod関数

strtod関数は文字列をdouble型の数値に変換します。atof関数との相違は、指定した文字列が数字でない場合の判別手段が用意されている事です。

変換する文字列の先頭は空白(スペースやタブ、等)でも構いませんし、+や-は正・負の符号とみなします。また、途中の.は小数点とみなします。これらの記号や数字以外が現れた時点で変換を終了します。(「整数.整数E±整数」(Eは小文字も可)の形式もサポートしています)

なお、"INF"または"INFINITY"は無限、"NAN"は計算できない数(not-a-number)とみなします。(大文字小文字は区別しません)

【「14-7-6】 strtod関数
形式#include <stdlib.h>
double strtod(const char *nptr, char **endptr);
返り値数値に変換した値を返します。変換出来なかった場合は0を返します。
引数
const char *nptr
変換する文字列を指定します。
char **endptr
変換した数字文字の、次の文字のアドレスを格納するポインタ変数のアドレスを指定します。NULLを指定することも出来ます。

変換結果がオーバーフローまたはアンダーフローを起こした場合には、外部変数errnoにERANGEが設定され、返り値はオーバーフローの場合はHUGE_VALが、アンダーフローの場合は0が返ります。

第1引数で指定した文字列が正常に変換されたか否かは、第2引数で指定したポインタ変数の指し示す文字がヌル文字('\0')かどうかで判別できます。ヌル文字であれば、ヌル文字の前の文字、つまり、文字列の最後の文字までが変換対象になったことになります。

14.42.3 strtol関数、strtoul関数

strtol関数は文字列をlong int型の数値に、strtoul関数はunsigned long int型の数値に変換します。strtod関数と同様に、指定した文字列が数字でない場合の判別手段が用意されています。

変換する文字列の先頭は空白(スペースやタブ、等)でも構いませんし、+や-は正・負の符号とみなします。また、'0X'や'0x'で始まる場合は十六進数、0で始まる場合は八進数とみなします。

【表14-7-7】 strtol関数、strtoul関数
形式#include <stdlib.h>
long int strtol(const char *nptr, char **endptr, int base);
unsigned long int strtoul(const char *nptr, char **endptr, int base);
返り値数値に変換した値を返します。変換出来なかった場合は0を返します。
引数
const char *nptr
変換する文字列を指定します。
char **endptr
変換した数字文字の、次の文字のアドレスを格納するポインタ変数のアドレスを指定します。NULLを指定することも出来ます。
int base
変換する数値の基数を指定します。2〜36までの値を指定することが出来ます。

変換結果がオーバーフローまたはアンダーフローを起こした場合には、外部変数errnoにERANGEが設定され、返り値は次の値になります。

  • strtol関数の場合は、オーバーフローした場合にはLONG_MAXが、アンダーフローした場合にはLONG_MINが返ります。
  • strtoul関数の場合は、オーバーフローした場合にはULONG_MAXが返ります。また、先頭が-符号の場合は、変換結果は符号を反転した値が返ります。

第1引数で指定した文字列が正常に変換されたか否かは、第2引数で指定したポインタ変数の指し示す文字がヌル文字('\0')かどうかで判別できます。ヌル文字であれば、ヌル文字の前の文字、つまり、文字列の最後の文字までが変換対象になったことになります。

第3引数で0又は16を指定した場合、変換する文字列の先頭に'0X'や'0x'を指定すると十六進数とみなします。また、0を指定して、変換する文字列の先頭に0を指定すると八進数とみなします。

14.42.4 例題

入力した文字列を整数値に変換して表示することを繰り返します。入力文字列として、endを入力したら終了します。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #define BUFFSIZE    1024
  6.  
  7. int main(void)
  8. {
  9.     long int        conv;
  10.     char            buff[BUFFSIZE];
  11.     char            *buff_p;
  12.     char            *endptr;
  13.  
  14.     while(1)
  15.     {
  16.         printf("文字列を入力してください ==> ");
  17.         fgets(buff, BUFFSIZE, stdin);
  18.  
  19.         if (strncmp(buff, "end", 3) != 0)
  20.         {
  21.             /* 改行をヌル文字に置き換える */
  22.             if ((buff_p = strchr(buff, '\n')) != NULL)
  23.             {
  24.                 *buff_p = '\0';
  25.             }
  26.  
  27.             errno = 0;             /* 外部変数errnoを初期化 */
  28.             /* 文字列をlong int型に変換 */
  29.             conv = strtol(buff, &endptr, 0);
  30.             /* 完全に変換できたかのチェック */
  31.             if (errno == 0 && *endptr == '\0')
  32.             {
  33.                 printf("%s --> %ld\n", buff, conv);
  34.             }
  35.             else
  36.             {
  37.                 printf("変換できませんでした。\n");
  38.             }
  39.         }
  40.         else
  41.         {
  42.             break;
  43.         }
  44.     }
  45.  
  46.     return 0;
  47. }
$ ./ex14_7_2.prg
文字列を入力してください ==> 123
123 --> 123
文字列を入力してください ==> +123
+123 --> 123
文字列を入力してください ==> -123
-123 --> -123
文字列を入力してください ==> 123.5
変換できませんでした。
文字列を入力してください ==> 0x1a
0x1a --> 26
文字列を入力してください ==> 012
012 --> 10
文字列を入力してください ==>    345
345 --> 345
文字列を入力してください ==>    34 5
変換できませんでした。
文字列を入力してください ==> 0Z1a
変換できませんでした。
文字列を入力してください ==> 2000000000
2000000000 --> 2000000000
文字列を入力してください ==> 2222222222
変換できませんでした。
文字列を入力してください ==> end
$
27行目
変換結果がオーバーフローやアンダーフローを起こす場合を考慮して、外部変数errnoを0で初期化します。
29行目
入力した文字列をstrtol関数でlong int型の整数値に変換します。
31行目
文字列が変換出来たかをチェックします。errnoが0以外の場合はオーバーフロー又はアンダーフローが起きたことになりますし、*endptrがヌル文字でない場合は文字列中の最後の文字までが変換対象になっていないことになります。