2016-08-03 3 views
18

कुछ प्रकार यह देखते हुए कि स्ट्रीम करने योग्य है:स्ट्रीम वस्तु :: स्ट्रिंग

struct X { 
    int i; 

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

मैं एक std::string पर इस संलग्न करना चाहते हैं। मैं के रूप में यह लागू कर सकते हैं:

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()' या इसी तरह लागू करें , और कॉल करें कि 'एपेंड' और 'ऑपरेटर <<' दोनों में? आदर्श नहीं है, लेकिन आप मध्यवर्ती 'स्ट्रिंगस्ट्रीम' से बचें। – 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 में संलग्न के रूप में दिखाई देना चाहिए।

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

संपादित

@rustyx सही ढंग से नोटों के रूप में, xsputn अधिभावी प्रदर्शन में सुधार के लिए आवश्यक है।

पूर्ण उदाहरण

निम्नलिखित प्रिंट 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

ऐसे समय होते हैं जब मुझे लगता है कि मुझे सी ++ पता है। यह उन समयों में से एक नहीं है। – 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) + ")"; 
} 

}; 

, तो आप बस इसे करने के लिए संलग्न कर सकता है एक std :: स्ट्रिंग:

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

ठीक है लेकिन अब मेरे पास दो बार एक ही तर्क है। – Barry

+0

सच है। ऑपरेटर की पहली पंक्ति << विधि से "os << static_cast (x);" बदलें। – HeywoodFloyd

-1

चूंकि मूल स्ट्रिंग केवल मौजूदा आवंटन के लिए पर्याप्त है, इसलिए आप उम्मीद कर सकते हैं कि स्ट्रीम में एक बार जो कुछ भी आप जोड़ना चाहते हैं उसे प्रारूपित करना है, फिर परिणाम को अपने उदाहरण में जोड़ दें।

यदि आप अक्सर इन परिशिष्टों को करने की योजना बनाते हैं, तो मैं तर्क दूंगा कि std :: string समस्या के लिए गलत प्रकार है। मैं एक std :: स्ट्रिंग के बजाय सीधे std :: ostringtream का उपयोग करने की अनुशंसा करता हूं, और अंतिम परिणाम की आवश्यकता होने पर ही केवल एक स्ट्रिंग में कनवर्ट करें।

1

इस विशिष्ट मामले में मैं सिर्फ KISS सिद्धांत का पालन करेंगे:

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 चाहते हैं तो आप toString पर कॉल करने के लिए operator<< को तीन बार कार्यान्वित कर सकते हैं।

संबंधित मुद्दे