2013-10-21 43 views
1

我有一個std::istream對象的列表,我需要作爲一個單一的std::istream對象出現。因此,如果我有三個istream s,A,B和C,我希望能夠創建一個istream,D將首先返回來自A的字節,然後返回來自B的字節,然後在達到EOF之前C。複合流將始終按順序讀取,並在所有字節被讀取後關閉。複合std :: istream在C++

有沒有一種簡單的方法來使用stl/boost來做到這一點,或者我只需要寫我自己的複合istream?

+0

檢出Boost.Iostreams。 – GManNickG

+0

直到你需要從std :: ios繼承,我會說最直接的方法是構建一個複合istream,有一個其他流的隊列。 –

+0

你是說你有一個* std :: list * *的istreams?含義'std :: list '? – 0x499602D2

回答

0

另一個問題(https://stackoverflow.com/a/17103292/1424877)的無題答案可能對您有所幫助。

#include <iostream> 
#include <string> 
#include <sstream> 

class ConcatStreams : public std::streambuf 
{ 
    int useBuf; 
    std::streambuf *sbuf_[2]; 
    char buffer_[1024]; 

    public: 
    ConcatStreams(std::istream& sbuf1, std::istream& sbuf2) : 
     useBuf(0), sbuf_{sbuf1.rdbuf(), sbuf2.rdbuf()} 
    { } 

    int underflow() 
    { 
     if (this->gptr() == this->egptr()) { 
      std::streamsize size = 0; 
      while (useBuf < 2) { 
       size = this->sbuf_[useBuf]->sgetn(this->buffer_, sizeof this->buffer_); 
       if (!size) { 
        useBuf++; 
       } else { 
        break; 
       } 
      } 
      this->setg(this->buffer_, this->buffer_, this->buffer_ + size); 
     } 
     return this->gptr() == this->egptr() 
      ? std::char_traits<char>::eof() 
      : std::char_traits<char>::to_int_type(*this->gptr()); 
    } 
}; 

int main() 
{ 
    std::istringstream is("hello world!\n"); 

    ConcatStreams cs_(is, std::cin); // prepend "hello world" to the input 
    std::istream cs(&cs_); 

    std::string s; 
    while (cs >> s) 
     std::cout << "'" << s << "'" << std::endl; 
} 

注意,你不能用這種特殊的技巧來連接std::cin與本身,甚至is自身;但它應該很好地連接任何兩個不同的輸入流。你甚至可以連接多個ConcatStreams實例!