最終更新日時(UTC):
が更新

履歴 編集

function template
<charconv>

std::to_chars(C++17)

namespace std {
  //整数型用
  to_chars_result to_chars(char* first, char* last, /*see below*/ value,  int base = 10); // (1)

  //精度、フォーマット指定なし
  to_chars_result to_chars(char* first, char* last, float value);        // (2)
  to_chars_result to_chars(char* first, char* last, double value);       // (3)
  to_chars_result to_chars(char* first, char* last, long double value);  // (4)

  //精度指定なし
  to_chars_result to_chars(char* first, char* last, float value,
                           chars_format fmt);                            // (5)
  to_chars_result to_chars(char* first, char* last, double value,
                           chars_format fmt);                            // (6)
  to_chars_result to_chars(char* first, char* last, long double value,
                           chars_format fmt);                            // (7)

  //精度とフォーマットを指定
  to_chars_result to_chars(char* first, char* last, float value,
                           chars_format fmt, int precision);             // (8)
  to_chars_result to_chars(char* first, char* last, double value,
                           chars_format fmt, int precision);             // (9)
  to_chars_result to_chars(char* first, char* last, long double value,
                           chars_format fmt, int precision);             // (10)
}

概要

与えられた数値(value)を文字列へ変換し、[fisrt, last)内へ出力する。
変換に際し、メモリ確保を行わず例外を投げることもない。

C++標準はこれら関数の実装の詳細について何も規定しない。これは、各実装において可能な最も高速なアルゴリズムが選択されることを意図しての事である。

要件

  • 全て : 出力範囲[fisrt, last)は有効な範囲であること(charのオブジェクトが構築済みであり、連続していること)。
  • (1) : baseは2~36までの値であること。
  • (5)~(10) : fmtchars_formatの列挙値のうちの一つであること。

引数

  • first -- 変換結果の文字列を出力する範囲の先頭のポインタ。
  • last -- 変換結果の文字列を出力する範囲の終端の次を指すポインタ。
  • value -- 文字列へ変換する値。
  • base -- 整数の出力基数(n進数のn)指定、2進数から36進数まで。
  • fmt -- 浮動小数点数の出力フォーマット指定、chars_formatのいずれか。
  • precision -- 浮動小数点数の出力精度(小数点以下の桁数)指定、printfにおいて%.nf, %.neなどとしたときのnにあたる。

効果

  • 全て : valueの値を文字列へ変換し、結果文字列を[fisrt, last)に書き込む。
  • (1) : baseの値をnとすると、整数値をn進数の文字列へ変換する( valueが負なら-が先頭に付く)。
    10 < nの場合、10~36の値はアルファベットの小文字a~zがあてられる。
    桁数を合わせるために左側を0をパディングすること(0埋め)は行われない。

  • (2)(3)(4) : Cロケールでprintfによって行われたかのように浮動小数点数を文字列へ変換する。
    フォーマット指定子は%f,%eどちらかを出力文字列が最も短くなるように(両者が同じなら%fが優先)選択する。

  • (5)(6)(7) : fmtによって指定されたフォーマット指定子を用いて、Cロケールでprintfによって行われたかのように浮動小数点数を文字列へ変換する。
    出力文字列が最も短くなるように変換される。
    chars_format::generalが指定された場合は(2)(3)(4)と同等。

  • (8)(9)(10) : fmtprecisionによって指定されたフォーマット指定子と精度を用いて、Cロケールでprintfによって行われたかのように浮動小数点数を文字列へ変換する。

出力文字列が最も短くなるようにとは、小数点の前に少なくとも1桁あり、対応するfrom_chars関数によって値を正確に復元できるような最小の文字数、になることである。
そのような文字列表現が複数ある場合、valueの値との差が最も小さくなる物が選ばれ、それも複数あるときはstd::round_to_nearestに従った丸めによって一つを選択する。

なお、from_chars関数によって値を正確に復元できるのは両関数が同じ処理系で提供されているときにのみ保証される。

全てのオーバーロードにおいて、変換に失敗した場合の[fisrt, last)の状態は未規定。

戻り値

to_chars_resultの値。

  • 成功した場合
    • ptr : 書き込まれた最後の文字の次の位置を指す(一般的なイテレータ範囲におけるendに相当)。
    • ec : ec == errc{}
  • 失敗した場合

どちらの場合も*ptr == '\0'*(--ptr) == '\0'は保証されない。すなわち、変換後文字列はnull終端されない。

例外

投げない。

備考

(1)の関数は実装によって全ての整数型(符号付、無し)およびcharのオーバーロードが提供される。

MSVCでは浮動小数点数→10進文字列変換の実装にRyuというアルゴリズムを利用している。

#include <iostream>
#include <charconv>

int main()
{
  char out[50]{};
  auto begin = std::begin(out);
  auto end = std::end(out);

  //(1) 10進数文字列へ変換
  if (auto [ptr, ec] = std::to_chars(begin, end, 10); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(1) 2進数文字列へ変換
  if (auto [ptr, ec] = std::to_chars(begin, end, 65535, 2); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(1) 36進数文字列へ変換
  if (auto [ptr, ec] = std::to_chars(begin, end, 35, 36); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }

  //リウヴィル数 
  constexpr double l = 0.11000100000000000000000100000000000;

  //(3) 精度・フォーマット指定なしの浮動小数点数変換
  if (auto [ptr, ec] = std::to_chars(begin, end, l); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }

  //(6) 精度指定なしの浮動小数点数変換、指数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::scientific); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(6) 精度指定なしの浮動小数点数変換、固定少数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::fixed); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(6) 精度指定なしの浮動小数点数変換、16進指数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::hex); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }

  //(9) 精度指定ありの浮動小数点数変換、指数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::scientific, 16); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(9) 精度指定ありの浮動小数点数変換、固定少数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::fixed, 16); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
  //(9) 精度指定ありの浮動小数点数変換、16進指数表記
  if (auto [ptr, ec] = std::to_chars(begin, end, l, std::chars_format::hex, 16); ec == std::errc{}) {
    std::cout << std::string_view(begin, ptr - begin) << std::endl;
  }
  else {
    std::cout << "conversion failed." << std::endl;
  }
}

出力例(VS2019 preview4.1)

10
1111111111111111
z
0.110001
1.10001e-01
0.110001
1.c29068986fcdfp-4
conversion failed.
conversion failed.
1.c29068986fcdf000p-4

精度指定した16進指数表記以外の浮動小数点数変換に失敗するのはMSVC(VS2019 preview4.1)のバグと思われる。

バージョン

言語

  • C++17

処理系

  • Clang: 7.0(整数のみ)
  • GCC: 8.0(整数のみ)
  • Visual C++: 2017 update 7(整数のみ), update 9(full suport)

関連項目

参照