2008-12-14 35 views
38

से एक std :: ostream प्राप्त करें, मैं किसी निश्चित प्रोग्राम स्थिति के आधार पर std::cout या std::ofstream ऑब्जेक्ट पर std::ostream कैसे बांधूं?std :: cout या std :: ofstream (file)

:

std::ostream out = condition ? &std::cout : std::ofstream(filename); 

मैं कुछ उदाहरण दिए गए अपवाद-सुरक्षित नहीं हैं, http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/34-2.html से इस तरह के रूप में एक देखा है: यह कई कारणों से अमान्य है, मैं कुछ है कि अर्थ की दृष्टि से निम्नलिखित के बराबर है प्राप्त करने के लिए चाहते हैं हालांकि

int main(int argc, char *argv[]) 
{ 
    std::ostream* fp;           //1 
    if (argc > 1) 
    fp = new std::ofstream(argv[1]);       //2 
    else 
    fp = &std::cout           //3 

    *fp << "Hello world!" << std::endl;       //4 
    if (fp!=&std::cout) 
    delete fp; 
} 

क्या कोई बेहतर, अपवाद-सुरक्षित समाधान जानता है?

उत्तर

52
std::streambuf * buf; 
std::ofstream of; 

if(!condition) { 
    of.open("file.txt"); 
    buf = of.rdbuf(); 
} else { 
    buf = std::cout.rdbuf(); 
} 

std::ostream out(buf); 

जो या तो कोउट या आउटपुट फ़ाइल स्ट्रीम के अंतर्निहित स्ट्रीमबफ को जोड़ता है। उसके बाद आप "बाहर" लिख सकते हैं और यह सही गंतव्य में समाप्त हो जाएगा। तुम सिर्फ चाहते हैं कि सब कुछ std::cout के लिए जा रहा एक फ़ाइल में चला जाता है, तो आप

std::ofstream file("file.txt"); 
std::streambuf * old = std::cout.rdbuf(file.rdbuf()); 
// do here output to std::cout 
std::cout.rdbuf(old); // restore 

करना यह दूसरी विधि दोष यह है कि यह अपवाद सुरक्षित नहीं है है रूप में अच्छी तरह कर सकते हैं। आप संभवतः एक कक्षा लिखना चाहते हैं जो आरएआईआई:

struct opiped { 
    opiped(std::streambuf * buf, std::ostream & os) 
    :os(os), old_buf(os.rdbuf(buf)) { } 
    ~opiped() { os.rdbuf(old_buf); } 

    std::ostream& os; 
    std::streambuf * old_buf; 
}; 

int main() { 
    // or: std::filebuf of; 
    //  of.open("file.txt", std::ios_base::out); 
    std::ofstream of("file.txt"); 
    { 
     // or: opiped raii(&of, std::cout); 
     opiped raii(of.rdbuf(), std::cout); 
     std::cout << "going into file" << std::endl; 
    } 
    std::cout << "going on screen" << std::endl; 
} 

अब, जो कुछ भी होता है, std :: cout स्वच्छ स्थिति में है।

+0

ओह, मुझे std :: streambuf * std :: ostream * – Tom

+0

से बेहतर पसंद है, लेकिन अगर कुछ फेंकता है, तो आपको अब नष्ट किए गए स्ट्रीम के अपने स्ट्रीमबफ * के कोउट में एक खतरनाक पॉइंटर के साथ छोड़ा जाएगा। तो सावधान रहें, एक RAII विधि बेहतर लिखो। –

+2

मुझे hdacking std :: cout पसंद नहीं है। इसका मतलब है कि कोउट और प्रिंटफ अब समकक्ष नहीं हैं, जो कुछ ऐसा है जो मुझे लगता है कि बहुत से डेवलपर्स को मंजूरी मिलती है। – Tom

22

यह अपवाद-सुरक्षित है:

void process(std::ostream &os); 

int main(int argc, char *argv[]) { 
    std::ostream* fp = &cout; 
    std::ofstream fout; 
    if (argc > 1) { 
     fout.open(argv[1]); 
     fp = &fout; 
    } 
    process(*fp); 
} 

संपादित करें: हर्ब Sutter लेख Switching Streams (Guru of the Week) में इस को संबोधित किया है।

+0

इस से किसी भी अधिक अपवाद-सुरक्षित नहीं लगता है मूल कोड – Brian

+0

हां यह है। प्रसंस्करण (* fp << "हैलो वर्ल्ड" << std :: endl) के दौरान एक अपवाद फेंक दिया गया है, तो मूल कोड में स्मृति रिसाव है। – Tom

+1

इस जवाब को मेरा वोट क्यों मिलता है कि पहला जवाब मेरा पुराना नियम तोड़ता है "अन्य वस्तुओं के आंतरिक के साथ गड़बड़ न करें"। सिर्फ इसलिए कि आप ** ** rdbuf को प्रतिस्थापित कर सकते हैं इसका मतलब यह नहीं है कि आपको चाहिए। –

10
std::ofstream of; 
std::ostream& out = condition ? std::cout : of.open(filename); 
+4

आप कैसे करते हैं .close()? –

+1

यह कैसे संकलित कर सकता है? 'Std :: ofstream :: open' का वापसी प्रकार 'शून्य' है। – Haoshu

0

सी ++ के लिए एक नौसिखिया होने के नाते, मैं अगर यह अपवाद-सुरक्षित है पता नहीं है, लेकिन यहाँ कैसे मैं आमतौर पर यह करना है:

std::ostream& output = (condition)?*(new std::ofstream(filename)):std::cout; 
संबंधित मुद्दे