名前空間
変種
操作

std::num_put::put, std::num_put::do_put

提供: 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 v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, long v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, long long v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, unsigned long v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, unsigned long long v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, double v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, long double v ) const;
iter_type put( iter_type out, std::ios_base& str, char_type fill, const void* v ) const;
(2)
protected:
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, bool v ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long v ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long long v ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, unsigned long ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, unsigned long long ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, double v ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, long double v ) const;
virtual iter_type do_put( iter_type out, std::ios_base& str, char_type fill, const void* v ) const;
1) public メンバ関数。 最も派生したクラスの protected virtual メンバ関数 do_put を呼びます。
2) ストリーム str に設定されているロケールの書式化フラグ str.flags()、ファセット std::numpunct および std::ctype によって要求される通りに書式化して、 v の値を表す文字列を出力シーケンス out に書き込みます。 この関数は std::cout << n; などのすべての書式付き出力ストリーム演算子によって呼ばれます。

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

目次

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

  • 以下によって行われたかのように、入出力書式化フラグが取得されます。
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);
  • v の型が bool の場合、
    • boolalpha == 0 の場合は、 vint 型変換し、整数の出力を行います。
    • boolalpha != 0 の場合は、 v == true であれば std::use_facet<std::numpunct<charT>>(str.getloc()).truename() を、 v == false であれば std::use_facet<std::numpunct<charT>>(str.getloc()).falsename() を取得し、その文字列の連続するそれぞれの文字 c*out++ = cout に出力します。 この場合、以降の処理は行われず、この関数は out を返します。
  • v の型が整数型の場合は、以下のうち最初に適用可能なものが選択されます。
basefield == oct の場合は、変換指定子 %o を使用します。
basefield == hex && !uppercase の場合は、変換指定子 %x を使用します。
basefield == hex の場合は、変換指定子 %X を使用します。
v の型が符号付きの場合は、変換指定子 %d を使用します。
v の型が符号なしの場合は、変換指定子 %u を使用します。
  • 整数型の場合、必要であれば変換指定子に長さ修飾子 (long および unsigned long の場合は llong long および unsigned long long の場合は ll) が追加されます。
  • v の型が浮動小数点型の場合、以下のうち最初に適用可能なものが選択されます。
floatfield == std::ios_base::fixed の場合は、変換指定子 %f を使用します。
floatfield == std::ios_base::scientific && !uppercase の場合は、変換指定子 %e を使用します。
floatfield == std::ios_base::scientific の場合は、変換指定子 %E を使用します。
floatfield == (std::ios_base::fixed | std::ios_base::scientific) && !uppercase の場合は、変換指定子 %a を使用します。
floatfield == (std::ios_base::fixed | std::ios_base::scientific) の場合は、変換指定子 %A を使用します。
(C++11以上)
!uppercase の場合は、変換指定子 %g を使用します。
そうでなければ、変換指定子 %G を使用します。
  • v の型が long double の場合は、長さ修飾子 L が変換指定子に追加されます。
  • さらにfloatfield != (ios_base::fixed | ios_base::scientific) の場合は (C++11以上)str.precision() に設定された精度修飾子が追加されます。
  • 整数型と浮動小数点型の場合、 showpos がセットされていれば、修飾子 + が前置されます。
  • 整数型の場合、 showbase がセットされていれば、修飾子 # が前置されます。
  • 浮動小数点型の場合、 showpoint がセットされていれば、修飾子 # が前置されます。
  • v の型が void* の場合は、変換指定子 %p を使用します。
  • "C" ロケールで std::printf(spec, v) (ただし spec は選択された変換指定子) を呼んだかのように、ナロー文字列が作成されます。

[編集] ステージ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() によって置き換えられます。

[編集] ステージ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() より小さい場合、シーケンスの長さを str.width() にするため、パディングの示す位置に fill 文字のコピーが挿入されます。

いずれの場合でも、 std::setw の効果を取り消すために str.width(0) が呼ばれます。

[編集] ステージ4: 出力

ステージ3からの CharT のシーケンスからのすべての連続する文字 c が、 *out++ = c によって行われたかのように、出力されます。

[編集] 引数

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

[編集] 戻り値

out

[編集] ノート

先行するゼロは変換指定子 #o (例えば std::showbasestd::oct の組み合わせの結果) によって生成され、パディング文字としては数えられません。

浮動小数点値を hexfloat として書式化するとき (すなわち floatfield == (std::ios_base::fixed | std::ios_base::scientific) のとき)、ストリームの精度は使用されません。 代わりに、数値は常に、値を正確に表現するために十分な精度で表示されます。 (C++11以上)

[編集]

ファセットを直接使用して数値を出力し、ユーザ定義ファセットをデモンストレーションします。

#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 s, std::ios_base& f,
                     char_type fill, long v) const
    {
        return std::num_put<char>::do_put(s, f, fill, v*v );
    }
 
    iter_type do_put(iter_type s, std::ios_base& f,
                     char_type fill, unsigned long v) const
    {
        return std::num_put<char>::do_put(s, f, fill, v*v);
    }
};
 
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, base const& 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

[編集] 関連項目

書式付きデータを挿入します
(std::basic_ostreamのパブリックメンバ関数) [edit]