C++17では、<charconv>ヘッダで高速な文字列・数値変換が提供される。
ロケール非依存、動的メモリ確保なし、例外なしで変換できる。
文字列と数値間の変換(C++)で扱うstd::to_stringやstd::stoi系は使いやすい一方、こちらはより低レベルだが高速な変換方法である。
数値から文字列
std::to_chars
数値を指定した文字バッファ範囲に書き込む関数。
#include <charconv>
#include <iostream>
int main()
{
char buffer[16] {};
int value { 12345 };
auto [ptr, ec] { std::to_chars(buffer, buffer + 16, value) };
if (ec == std::errc{}) {
std::cout.write(buffer, ptr - buffer);
std::cout << '\n';
}
}ptrは書き込みが終わった位置を指し、変換結果は[buffer, ptr)の範囲に入る。
自動ではヌル終端されないため、必要なら自分で終端文字を追加する。
std::to_stringはstd::stringを返して扱いやすいが、std::to_charsはバッファを直接扱う代わりに高速である。
整数だけでなく浮動小数点数も対象だが、書式指定や処理系差の詳細は別途確認が必要である。
文字列から数値
std::from_chars
文字列の範囲[first, last)を数値へ変換する関数。
#include <charconv>
#include <iostream>
int main()
{
const char text[] { "12345abc" };
int value {};
auto [ptr, ec] { std::from_chars(text, text + 8, value) };
if (ec == std::errc{}) {
std::cout << value << '\n';
}
}ptrは変換に使われなかった最初の文字を指す。
変換に失敗した場合も例外は投げず、ecで結果を確認する。
- 数値として読めない場合は
std::errc::invalid_argument - 範囲外の値なら
std::errc::result_out_of_range
std::stoi系と違い、先頭の空白は読み飛ばさず、+も受け付けない。
また、0xのような接頭辞も自動では解釈しない。
失敗した場合、変換先の値は変更されない。
補足
to_chars/from_charsは、null終端文字列そのものではなく範囲[first, last)を扱う- バッファを自分で用意する必要がある
- 書式指定や入力の柔軟さは、
iostreamやstd::stoi系より限定的である - JSONやCSVのような、機械が生成・消費するテキストの変換と相性がよい