2012-09-20 32 views
7

एक विधि है कि एक stringstream लेता लिख ​​सकते हैं और यह कुछ इस तरह दिखाई है,सी ++ के बाद stringstream का उपयोग << पैरामीटर के रूप में

void method(string str) 
void printStringStream(StringStream& ss) 
{ 
    method(ss.str()); 
} 

क्या यह संभव है और यह

stringstream var; 
printStringStream(var << "Text" << intVar << "More text"<<floatvar); 

की तरह कहा जा सकता है मैंने < < ऑपरेटर को देखा और ऐसा लगता है कि यह ostream& ऑब्जेक्ट देता है लेकिन मैं शायद this गलत पढ़ रहा हूं या इसे सही तरीके से कार्यान्वित नहीं कर रहा हूं।

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

नोट्स:

मैं c++11 जवाब में से ज्यादा उपयोग नहीं कर सकते, क्योंकि मैं दृश्य स्टूडियो 2010 पर चल रहा हूँ (मेरी इच्छा के विरुद्ध, लेकिन अभी भी)

मैं Boost की पहुंच है तो पागल हो जाना उस के साथ।

जब तक यह इस गड़बड़ी को साफ नहीं करता तब तक मैं एक कस्टम विधि के खिलाफ नहीं होगा।

संपादित करें:

@Mooing @PiotrNycz वाक्य रचना के साथ मिश्रित बतख का जवाब मैं इस तरह से लिखा कोड के अपने लक्ष्य को हासिल किया के साथ,

try{ 

    //code 

}catch(exception e) 
{ 
    printStringStream(stringstream() << "An exception has occurred.\n" 
          <<" Error: " << e.message 
          <<"\n If this persists please contact "<< contactInfo 
          <<"\n Sorry for the inconvenience"); 
} 

इस रूप में स्वच्छ और पठनीय है के रूप में मैं आशाओं के अनुकूल हो के लिये।

उम्मीद है कि यह दूसरों को लेखन संदेश साफ़ करने में मदद करता है।

+2

विजुअल स्टूडियो 11 में संपूर्ण सी ++ 11 लाइब्रेरी है, और कई भाषा विशेषताएं हैं। _Which_ विजुअल स्टूडियो आप तक सीमित हैं? इसके अलावा, पूंजीकरण के अलावा, कोड मेरी आंखों के लिए ठीक दिखता है; ठीक काम करना चाहिए। –

+0

क्या आपने कोशिश की? यदि हां, तो क्या हुआ? यदि नहीं - क्यों? –

+0

आप पहले स्ट्रीम को क्यों भरते हैं, फिर इसे तर्क के रूप में पास करते हैं? –

उत्तर

8

आह, मुझे एक मिनट लगा। चूंकि operator<<सभी ओस्ट्रीम प्रकारों के लिए एक नि: शुल्क फ़ंक्शन ओवरलोड किया गया है, यह std::stringstream वापस नहीं करता है, यह आपके जैसे std::ostream देता है।

void printStringStream(std::ostream& ss) 

अब स्पष्ट रूप से, सामान्य ostream एक .str() सदस्य नहीं है, लेकिन वे एक से दूसरे पूरे धारा कॉपी करने के लिए एक जादू तरीका है :

std::cout << ss.rdbuf(); 

यहाँ करने के लिए एक लिंक भी है पूर्ण कोड दिखा रहा है कि यह संकलित करता है तथा ठीक चलाता http://ideone.com/DgL5V

संपादित

क्या तुम सच में समारोह में एक स्ट्रिंग की जरूरत है, मैं कुछ समाधान के बारे में सोच सकते हैं:,

पहले कर अलग से स्ट्रीमिंग:

stringstream var; 
var << "Text" << intVar << "More text"<<floatvar; 
printStringStream(var); 

दूसरा: एक स्ट्रिंग (संभव प्रदर्शन मुद्दा) में स्ट्रीम कॉपी

void printStringStream(ostream& t) 
{ 
    std::stringstream ss; 
    ss << t.rdbuf(); 
    method(ss.str()); 
} 

तीसरा: अन्य समारोह एक धारा भी

+0

और यहां मैं 'rdbuf' के बजाय 'copy' के साथ प्रयोग कर रहा था। – chris

+0

इसलिए मुझे पता है कि यह वास्तव में स्पष्ट नहीं था क्योंकि मैं उदाहरण के लिए अपनी समस्या को सरल बना रहा हूं, लेकिन मुझे इस विधि के अंदर एक स्ट्रिंग की आवश्यकता है जो इसे इस तरह दिखने वाले किसी अन्य फ़ंक्शन पर पास करे। 'शून्य विधि (स्ट्रिंग str) 'मैं' rdbuf() 'को उस चीज़ में कैसे बदलूं जो उसके साथ काम करता है? – Dan

+0

यह प्रीफेक्ट है! मेरा 'विधि' वास्तव में एक टाइम स्टैम्प को जोड़ने के लिए एक और' स्ट्रिंगस्ट्रीम 'का उपयोग करता है और लॉगिंग के लिए कुछ अन्य जानकारी को जोड़ता है, इसलिए मैं इसे' स्ट्रिंग 'के बजाय' स्ट्रीमबफ * 'लेता हूं और मेरी समस्याएं खत्म हो जाती हैं। एक नोब के रूप में मुझे एहसास नहीं हुआ कि मैं '<<' कर सकता हूं। बहुत बहुत धन्यवाद! – Dan

3

