2016-08-03 17 views
18

ストリーミングであるいくつかのタイプを考える:私はstd::stringにこれを追加したいStreamオブジェクト::文字列

struct X { 
    int i; 

    friend std::ostream& operator<<(std::ostream& os, X const& x) { 
     return os << "X(" << x.i << ')'; 
    } 
}; 

を。

void append(std::string& s, X const& x) { 
    std::ostringstream os; 
    os << x; 
    s.append(os.str()); 
} 

をしかし、私はちょうどそのちょうど別のものにそれを追加する目的のために新しい文字列を割り当てるために一つのストリームにデータを書いているので、これはラメようだ:私はこれを実装することができます。より直接的なルートはありますか?

+0

私はhttp://www.boost.org/doc/libs/1_61_0/doc/html/interprocess/streams.htmlを参照してください – bobah

+0

おそらく 'std :: string X :: repr()'などを実装しますそれを 'append'と' operator << 'の両方で呼び出しますか?理想的ではありませんが、中間の 'stringstream'は避けてください。 – Praetorian

+0

単純に 's.append(std :: string :: to_string(x));'?私は何かが欠けていましたか? –

答えて

13

これは、新しいタイプのstreambufで解決できます(Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference参照)。ここで

はそれが見えることができる方法のスケッチです:

#include <streambuf> 

class existing_string_buf : public std::streambuf 
{ 
public: 
    // Store a pointer to to_append. 
    explicit existing_string_buf(std::string &to_append); 

    virtual int_type overflow (int_type c) { 
     // Push here to the string to_append. 
    } 
}; 

あなたがここに詳細を肉付けしたら、次のように、あなたはそれを使用することができます:

#include <iostream> 

std::string s; 
// Create a streambuf of the string s 
existing_string_buf b(s); 
// Create an ostream with the streambuf 
std::ostream o(&b); 

今、あなただけのoに書き込み、結果はsに追加されたように表示されます。 xsputnを上書き編集

@rustyxが正しく指摘したよう

// This will append to s 
o << 22; 

は、パフォーマンスを向上させるために必要とされます。

全例

次のプリント22

#include <streambuf> 
#include <string> 
#include <ostream> 
#include <iostream> 

class existing_string_buf : public std::streambuf 
{ 
public: 
    // Somehow store a pointer to to_append. 
    explicit existing_string_buf(std::string &to_append) : 
     m_to_append(&to_append){} 

    virtual int_type overflow (int_type c) { 
     if (c != EOF) { 
      m_to_append->push_back(c); 
     } 
     return c; 
    } 

    virtual std::streamsize xsputn (const char* s, std::streamsize n) { 
     m_to_append->insert(m_to_append->end(), s, s + n);                     
     return n; 
    } 

private: 
    std::string *m_to_append; 
}; 


int main() 
{ 
    std::string s; 
    existing_string_buf b(s); 
    std::ostream o(&b); 

    o << 22; 

    std::cout << s << std::endl; 
} 
+2

良いパフォーマンスを得るために 'xsputn()'をオーバーライドします。 – rustyx

+0

@rustyx優れた点。追加されました。多くのありがとう –

+4

私はC++を知っているように感じる時があります。これはその時代の一つではありません。 – Barry

1

あなたがのstd ::文字列のキャスト演算子書くことができます:次に

struct X { 
int i; 

friend std::ostream& operator<<(std::ostream& os, X const& x) { 
    os << "X(" << x.i << ')'; 
    return os; 
} 

operator std::string() { 
    return std::string("X(") + std::to_string(x.i) + ")"; 
} 

}; 

を、あなたは単にそれを追加することができa std :: string:

X myX; 
myX.i = 2; 
std::string s("The value is "); 
s.append(myX); //myX is cast into the string "X(2)" 
+0

しかし、今は同じロジックを2回持っています。 – Barry

+0

真。演算子<<メソッドの最初の行を "os << static_cast (x);"に変更してください。 – HeywoodFloyd

-1

元の文字列は既存の割り当てに十分なだけの大きさなので、ストリームに一度追加したいものをすべてフォーマットしてから、その結果を追加することをお勧めします。

これらのアペンドを頻繁に実行する予定がある場合は、std :: stringが間違ったタイプであると主張します。 std :: stringの代わりにstd :: ostringtreamを直接使用して、最終結果が必要なときにのみ文字列に変換することをお勧めします。私はKISSの原則に従うだろう。この特定のケースで

1

struct X { 
    int i; 

    std::string toString() const { 
     return "X(" + std::to_string(i) + ")"; 
    } 
}; 

使用法:

string += x.toString(); 
std::cout << x.toString(); 

operator<<(std::ostream&, …)は、一般的な文字列変換のために本当に適していないので、それが何だ場合'その後は、toStringのメソッド/フリー関数の方がはるかに優れています。そしてもしあなたがstd::cout << xを望むのであれば、operator<<を簡単に実装してtoStringと呼ぶことができます。

関連する問題