strtol による整数の読み取り
はじめに
コマンドライン引数から整数値を読み取る場合によく使われる関数にatoi
がある。文字通りascii から integer への変換を実現する。atoi
は簡便に使える便利な関数だが
- 整数以外の文字列が入力された時にエラーを検知できない
- intの範囲を大きく超える整数の検出などもできない
といった問題点がある。ここではユーザ入力をより安全に受け付ける関数としてstrtol
を紹介する。
strtol()
strtol() は文字列を受け取り、基数を指定してlong
型の整数を返す関数でstdlib.h
で定義されている。
#include <stdlib.h>
long strtol(const char *s, char **endptr, int base);
第一引数は変換対象文字列、第三引数は基数を表す。十進数で読み取る場合は10 としてすればよい。この引数を変更することで16進数や8進数形式の文字列が来た際でも読み取りが可能である。ポイントの一つとして、文字列に数字と無関係の文字が含まれている場合等、読み込みに失敗した場合に、第二引数のポインタにそのアドレスを格納できる点がある。これにより読み込みに失敗した箇所を正しく同定できる。この処理が不要な場合はNULL
を指定すればよい。
もう一つの特徴として、strtolは何らかの読み込みエラーに対して、エラー番号を格納するグローバル変数errno
に値をセットするということがある。errno
は errno.h
で定義されていて、直前のエラーが何であったかを整数でセットする。同様にerrno.h
で定義されたstrerror
という関数を利用して、どのようなエラーか表示することができる。
使用例
第3回講義では以下のようにしてユーザ入力を変換している。
char *e;
long w = strtol(argv[1],&e,10);
if (*e != '\0'){
fprintf(stderr, "%s: irregular character found %s\n", argv[1],e);
return EXIT_FAILURE;
}
strtolの結果、残った文字列が存在するとすると、整数でないものが含まれるのでエラーとしている。上記の例だと3.5 などの入力を許容しない。今回はerrno の判定を行っておらず、読み込めた数字が大きすぎたりする場合は検出していないが、そのようなチェックを記述することでより安全な読み込みが可能となる。