std :: stringstreamおよびstring format

情報の入力と出力は重要なタスクであり、これがなければプログラムは役に立たなくなります。 C ++では、この問題を解決するために、標準のIOStreamライブラリに実装されているI / Oストリームが伝統的に使用されています。

このアプローチの利点は次のとおりです。
-普遍性:ストリームの接続先は関係ありません-コンソール、ファイル、ソケットからの入力/出力、プロセスは同じです。
-透明性:プログラマは、入力または出力オブジェクトのタイプを明示的に示す必要はありません。
-拡張性:プログラマは、対応する演算子をオーバーロードするだけで、オブジェクトのストリームにI / Oサポートを追加できます。

IOStreamライブラリには、入力/出力ストリームをメモリ内の文字列に関連付けることができるstringstreamクラスもあります。 そのようなストリームに出力されるものはすべて、行の最後に追加されます。 ストリームから読み取られるものはすべて、行の先頭から取得されます。

たとえば、型変換を実行するなど、非常に面白いことを行うことができます。



 #include <sstream> #include <iostream> int main(int argc, char* argv[]) { std::stringstream ss; ss << "22"; int k = 0; ss >> k; std::cout << k << std::endl; return 0; } 


さらに、このクラスを使用して、たとえば次のような複雑な文字列をフォーマットできます。

 void func(int id, const std::string& data1, const std::string& data2) { std::stringstream ss; ss << "Operation with id = " << id << " failed, because data1 (" << data1 << ") is incompatible with data2 (" << data2 << ")"; std::cerr << ss.str(); } 


この場合、メッセージを直接cerr出力できるため、 stringstreamの使用stringstream不要であることは明らかです。 しかし、メッセージを標準ストリームではなく、たとえばsyslog()関数を使用してシステムログに出力する場合はどうでしょうか。 または、この行を説明として含む例外をスローします。

 void func(int id, const std::string& data1, const std::string& data2) { std::stringstream ss; ss << "Operation with id = " << id << " failed, because data1 (" << data1 << ") is incompatible with data2 (" << data2 << ")"; throw std::runtime_error(ss.str()); } 


最初に文字列を形成し、次にstr()メソッドを使用して取得する中間stringstreamオブジェクトが必要であることがstringstreamます。 同意しますか?

C ++は 、その過度の複雑さと冗長性のせいにされることがありますが、場合によっては、非常にエレガントなデザインを作成できます。 そして今、 テンプレート演算子オーバーロードする機能により、 stringstreamラッパーを作成することができました。

 void func(int id, const std::string& data1, const std::string& data2) { throw std::runtime_error(MakeString() << "Operation with id = " << id << " failed, because data1 (" << data1 << ") is incompatible with data2 (" << data2 << ")"); } 


そして、ここにMakeString自体があります。

 class MakeString { public: template<class T> MakeString& operator<< (const T& arg) { m_stream << arg; return *this; } operator std::string() const { return m_stream.str(); } protected: std::stringstream m_stream; }; 


とても簡単に機能します。 一方、 MakeStringクラスでは、 MakeString演算子(<<)がオーバーロードされます。これは、任意の型のオブジェクトへの定数参照を引数として受け取り、このオブジェクトを内部のMakeStringに直ちに出力し、それ自体へのリンクを返します。 一方、文字列への変換演算子はオーバーロードされ、 stringstreamによって形成された文字列を返します。

おそらく、このラッパーは誰かに役立つことがわかるでしょう。 私はコメント、提案、提案を聞いてうれしいです。

Source: https://habr.com/ru/post/J131977/


All Articles