लेखन वस्तुओं को आसानी से स्ट्रीम में डाला जा सकता है, इन सभी वर्गों को ostream& पर अधिभारित किया गया है। (ऑपरेटर ओवरलोडिंग का उपयोग सबक्लास द्वारा किया जा सकता है, यदि कोई करीबी मिलान मौजूद नहीं है।) ये operator<< सभी रिटर्न ostream& ओवरलोड करता है।

आप क्या कर सकते हैं यह कार्य ostream& और dynamic_cast<> पर stringstream& पर ले जाता है। यदि गलत प्रकार बीत चुका है, bad_cast फेंक दिया गया है।

void printStringStream(ostream& os) { 
    stringstream &ss = dynamic_cast<stringstream&>(os); 
    cout << ss.str(); 
} 

नोट: static_cast<>, इस्तेमाल किया जा सकता यह तेजी से होगा, लेकिन इस मामले में ऐसा नहीं बग सबूत आप कुछ है कि एक stringstream नहीं है पारित कर दिया।

2

वापसी मान लेने के बाद से आप जानते हैं कि आप एक stringstream मिल गया है, बस डाली बनाने:

stringstream var; 
printStringStream(static_cast<stringstream&>(var << whatever)); 
3

अपने रैपर को std :: stringstream पर बनाएं। इस नई श्रेणी में आप परिभाषित कर सकते हैं जो कुछ भी operator << आप की जरूरत:

class SSB { 
public: 
    operator std::stringstream&() { return ss; } 

    template <class T> 
    SSB& operator << (const T& v) { ss << v; return *this; } 
    template <class T> 
    SSB& operator << (const T* v) { ss << v; return *this; } 
    SSB& operator << (std::ostream& (*v)(std::ostream&)) { ss << v; return *this; } 
    // Be aware - I am not sure I cover all <<'s  
private: 
    std::stringstream ss; 
}; 

void print(std::stringstream& ss) 
{ 
    std::cout << ss.str() << std::endl; 
} 

int main() { 
    SSB ssb; 
    print (ssb << "Hello" << " world in " << 2012 << std::endl); 
    print (SSB() << "Hello" << " world in " << 2012 << std::endl); 
} 
+0

+1 मैं 'स्ट्रिंगस्ट्रीम() << सामान' कर रहा था, यह पूरे समय जो इसे 1 लाइन पर केंद्रित करता है। – Dan

+0

यह सही है! बस मैं जो खोज रहा था, इसलिए मैं '<<' नोटेशन का उपयोग करके आसानी से किसी भी और सभी वस्तुओं को प्रिंट कर सकता हूं, और 'cout' पर जाने से पहले प्रिंट() फ़ंक्शन रैपर से गुजरना चाहता हूं। – gbmhunter

0

बस मिश्रण में जोड़ने के लिए:

#include <sstream> 
#include <iostream> 

void someFunction(std::string const& value) 
{ 
    std::cout << "someFunction(" << value << ")\n"; 
} 

void method(std::string const& value) 
{ 
    std::cout << "method(" << value << ")\n"; 
} 

class FunctionStream 
    : private virtual std::stringbuf 
    , public std::ostream 
{ 
public: 
    FunctionStream() 
     : std::ostream(this) 
     , d_function(&method) 
    { 
    } 
    FunctionStream(void (*function)(std::string const&)) 
    : std::ostream(this) 
    , d_function(function) 
    { 
    } 
    ~FunctionStream() 
    { 
     this->d_function(this->str()); 
    } 
private: 
    void (*d_function)(std::string const&); 
}; 

int main(int ac, char* av[]) 
{ 
    FunctionStream() << "Hello, world: " << ac; 
    FunctionStream(&someFunction) << "Goodbye, world: " << ac; 
} 
: व्यक्तिगत रूप से, मैं एक धारा जो कहता है जो कुछ भी समारोह मैं विनाश पर कॉल करने की आवश्यकता पैदा करेगा

यह ध्यान देने योग्य है कि अस्थायी को भेजी गई पहली वस्तु को विशिष्ट प्रकार के प्रकारों का होना चाहिए, अर्थात् उनमें से एक, वर्ग std::ostream इस बारे में जानता है: आम तौर पर, शिफ्ट ऑपरेटर पहले तर्क के रूप में std::ostream& लेता है लेकिन अस्थायी नहीं हो सकता इस प्रकार से बंधे हैं। हालांकि, ऐसे कई सदस्य ऑपरेटर हैं जो सदस्य होने के नाते, किसी संदर्भ से जुड़ने की आवश्यकता नहीं है! यदि आप पहले उपयोगकर्ता परिभाषित प्रकार का उपयोग करना चाहते हैं, तो आपको एक संदर्भ अस्थायी निकालने की आवश्यकता है जिसे सदस्य इनपुट ऑपरेटरों में से किसी एक का उपयोग करके किया जा सकता है।

+0

मुझे लगता है कि मैं लगभग यहां क्या हो रहा है। क्या आप कुछ उदाहरण इनपुट और आउटपुट जोड़ सकते हैं ताकि मैं आपके द्वारा यहां किए गए लॉक में लॉक कर सकूं? – Dan

+0

मुझे लगता है कि यह 'विधि (हैलो, दुनिया:: ##) कुछ फ़ंक्शन (अलविदा, दुनिया: ##) 'है जहां' ## 'तर्कों की संख्या है। क्या यह सही है? – Dan

+0

हां: संबंधित फ़ंक्शन स्ट्रिंग स्वरूपित के साथ कहा जाता है। मुख्य बिंदु यह है कि इसमें केवल एक विशेष इकाई शामिल है ('फंक्शनस्ट्रीम' ऑब्जेक्ट) और कोई कलाकार या कुछ भी आवश्यक नहीं है। –

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

  • कोई संबंधित समस्या नहीं^_^