10

ostream &パラメータを取り、oその ostream に書き込む関数があるとします。operator <<実装は良い例です。

ostream& operator << (ostream& o, const MyThing& t)
{
  // ... interesting code here ...
  return o;
}

関数内で、ストリームの書式設定オプションを指定したい場合があります。oたとえば、関数に渡されるときに がどのように構成されていても、数値を 16 進数として出力したい場合があります。

第 2 に、現在の書式設定フラグについて推測できるようになりたいと思うかもしれません。たとえば、別の方法で要求しない限り、数値が 10 進数としてフォーマットされていると想定できると便利です。

最後に、関数が終了するまでに、書式設定オプションをo関数が呼び出される前と同じにして、呼び出し元に変更されないようにします。これは単に発信者に対する礼儀の問題です。

これまではostringstream、関数内に local を作成し、その上ですべての作業 (書式設定オプションの設定を含む) を行い、関数の最後に .str()toを送信することでこれを達成してきました。ここでの StackOverflow の質問は、私より賢い人が同じアプローチを取ることを示唆しています。 ただし、ostringstreams に非常に多くのデータを保持しているため、以前に出力に送信される可能性があることが気になります (文字列が非常に大きくなる可能性があります)。o

2 つの質問があります。

1)一時的な(スタックベースの)ostreamを作成し、そのostreamで作業を行うことは、合法的、慣用的、適切な形式ですか?o.rdbuf()私自身のテストとcppreference.comのページは、私ができることを示唆しているようです。

ostream& operator << (ostream& o_, const MyThing& t)
{
  ostream o (o_.rdbuf());
  // write stuff to "o",
  // setting formatting options as I go.
  return o_; // Formatting on the parameter ostream o_ unchanged.
}

2)私が考えていない別のより良い方法はありますか?

4

3 に答える 3

2

Boost IO State Saverはまさにこの目的のために構築されています。

于 2014-11-06T12:07:34.867 に答える
1

それは悪い解決策ではありません。それは確かに合法です。あまり一般的ではないと思うので、なぜそうしているのかについてコメントすることをお勧めします。

私がここで見た最も頻繁な解決策は、コンストラクターで必要なすべての状態 (通常はflags()precision()およびfill()) を保存し、デストラクタでそれを復元してから、強制的にすべての状態を設定するステート セーバー クラスを作成することです。必要なオプション。(これを使用することは可能かもしれませんがcopyfmt、これは例外マスクのようなものもコピーしますが、これはおそらく使いたくないでしょう。)

于 2014-11-06T12:23:57.280 に答える
0

設定は、iostream に含まれている ios というクラスで定義された、fmtflags オブジェクトと呼ばれるオブジェクトのタイプに格納できます。これらのオブジェクトのいずれかを宣言できますが、スコープ解決演算子を使用して宣言する必要があります。

次のステートメントは、フォーマット状態の特定の側面を変数 old_settings に保存します。

ios::fmtflags old_settings = cout.flags();

次に、新しい設定を使用して出力を行った後、古い設定を引数として同じ関数を呼び出すことで、古い設定を復元できます。

cout.flags(old_settings);

その他の設定は、メンバー関数を使用して取得および復元できます。例えば、

int old_precision = cout.precision();

現在の精度仕様を保存します。それで

cout.precision(old_precision);

精度を元の値に戻します

于 2014-11-06T12:07:22.253 に答える