2014-11-30 48 views
5

Aynı verileri konsolda ve bir dosyada yazdırmam gereken bir kod yazıyorum. Ortak bir çıkış akışı nesnesini doldurmanın ve ardından cout'u kullanarak konsolda görüntülemenin ve fstream ve iostream kitaplıklarını kullanarak bir dosyaya vermenin bir yolu var mı?Konsolda ve C++ içindeki bir dosyada yazdırmak için ortak bir çıkış akışı nesnesi oluşturmanın bir yolu var mı?

+3

kullanın [ 'artırmak :: iostreams :: tee_device'] (http://www.boost.org/doc/libs/: Örneğin

, burada bu yaklaşımın basit bir uygulamasıdır 1_39_0/libs/iostreams/doc/işlevleri/tee.html). – 0x499602D2

+0

Bunu arama ortamında yapmanızı öneririm. –

cevap

6

Elbette. Yalnızca dahili olarak yazdığı diğer akış arabelleklerini depolayan uygun bir akış arabelleği oluşturursunuz. Bu akış arabelleğini kullanarak, yazdığınız bir std::ostream oluşturursunuz.

#include <streambuf> 
#include <ostream> 

class teebuf 
    : public std::streambuf 
{ 
    std::streambuf* sb1_; 
    std::streambuf* sb2_; 

    int overflow(int c) { 
     typedef std::streambuf::traits_type traits; 
     bool rc(true); 
     if (!traits::eq_int_type(traits::eof(), c)) { 
      traits::eq_int_type(this->sb1_->sputc(c), traits::eof()) 
       && (rc = false); 
      traits::eq_int_type(this->sb2_->sputc(c), traits::eof()) 
       && (rc = false); 
     } 
     return rc? traits::not_eof(c): traits::eof(); 
    } 
    int sync() { 
     bool rc(false); 
     this->sb1_->pubsync() != -1 || (rc = false); 
     this->sb2_->pubsync() != -1 || (rc = false); 
     return rc? -1: 0; 
    } 
public: 
    teebuf(std::streambuf* sb1, std::streambuf* sb2) 
     : sb1_(sb1), sb2_(sb2) { 
    } 
}; 

class oteestream 
    : private virtual teebuf 
    , public std::ostream { 
public: 
    oteestream(std::ostream& out1, std::ostream& out2) 
     : teebuf(out1.rdbuf(), out2.rdbuf()) 
     , std::ostream(this) { 
     this->init(this); 
    } 
}; 

#include <fstream> 
#include <iostream> 

int main() 
{ 
    std::ofstream fout("tee.txt"); 
    oteestream tee(fout, std::cout); 
    tee << "hello, world!\n"; 
} 
+1

Özel bir akış arabelleği burada olsa çok fazla olabilir. Bir "stringstream" e kaydetme ve bunu iki kez çıkarmanız yeterli olabilir. Her neyse, iyi biri. (BTW: Bu kodun etrafta yattığını mu düşünüyorsun?) – Deduplicator

+1

@Deduplicator: Evet, kullanması uygun bir çözüm ve uygun bir çözüm olan bir çözüm var. Akış arabelleğini bir "std :: ostream" haline getirerek tee akışı arabelleğini kullanmak oldukça güzel hale getirir. ... ve evet, bu kodun etrafında yalan söyledim: _that_ fast :-) yazmam. –