ostringstreamを再利用する方法?


回答:


156

私は過去にclearとstrのシーケンスを使用しました:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

これは、入力文字列ストリームと出力文字列ストリームの両方に対応しています。または、手動で消去してから、最初に適切なシーケンスを探すこともできます。

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

これによりstr、代わりに現在出力バッファにあるものを上書きすることによって行われる一部の再割り当てが防止されます。結果は次のようになります。

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

文字列をC関数に使用したい場合は、を使用してstd::ends、次のように終端のnullを挿入できます。

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::endsstd::strstreamスタックに割り当てたchar配列に直接書き込むことができた非推奨のの遺物です。終端のnullを手動で挿入する必要がありました。ただし、std::endsは非推奨ではありません。上記の場合と同様に、まだ有用であるためです。


私はostreamでs.str()を使用しようとしています。サイズがめちゃくちゃになっています(最初の文字がnullであることがわかりますが、はるかに多く印刷されます)。strの長さを修正する良い方法はありますか?私はs.str()。c_str();を使用しています。ATMとそれはうまく機能します

実際、これも正しくありません。s.str("");代わりにやった。auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;

std :: endsはGoogleテストでは機能しません。boost::any a = 1; std::ostringstream buffer; buffer << a << std::ends; EXPECT_EQ( buffer.str(), "any<(int)1>" ); TestUtilsTest.cpp:27: Failure Expected: buffer.str() Which is: "any<(int)1>\0" To be equal to: "any<(int)1>" 異なる長さの文字列で再利用すると、ビットが残ります
David van Laatum

再割り当てを避けたい場合は、Alternativeが真の答えです。また、再割り当てをせずに本当に「最初からやり直したい」場合は、std :: endを送信した後、もう一度seekp(0)を呼び出します。s.seekp(0); s << std::ends; s.seekp(0);
チップグランディット2017年

5

ostr.str("")呼び出しがトリックを行うように思われます。


9
これはostringstreamの基になるバッファーを再利用しないことを指摘する価値があります。新しいバッファーを割り当てるだけです。したがって、ostringstreamオブジェクトを再利用している間も、2つのバッファーを割り当てています。ostringstreamは、意図した方法で再利用できるように設計されているとは思いません。
razlebe 2009年

2
また、状態をクリアしません。これは.clear()が行うことです。私は同意します、それは本当にこのように使用されることを意図していません。確かに新しいものを作成してください。あなたがプロファイリングした場合のみ、それが何らかの違いを生むかどうかが分かります。
Brian Neal

1
あいさつ、ブライアン、そうだね。ただし、上記のlitbのメソッドではstd :: endsを使用する必要があることに注意してください。バッファを再利用しますが、通常どおりstringstreamsを使用してコードを変更します(通常はstd :: endsを使用しません)。
ディエゴセビリア

2

最初に使用する前にバッファがクリアされるような方法でバッファをクリアする場合は、まずMSVCを使用してバッファに何かを追加する必要があります。

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
    template<class T>
    inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

VS2012で問題のある動作は見られません。さらに、通話がclearします原因failbitストリームが空である場合に設定します。seekpストリームが存在しない場合は、呼び出しだけで戻ります。
ジョナサンミー2014

0

あなたはしません。明確にするために2つの異なる名前のストリームを使用し、最適化コンパイラーが古いストリームを再利用できることを認識させます。


4
コードが入力データをループし、ostringstream(読み取ったデータに基づいて)に書き込み、ostringstream時々(たとえば、特定の文字シーケンスが読み取られた後)どこかに構築された文字列を書き込む必要があるユースケースを検討してください。新しい文字列を作成します。
Andre Holzner、2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.