[ C++で開発 ]
文字列で表現された数値を、組み込み型のintなどのインスタンスに変換したり、逆にint型などのインスタンスを文字列に変換したりとした処理をC++で記述するのは意外と面倒です。使用するライブラリによって書き方がいくつかあります。
型安全性(実行時エラーよりコンパイルエラー)、テンプレートによるラッピング、バッファ管理のラッピング、記述の簡潔さを考慮すると、3.の方法がもっとも扱いやすいのですが、基数(16進数等)を指定することができないという制約があります。
まず、文字列から整数に変換するために使用するstrtol系の関数は以下となります。
JIS X 3010 プログラム言語C 7.20.1.4より抜粋
#include <stdlib.h>
| 関数名 | 概要 | シグニチャ |
|---|---|---|
| strtol | nptrが指す文字列の最初の部分をlong int型に変換する |
long int strtol(
const char * restrict nptr,
char ** restrict endptr,
int base);
|
| strtoll | nptrが指す文字列の最初の部分をlong long int型に変換する |
long long int strtoll(
const char * restrict nptr,
char ** restrict endptr,
int base);
|
| strtoul | nptrが指す文字列の最初の部分をunsigned long int型に変換する |
unsigned long int strtol(
const char * restrict nptr,
char ** restrict endptr,
int base);
|
| strtoull | nptrが指す文字列の最初の部分をunsigned long long int型に変換する |
unsigned long long int strtol(
const char * restrict nptr,
char ** restrict endptr,
int base);
|
整数を文字列に変換するsnprintf関数は以下となります。
JIS X 3010 プログラム言語C 7.19.6.5より抜粋
#include <stdio.h>
| 関数名 | 概要 | シグニチャ |
|---|---|---|
| snprintf | formatの書式にもとづき変換した出力をsの指す配列へ書き込む。n-1番目より後の出力文字は捨てられる。 |
int snprintf(
char * restrict s,
size_t n,
const char * restrict format, ...);
|
ここでは、文字列から数値へ変換する関数、数値から文字列へ変換する関数のインタフェースをC++流に定義し、上記の各実装方法で実装します。
namespace stringutil {
template<typename T>
T string2binary(const std::string& text, int base);
template<typename T>
std::string binary2string(T value, int base);
}
Tには、数値型のいずれかが合致します。
まず、2.の方法で基数を含めた変換を実現する方法を実装してみます。
iostreamの入出力先を文字列に変換可能なistringstream/ostringstreamとしたものです。
#include <sstream>
#include <string>
#include <cassert>
namespace stringutil {
template<typename T>
T string2binary(const std::string& text, int base) {
assert(base == 8 || base == 10 || base == 16);
std::istringstream is(text);
T value;
switch (base) {
case 8:
is >> std::oct >> value;
break;
case 10:
is >> value;
break;
case 16:
is >> std::hex >> value;
break;
default:
;
}
return value;
}
}
|
#include <sstream>
#include <string>
#include <cassert>
namespace stringutil {
template<typename T>
std::string binary2string(T value, int base) {
assert(base == 8 || base == 10 || base == 16);
std::ostringstream os;
switch (base) {
case 8:
if (value < 0) {
os << '-';
value *= -1;
}
os << std::oct;
break;
case 10:
os << std::dec;
break;
case 16:
if (value < 0) {
os << '-';
value *= -1;
}
os << std::hex;
break;
}
os << value;
return os.str();
}
}
|
次に、3.の方法で基数を含めた変換を実現する方法を実装してみます。