名前空間
変種
操作

std::num_get<CharT,InputIt>::get, std::num_get<CharT,InputIt>::do_get

From cppreference.com
< cpp‎ | locale‎ | num get
 
 
 
 
std::num_get
メンバ関数
num_get::getnum_get::do_get
 
(1)
public:

iter_type get( iter_type in, iter_type end, std::ios_base& str,

               std::ios_base::iostate& err, bool& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, long& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, long long& v ) const;
(C++11以降)
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, unsigned short& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, unsigned int& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, unsigned long& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, unsigned long long& v ) const;
(C++11以降)
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, float& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, double& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, long double& v ) const;
iter_type get( iter_type in, iter_type end, std::ios_base& str,
               std::ios_base::iostate& err, void*& v ) const;
(2)
protected:

virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,

                          std::ios_base::iostate& err, bool& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, long& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, long long& v ) const;
(C++11以降)
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, unsigned short& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, unsigned int& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, unsigned long& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,

                          std::ios_base::iostate& err,

                          unsigned long long& v ) const;
(C++11以降)
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, float& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, double& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, long double& v ) const;
virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
                          std::ios_base::iostate& err, void*& v ) const;
1) 公開メンバ関数。最も派生したクラスのメンバ関数do_getを呼び出します。
2) 入力イテレータinから文字を読み込み、vの型の値に変換します。この際、I/Oストリームのフォーマットフラグ(str.flags()から取得)、文字分類ルール(std::use_facet<std::ctype<CharT>>(str.getloc())から取得)、および数値句読点文字(std::use_facet<std::numpunct<CharT>>(str.getloc())から取得)を考慮します。この関数は、std::cin >> n;のようなすべての書式付き入力ストリーム演算子によって呼び出されます。

変換は3つの段階で行われます。

目次

[edit] 段階1: 変換指定子の選択

  • I/Oフォーマットフラグは、以下のように取得されます。
fmtflags basefield = (str.flags() & std::ios_base::basefield);
fmtflags boolalpha = (str.flags() & std::ios_base::boolalpha);
  • vの型が整数型の場合、以下の5つのうち最初の該当するものが選択されます。
もしbasefield = octなら、変換指定子%oを使用します。
もしbasefield = hexなら、変換指定子%Xを使用します。
もしbasefield = 0なら、変換指定子%iを使用します。
vの型が符号付きの場合、変換指定子%dを使用します。
vの型が符号なしの場合、変換指定子%uを使用します。
  • 整数型の場合、必要に応じて変換指定子に長さ修飾子が追加されます。shortおよびunsigned shortにはhlongおよびunsigned longにはl(C++11以降)lllong longおよびunsigned long longに使用されます。
  • vの型がfloatの場合、変換指定子%gを使用します。
  • vの型がdoubleの場合、変換指定子%lgを使用します。
  • vの型がlong doubleの場合、変換指定子%Lgを使用します。
  • vの型がvoid*の場合、変換指定子%pを使用します。
  • vの型がboolで、boolalpha = 0の場合、段階3でvに格納される値を除いて、vの型がlongであるかのように処理が進みます。
  • vの型がboolで、boolalpha != 0の場合、段階2と3は以下で置き換えられます。
    • 入力イテレータinから取得された連続する文字は、std::use_facet<std::numpunct<CharT>>(str.getloc()).falsename()およびstd::use_facet<std::numpunct<CharT>>(str.getloc()).truename()から取得される文字シーケンスと、一意な一致を特定するために必要な範囲でのみ照合されます。入力イテレータinは、文字を取得するために必要な場合にのみendと比較されます。
    • ターゲットシーケンスが一意に一致した場合、vは対応するbool値に設定されます。それ以外の場合はfalsevに格納され、std::ios_base::failbiterrに設定されます。入力が終わる前(in == end)に一意な一致が見つからなかった場合、err |= std::ios_base::eofbitが実行されます。

[edit] 段階2: 文字の抽出

  • in == endの場合、段階2は直ちに終了し、それ以上文字は抽出されません。
  • 次の文字は、char_type ct = *in;のようにinから抽出されます。
    • 文字が、"0123456789abcdefxABCDEFX+-"(C++11まで)"0123456789abcdefpxABCDEFPX+-"(C++11以降)のいずれかに対応し、ロケールのchar_typeに拡張される場合(std::use_facet<std::ctype<CharT>>(str.getloc()).widen()による)、対応するcharに変換されます。
    • 文字が小数点の区切り文字(std::use_facet<std::numpunct<CharT>>(str.getloc()).decimal_point()))に一致する場合、'.'に置き換えられます。
    • 文字が桁区切り文字(std::use_facet<std::numpunct<CharT>>(str.getloc()).thousands_sep())に一致し、桁区切りが使用されている場合(std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping().length() != 0によって決定される)、小数点('.')がまだ蓄積されていない場合、その文字の位置が記憶されますが、文字自体は無視されます。すでに小数点が蓄積されている場合、その文字は破棄され、段階2は終了します。
    • いずれの場合も、前のステップで取得されたcharが、段階1で選択された変換指定子に従ってstd::scanfによって解析される入力フィールドで許可されているかどうかを確認します。許可されている場合は一時バッファに蓄積され、段階2が繰り返されます。許可されていない場合は、段階2は終了します。

[edit] 段階3: 変換と格納

  • 段階2で蓄積されたcharのシーケンスは数値値に変換されます。
std::scanfの規則に従って入力が解析されます。
(C++11まで)
入力は以下のように解析されます。
(C++11以降)
  • 変換関数がフィールド全体の変換に失敗した場合、値0vに格納されます。
  • vの型が符号付き整数型で、変換関数がそれを収めるのに大きすぎる正または負の値をもたらした場合、格納可能な最大正の値または最小負の値がそれぞれvに格納されます。
  • vの型が符号なし整数型で、変換関数がそれを収めるのに大きすぎる値をもたらした場合、格納可能な最大正の値がvに格納されます。
  • いずれの場合も、変換関数が失敗した場合、std::ios_base::failbiterrに設定されます。
  • それ以外の場合、変換の数値結果がvに格納されます。
    • vの型がboolでboolalphaが設定されていない場合、格納される値が0であればfalse1であればtrueが格納されます。それ以外の値の場合、std::ios_base::failbiterrに設定され、trueが格納されます。
  • その後、桁区切りがチェックされます。段階2で破棄された桁区切り文字の位置が、std::use_facet<std::numpunct<CharT>>(str.getloc()).grouping()によって提供されるグループ化と一致しない場合、std::ios_base::failbiterrに設定されます。
  • 段階2がin == endのテストによって終了した場合、err |= std::ios_base::eofbitが実行され、eofビットが設定されます。

[edit] 戻り値

in

[edit] 注記

LWG issue 23およびLWG issue 696の解決前は、エラーが発生した場合vは変更されませんでした。

LWG issue 221の解決前は、16進数整数の文字列(例:"0xA0")は、strtolで有効な入力であっても、段階2で文字'X'および'x'がフィルタリングされるため、do_get(int)によって拒否されていました。

LWG issue 1169の解決前は、符号なし整数への負の数値文字列の変換は、文字列で表される値がターゲット型で表現できる範囲よりも小さいため、ゼロになる可能性がありました。

LWG issue 2381の解決前は、16進数浮動小数点数の指数付き文字列(例:"0x1.23p-10")は、strtodで有効な入力であっても、段階2で文字'P'および'p'がフィルタリングされるため、do_get(double)によって拒否されていました。

無限大または非数(NaN)を表す文字列(例:"NaN"および"inf")は、strtodで有効な入力であっても、段階2で文字'N''i'のような文字がフィルタリングされるため、do_get(double)によって拒否されます。

(C++11以降)

[edit]

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

#include <iostream>
#include <iterator>
#include <locale>
 
struct base { long x; };
 
template<class CharT, class Traits>
std::basic_istream<CharT, Traits>&
    operator >>(std::basic_istream<CharT, Traits>& is, base& b)
{
    std::ios_base::iostate err = std::ios_base::goodbit;
 
    try // setting err could throw
    {
        typename std::basic_istream<CharT, Traits>::sentry s(is);
 
        if (s) // if stream is ready for input
            std::use_facet<std::num_get<CharT>>(is.getloc()).get(is, {}, is, err, b.x);
    }
    catch (std::ios_base::failure& error)
    {
        // handle the exception
    }
 
    return is;
}
 
int main()
{
    base b;
    std::cin >> b;
}

[edit] 不具合報告

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

DR 適用対象 公開された動作 正しい動作
LWG 17 C++98 テキストのブール値の解析プロセスが誤っていました。 修正済み
LWG 18 C++98 bool& 値を取るgetのオーバーロードが欠落していました。 追加された
LWG 23 C++98 オーバーフローする入力は未定義の動作を引き起こしました。 オーバーフローが処理されるようになりました。
LWG 154 C++98 doubleの変換指定子が%gfloatと同じ)でした。 %lgに変更されました。
LWG 221 C++98 strtolは解析したにもかかわらず、do_get'x'および'X'を解析しませんでした。 'x'および'X'が解析されるようになりました。
LWG 275 C++98 float&値の代わりにshort&値を取るgetのオーバーロードがありました。 修正済み
LWG 358 C++98 小数点以下の桁区切りが無視されていました。 遭遇した場合、段階2は終了します。
LWG 696 C++98 変換失敗時に結果が変更されませんでした。 ゼロに設定されるようになりました。
LWG 1169 C++98 浮動小数点型間でオーバーフローの処理が一貫していませんでした。 整合性が取れた
strtof/strtodとの間で。
LWG 2381 C++11 strtodは解析したにもかかわらず、do_get'p'および'P'を解析しませんでした。 'p'および'P'が解析されるようになりました。

[edit] 関連項目

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