こんにちは、ナナです。
C言語のプログラムの中で「文字で表現された数字を、数値に変えたい!」と、思うことってあるんです。例えば、数字 “123” を数値「123」に変換したい、そんなシーンですね。
なぜ、こんなことがしたいかというと、数字 “123” は文字であるがゆえに計算ができないんです。計算するためには数値「123」にする必要があります。
注意:この記事においては意識的に、文字で表現された数のことを「数字」、計算可能な数のことを「数値」、と表現を切り分けて解説します。
本記事では次の悩みを解消する内容となっています。
では、「数字」から「数値」への変換方法を学んでいきましょう。
※atoi関数を使うと簡単な数字なら数値に変換ができますが、複雑な変換を求めているのであればsscanf関数の利用をオススメします。
》参考:sscanf関数【文字列を解析して変数へ:サンプル付き】
文字列の数字を数値へと変換するための標準ライブラリ関数
C言語で「数字」を「数値」へ変換するための標準ライブラリ関数は、次の関数になります。
変換ライブラリ関数一覧
#include <stdlib.h>
int atoi(const char * string); // ascii to integer
long atol(const char * string); // ascii to long
double atof(const char * string); // ascii to float(double)
よく見ると、引数は同じデータ型ですが、戻り値の型が異なっていますね。C言語は型制約の強い言語のため、データ型の種類に応じて関数を定義しています。
atoiとは「ascii(アスキーコードの文字) to(を) integer(整数型へ)」という意味になります。このような名前の法則を知っておくと、記憶に残りやすくなります。
注意としてはatof関数は「float型」の略ですが、戻り値の型は「double型」になっていることですね。
基本的なatoi関数の利用方法
それでは、一番基本となるatoi関数を呼び出してみましょう。引数に「数字」である”123456″の文字列をポインタで受け渡します。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char * input = "123456"; // 入力となる数字
int num = 0;
// 数字を数値に変換
num = atoi(input);
printf("%d", num);
return 0;
}
123456
結果はこの通り、文字である数字から計算可能な数値へ変換することができました。
atoi関数のサンプルコード:様々な入力文字列に対する出力結果
このようなライブラリ関数を使う時には、気をつけるべきことがあります。
それは、様々な入力パターンの文字や数字を「引数」で渡したときに、どのような「戻り値」の結果を受け取れるかをしっかりと把握することです。
これを把握しておかないと、意図せぬ動作になって場合によっては大きな問題となります。
入力サンプルに対する結果
それでは実際に様々な入力ケースに対するatoi関数の変換結果を考察しましょう。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("%s => %d\n", "-123", atoi("-123"));
printf("%s => %d\n", "3.14", atoi("3.14"));
printf("%s => %d\n", "XYZ", atoi("XYZ"));
printf("%s => %d\n", "5G", atoi("5G"));
printf("%s => %d\n", "G5", atoi("G5"));
printf("%s => %d\n", "1 2 3", atoi("1 2 3"));
printf("%s => %d\n", " 1", atoi(" 1"));
printf("%s => %d\n", "1,2,3", atoi("1,2,3"));
return 0;
}
-123 => -123
3.14 => 3
XYZ => 0
5G => 5
G5 => 0
1 2 3 => 1
1 => 1
1,2,3 => 1
この結果から、atoi関数の基本的な設計思想を読み取っていきます。
入力文字列 | 出力結果 | 考察内容 |
---|---|---|
-123 | -123 | 負値は正常に変換される。 |
3.14 | 3 | 小数点以下は切り捨て。整数型のため妥当な結果。 |
XYZ | 0 | 英字は変換できない。異常として0を出力する。 |
5G | 5 | 数字がある場合は、数字の部分だけ変換する。 |
G5 | 0 | 英字の後の数字は認識できない。異常として0を出力する。 |
1 2 3 | 1 | スペースの区切りが出現したら変換は終了する。 |
1 | 1 | 先頭のスペースは無視されて変換される。 |
1,2,3 | 1 | カンマのような記号も出現したら変換は終了する。 |
特徴的なのは、「数値」に変換できない文字が出現したときの動作ですね。
先頭から文字を変換し、変換できない文字が出現した時点で変換を終了していることが想像できます。
ただし、先頭のスペースに関しては特別に無視するという特殊処理となっていますね。
変換異常時の取り扱いに注意
atoi関数の仕様の性質上、注意するべき点があります。それは「変換異常時に0を返却」するということです。
入力パターンとして “0” という入力もあり得るわけですから、正常な変換結果の「0」と変換異常時の「0」の見分けが付きません。
このような判別できないケースも含めて、成立するプログラムを組み立てる必要があります。
atof関数のサンプルコード:様々な入力文字列に対する出力結果
続けて、浮動小数点の数字を数値に変換するatof関数も同様に動作を確認しておきましょう。
入力サンプルに対する結果
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("%s => %lf\n", "-123.4", atof("-123.4"));
printf("%s => %lf\n", "3.14", atof("3.14"));
printf("%s => %lf\n", "XYZ", atof("XYZ"));
printf("%s => %lf\n", "5.5G", atof("5.5G"));
printf("%s => %lf\n", "G5.5", atof("G5.5"));
printf("%s => %lf\n", "1.5 2.5 3.5", atof("1.5 2.5 3.5"));
printf("%s => %lf\n", " 1.5", atof(" 1.5"));
printf("%s => %lf\n", "1.5,2.5,3.5", atof("1.5,2.5,3.5"));
return 0;
}
-123.4 => -123.400000
3.14 => 3.140000
XYZ => 0.000000
5.5G => 5.500000
G5.5 => 0.000000
1.5 2.5 3.5 => 1.500000
1.5 => 1.500000
1.5,2.5,3.5 => 1.500000
atof関数の結果はatoiと大きく変わったところはありません。
入力文字列 | 出力結果 | 考察内容 |
---|---|---|
-123.4 | -123.400000 | 負値は正常に変換される。 |
3.14 | 3.140000 | 小数点以下も正常に変換できる。 |
XYZ | 0.000000 | 英字は変換できない。異常として0.0を出力する。 |
5.5G | 5.500000 | 数字がある場合は、数字の部分だけ変換する。 |
G5.5 | 0.000000 | 英字の後の数字は認識できない。異常として0.0を出力する。 |
1.5 2.5 3.5 | 1.500000 | スペースの区切りが出現したら変換は終了する。 |
1.5 | 1.500000 | 先頭のスペースは無視されて変換される。 |
1.5,2.5,3.5 | 1.500000 | カンマのような記号も出現したら変換は終了する。 |
atoi関数とsscanf関数の使い分け
実は数字を数値に変換する方法には、atoi関数以外にもsscanf関数を使う方法があります。
sscanf関数はかなりリッチな機能を備えており、文字列の中から英字と数字を切り分けたり、16進数の数字を数値に変換することもできます。
C言語は文字列を扱うのが苦手なため、複雑な文字列を操作する際は「sscanf関数」のような高機能関数を使うとバグの発生を軽減できます。
》参考:sscanf関数【文字列を解析して変数へ:サンプル付き】