名前空間
変種
操作

std::num_put<CharT,OutputIt>::put, std::num_put<CharT,OutputIt>::do_put

From cppreference.com
< cpp‎ | locale‎ | num put
 
 
 
 
std::num_put
メンバ関数
num_put::putnum_put::do_put
 
ヘッダー <locale> で定義
(1)
public:

iter_type put( iter_type out, std::ios_base& str,

               char_type fill, bool val ) const;
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, long val ) const;
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, long long val ) const;
(C++11以降)
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, unsigned long val ) const;
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, unsigned long long val ) const;
(C++11以降)
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, double val ) const;
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, long double val ) const;
iter_type put( iter_type out, std::ios_base& str,
               char_type fill, const void* val ) const;
(2)
protected:

virtual iter_type do_put( iter_type out, std::ios_base& str,

                          char_type fill, bool val ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, long val ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, long long val ) const;
(C++11以降)
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, unsigned long val ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, unsigned long long val ) const;
(C++11以降)
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, double val ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, long double val ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str,
                          char_type fill, const void* val ) const;
1) 公開メンバ関数。最も派生したクラスの保護仮想メンバ関数do_putを呼び出します。
2) 出力シーケンス out に、フォーマットフラグ str.flags()、およびストリーム str に埋め込まれたロケールの std::numpunct および std::ctype ファセットによって要求される方法でフォーマットされた val の値を表す文字を書き込みます。この関数は、std::cout << n; のようなすべてのフォーマット済み出力ストリーム演算子によって呼び出されます。

変換は4つのステージで行われます

目次

[edit] ステージ1:変換指定子の選択

  • I/Oフォーマットフラグは、次のように取得されます。
fmtflags basefield = (str.flags() & std::ios_base::basefield);
fmtflags uppercase = (str.flags() & std::ios_base::uppercase);
fmtflags floatfield = (str.flags() & std::ios_base::floatfield);
fmtflags showpos = (str.flags() & std::ios_base::showpos);
fmtflags showbase = (str.flags() & std::ios_base::showbase);
fmtflags showpoint = (str.flags() & std::ios_base::showpoint);
  • val の型が bool の場合
    • boolalpha = 0 の場合、val を型 int に変換し、整数出力を行います。
    • boolalpha != 0 の場合、val == true の場合は std::use_facet<std::numpunct<CharT>>(str.getloc()).truename()val == false の場合は std::use_facet<std::numpunct<CharT>>(str.getloc()).falsename() を取得し、その文字列の各連続する文字 c*out++ = c として out に出力します。この場合、これ以上の処理は行われず、関数は out を返します。
  • val の型が整数型の場合、次のうち最初の一致するものが選択されます。
    • basefield == oct の場合、変換指定子 %o を使用します。
    • basefield == hex && !uppercase の場合、変換指定子 %x を使用します。
    • basefield == hex の場合、変換指定子 %X を使用します。
    • val の型が符号付きの場合、変換指定子 %d を使用します。
    • val の型が符号なしの場合、変換指定子 %u を使用します。
  • 整数型の場合、必要に応じて変換指定子に長さ修飾子が付加されます。long および unsigned long の場合は llong long および unsigned long long の場合は ll(since C++11)
  • val の型が浮動小数点型の場合、次のうち最初の一致するものが選択されます。
(C++11まで)
(C++11以降)
(C++11以降)
  • !uppercase の場合、変換指定子 %g を使用します。
  • それ以外の場合、変換指定子 %G を使用します。
また
  • val の型が long double の場合、変換指定子に長さ修飾子 L が追加されます。
  • 浮動小数点型のvalの場合、floatfield != (ios_base::fixed | ios_base::scientific)(since C++11)、精度修飾子が追加され、str.precision() に設定されます。それ以外の場合は、精度は指定されません。
  • 整数型と浮動小数点型の両方で、showpos が設定されている場合、修飾子 + が前に付けられます。
  • 整数型の場合、showbase が設定されている場合、修飾子 # が前に付けられます。
  • 浮動小数点型の場合、showpoint が設定されている場合、修飾子 # が前に付けられます。
  • val の型が void* の場合、変換指定子 %p を使用します。
  • ナロー文字文字列は、"C"ロケールで std::printf(spec, val) を呼び出したかのように作成されます。ここで spec は選択された変換指定子です。

