このページの解説は C99 をベースとしています。
以下は目次です。
“12.3”、“-12.3” のような文字列を、実数型の値に変換したいとします。 前者なら 12.3、後者なら -12.3 にします。
“12.3abc” のように、実数と関係がない文字が登場した場合、その手前までで打ち切ります。 また、“abc12.3” の場合は、先頭部分が実数と関係がない文字なので、変換に失敗します。
C言語の標準ライブラリに含まれている atof関数を使うと、文字列を double型の値に変換できます。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
("%lf\n", atof("12.3"));
printf("%lf\n", atof("-12.3"));
printf("%lf\n", atof("+12.3"));
printf("%lf\n", atof("0"));
printf("%lf\n", atof("12.3abc"));
printf("%lf\n", atof("abc12.3"));
printf}
実行結果:
12.300000
-12.300000
12.300000
0.000000
12.300000
0.000000
この方法は手軽ですが、変換の失敗を検出する方法がないという欠点があります。 変換できなかった場合の戻り値は 0.0 になりますから、“0” を変換した場合との区別が付きません。 変換の失敗を検出できる必要がある場合は、方法②を使います。
C言語の標準ライブラリには、atof関数以外にも、文字列から実数へ変換する各種関数があります。
変換後の型が double型の strtod関数、float型の strtof関数、long double型の strtold関数があります。
方法①で取り上げた atof関数と比べて、手軽さの面で大きく劣ります。そのため、プログラムが長くなってしまうので、いったん、“12.3” だけを変換するプログラムを載せます。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* str = "12.3";
= 0;
errno char* end;
double v = strtod(str, &end);
if (errno == ERANGE) {
("error\n");
printf}
else if (str == end) {
("can't convert\n");
printf}
else {
("%lf\n", v);
printf}
}
実行結果:
12.300000
第1引数に変換したい文字列を指定します。
第2引数は、変換できなかった文字へのポインタを格納するポインタ変数を指定します。これは不要ならヌルポインタで構いませんが、変換の失敗を検出するためには指定が必要です。
2つの理由で、変換が失敗することがある点に注意が必要です。
1つには、変換後の値が、変換後の型で表現できないほど大きかったり、小さかったりするケースです。このケースでは、errno に ERANGE がセットされるので、これを使って調べられます。
もう1つは、“abc” を変換しようとした場合のように、数値に変換できないケースです。こちらは、第2引数をチェックすることで調べます。変換できなかった文字へのポインタが、変換元の最初の文字を指していたら、1文字も変換できなかったことを示しています。
このように、エラーの扱いを考慮すると、かなり長くなってしまいます。そこで、使いやすいようにラップしたものを用意しておくと便利かもしれません。一例として、次のようにできます。
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
/*
文字列を double型へ変換する。
str: 変換元の文字列。ヌルポインタは不可。
result: 変換結果を受け取るメモリアドレス。ヌルポインタは不可。
変換できなかった場合には、何も格納されない。
戻り値: 変換できた場合は 0以外、変換できなかった場合は 0。
*/
int stod(const char* str, double* result)
{
(str != NULL);
assert(result != NULL);
assert
= 0;
errno char* end;
double num = strtod(str, &end);
if (errno == ERANGE) {
return 0;
}
else if (str == end) {
return 0;
}
*result = num;
return 1;
}
int main(void)
{
double v;
if (stod("12.3", &v)) {
("%lf\n", v);
printf}
else {
("failed\n");
printf}
}
実行結果:
12.300000
この場合、変換できたのかできなかったのかだけを判定できるようにしています。 成否は戻り値で判別するので、戻り値のパターンを増やせば、 変換できなかった理由を区別できるように対応することは可能です。
return 0;
を削除(C言語編全体でのコードの統一)
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |