55

StroustrupのTC++PL、第3版、セクション21.3.3から:

変数vを読み込もうとして操作が失敗した場合、vの値は変更されません(vがistreamまたはostreamメンバー関数によって処理されるタイプの1つである場合は変更されません)。

次の例は、上記の引用と矛盾しているように見えます。上記の見積もりに基づいて、vの値は変更されないままであると予想していましたが、ゼロになります。この明らかな矛盾した振る舞いの説明は何ですか?

#include <iostream>
#include <sstream>

int main( )
{
    std::stringstream  ss;

    ss  << "The quick brown fox.";

    int  v = 123;

    std::cout << "Before: " << v << "\n";

    if( ss >> v )
    {
        std::cout << "Strange -- was successful at reading a word into an int!\n";
    }

    std::cout << "After: " << v << "\n";

    if( ss.rdstate() & std::stringstream::eofbit  ) std::cout << "state: eofbit\n";
    if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
    if( ss.rdstate() & std::stringstream::badbit  ) std::cout << "state: badbit\n";

    return 1;
}

x86_64-w64-mingw32-g ++。exe(rubenvb-4.7.2-release)4.7.2を使用して取得した出力は次のとおりです。

Before: 123
After: 0
state: failbit

ありがとう。

4

2 に答える 2

62

このリファレンスから:

抽出が失敗した場合(たとえば、数字が期待される場所に文字が入力された場合)、値は変更されずに残され、failbitが設定されます(C ++ 11まで

抽出が失敗した場合、ゼロが値に書き込まれ、failbitが設定されます。抽出の結果、値が大きすぎたり小さすぎて値に収まらない場合は、std :: neuro_limits :: max()またはstd :: neuro_limits :: min()が書き込まれ、フェイルビットフラグが設定されます。(C ++ 11以降

コンパイラがC++11モードでコンパイルしているようですが、これにより動作が変わります。


input演算子は、関数がを呼び出すロケールファセットstd::num_getを使用します。C ++ 11の場合、etを使用するように指定されています。al。関数のタイプ。C ++ 11より前は、数値を抽出するためにスタイル解析を使用していたようです(参照によると、C ++ 03仕様にアクセスできません)。動作の変化は、入力の解析におけるこの変化によるものです。getdo_getstd::strtollstd::scanf

于 2012-11-14T12:45:20.813 に答える
4

演算子>>は、フォーマットされた入力演算子です。
そのため、入力がストリームからどのように読み取られるかは、ロケールによって異なります。

[istream.formatted.arithmetic]

インサーターの場合と同様に、これらのエクストラクターは、ロケールのnum_get <>(22.4.2.1)オブジェクトに依存して、入力ストリームデータの解析を実行します。これらのエクストラクタは、フォーマットされた入力関数として動作します(27.7.2.2.1で説明されています)。歩哨オブジェクトが構築された後、変換は次のコードフラグメントによって実行されるかのように行われます。

   typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
   iostate err = iostate::goodbit;
   use_facet< numget >(loc).get(*this, 0, *this, err, val);
   setstate(err);

上記のように、値は実際numgetにはストリームに埋め込まれたロケールのファセットによって設定されます。

num_get仮想関数[facet.num.get.virtuals]

ステージ3:

保存する数値は、次のいずれかになります。

  • 変換関数がフィールド全体の変換に失敗した場合はゼロ。ios_base::failbitはerrに割り当てられます。
  • フィールドがvalで表すには大きすぎる正の値を表す場合、最も正の表現可能な値。ios_base::failbitはerrに割り当てられます。
  • フィールドがvalで表すには大きすぎる負の値を表す場合は、最も負の表現可能な値、または符号なし整数型の場合はゼロ。ios_base::failbitはerrに割り当てられます。

ステージ3の定義は、n2723->n2798の間で大幅に変更されました

現在のCまたはC++標準ドキュメントはどこにありますか?

num_get仮想関数[facet.num.get.virtuals]

ステージ3:ステージ2の処理の結果は、次のいずれかになります。

  • 一連の文字がステージ2に蓄積され、(scanfの規則に従って)valのタイプの値に変換されます。この値はvalに格納され、ios_base::goodbitはerrに格納されます。
  • ステージ2で蓄積された文字のシーケンスにより、scanfは入力の失敗を報告します。ios_base::failbitはerrに割り当てられます。
于 2012-11-14T13:42:10.530 に答える