[edit] ステージ2:ロケール固有の変換

  • ステージ1で取得された各文字 c は、小数点 '.' 以外の場合、std::use_facet<std::ctype<CharT>>(str.getloc()).widen(c) を呼び出すことによって CharT に変換されます。
  • 算術型の場合、std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep() から取得された千単位の区切り文字が、std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping() によって提供されるグループ化ルールに従ってシーケンスに挿入されます。
  • 小数点文字('.')は、std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point() で置き換えられます。

[edit] ステージ3:パディング

  • 調整フラグは、std::fmtflags adjustfield = (flags & (std::ios_base::adjustfield)) のように取得され、次のようにパディング位置を特定するために検査されます。
    • adjustfield == std::ios_base::left の場合、後にパディングされます。
    • adjustfield == std::ios_base::right の場合、前にパディングされます。
    • adjustfield == std::ios_base::internal で、符号文字が表現に現れる場合、符号の後にパディングされます。
    • adjustfield == std::ios_base::internal で、ステージ1の表現が 0x または 0X で始まる場合、x または X の後にパディングされます。
    • それ以外の場合、前にパディングされます。
  • str.width() がゼロ以外(例:std::setw が直前に使用された)で、ステージ2後の CharT の数が str.width() より少ない場合、fill 文字のコピーがパディングによって示される位置に挿入され、シーケンスの長さを str.width() にします。

いずれの場合も、str.width(0) が呼び出され、std::setw の効果がキャンセルされます。

[edit] ステージ4:出力

ステージ3からの CharT のシーケンスの各連続する文字 c は、*out++ = c のように出力されます。

[edit] パラメータ

out - 上書きされる最初の文字を指すイテレータ
str - フォーマット情報を取得するストリーム
fill - 結果をフィールド幅にパディングする必要がある場合に使用されるパディング文字
val - 文字列に変換して出力する値

[edit] 戻り値

out

[edit] 注記

変換指定子 #o(例:std::showbasestd::oct の組み合わせによって生成される)によって生成される先頭のゼロは、パディング文字としてはカウントされません。

浮動小数点値を hexfloat(すなわち、floatfield == (std::ios_base::fixed | std::ios_base::scientific))としてフォーマットする場合、ストリームの精度は使用されません。代わりに、値の正確な表現に必要な十分な精度で数値が常に印刷されます。

(C++11以降)

[edit]

ファセットを直接使用して数値をフォーマットし、ユーザー定義ファセットを実証する。

#include <iostream>
#include <locale>
 
// this custom num_put outputs squares of all integers (except long long)
struct squaring_num_put : std::num_put<char>
{
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
 
    iter_type do_put(iter_type out, std::ios_base& str,
                     char_type fill, unsigned long val) const
    {
        return std::num_put<char>::do_put(out, str, fill, val * val);
    }
};
 
int main()
{
    auto& facet = std::use_facet<std::num_put<char>>(std::locale());
    facet.put(std::cout, std::cout, '0', 2.71);
    std::cout << '\n';
 
    std::cout.imbue(std::locale(std::cout.getloc(), new squaring_num_put));
    std::cout << 6 << ' ' << -12 << '\n';
}

出力

2.71
36 144

ユーザー定義型の operator<< の実装。

#include <iostream>
#include <iterator>
#include <locale>
 
struct base { long x = 10; };
 
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os, const base& b)
{
    try
    {
        typename std::basic_ostream<CharT, Traits>::sentry s(os);
 
        if (s)
        {
            std::ostreambuf_iterator<CharT, Traits> it(os);
            std::use_facet<std::num_put<CharT>>(os.getloc())
                .put(it, os, os.fill(), b.x);
        }
    }
    catch (...)
    {
        // set badbit on os and rethrow if required
    }
 
    return os;
}
 
int main()
{
    base b;
    std::cout << b;
}

出力

10

[edit] 不具合報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
LWG 34 C++98 boolのオーバーロードが、存在しないメンバを使用していました。
truenamefalsenamestd::ctype
これらのメンバを使用します。
std::numpunct
LWG 231 C++98 精度修飾子は、次の場合にのみ追加されていました。
(flags & fixed) != 0 または str.precision() > 0
これらの条件は削除されました。
LWG 282 C++98 千単位の区切り文字は、ステージ2で
整数型に対してのみ挿入されていました。
次にも挿入されるようになりました。
浮動小数点型
LWG 4084 C++11 "NAN""INF" は印刷できませんでした。 印刷できるようになりました。

[edit] 関連項目

書式付きデータを挿入する
(std::basic_ostream<CharT,Traits>のpublicメンバ関数) [編集]
English 日本語 中文(简体) 中文(繁體)