2012-01-11 78 views
21

我想(通過istream接口,以便閱讀載體可以做)來包裝一個vector<char>std::istreamC++:與istream的

怎樣做的方式包裝矢量

+0

它不完全清楚你想要做什麼。你能舉一個你想寫的代碼的例子嗎? – 2012-01-11 06:45:29

+0

我使用一個需要使用istream的庫。但我手邊只有一個矢量,因此我需要以某種方式包裝它 – GabiMe 2012-01-11 06:48:37

+0

這是否足夠:http://stackoverflow.com/questions/4991697/wraps-a-vectorunsigned-char-inside-a-stream – 2012-01-11 06:53:34

回答

27

你會定義一個streambuf子包裹vector,並通過這方面的一個實例的istream的構造。

如果數據在構建後沒有改變,則使用streambuf::setg()設置數據指針就足夠了;對其他成員的默認實現做正確的事:

template<typename CharT, typename TraitsT = std::char_traits<CharT> > 
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT> { 
public: 
    vectorwrapbuf(std::vector<CharT> &vec) { 
     setg(vec.data(), vec.data(), vec.data() + vec.size()); 
    } 
}; 

std::vector<char> data; 
// ... 
vectorwrapbuf<char> databuf(data) 
std::istream is(&databuf); 

如果你需要什麼比這更先進,覆蓋streambuf::underflow方法。

+0

謝謝。可以將醜陋的* vec.begin()替換爲vec.data()? – GabiMe 2012-01-11 07:10:18

+0

當然,可以用'vec.data()+ vec.size()'替換'&* vec.end()'。 – 2012-01-11 07:21:12

+1

注意:'std :: istream'不釋放指針。更好地在堆棧上創建流緩衝區。 – ybungalobill 2012-01-11 07:25:03

2

你會可以逃脫只需建立一個實現了>>操作如流類,像這樣:

template<class _ITy> 
class RangeStreamLite 
{ 
private: 

    _ITy Begin; 
    _ITy End; 
    _ITy Next; 

public: 

    RangeStreamLite(_ITy begin, _ITy end) : 
     Begin(begin), 
     End(end), 
     Next(begin) 
    { 
     // Do nothing. 
    } 

    template<class _OTy> 
    RangeStreamLite& operator>>(_OTy& out) 
    { 
     out = *Next; 
     ++Next; 
     return *this; 
    } 


    void reset() 
    { 
     Next = Begin; 
    } 
}; 

這是一個「快速和骯髒的解決方案,一個「流精簡版',它並不是真正意義上的流,但它可以在你需要的只是一種表面流式的設備時起作用。要正確地創建一個自定義流會稍微複雜一些,並且需要從std :: streambuf繼承並實現必要的功能。這裏有幾個環節值得一看:

-1

您將不得不編寫一個繼承自istream的自定義流實現。這可以通過使用Boost.Iostreams輕鬆完成 - 您只需執行簡單的Source即可。

+1

Downvote是因爲間接/鏈接到解決方案而不是提供它們違反了Stack Overflow的概念。 – Catskul 2016-06-21 23:12:26

5

適應從Get an istream from a char*的答案,假設這是你想要做什麼:

// Forward declarations 
std::vector<char> my_create_buffer(); 
void my_consume_buffer(std::istream & is); 

// What you want to be able to write 
std::vector<char> buffer = my_create_buffer(); 
my_consume_buffer(wrap_vector_as_istream(buffer)); 

然後,您可以創建wrap_vector_as_istream這樣的(雖然未經測試):

#include <iostream> 
#include <istream> 
#include <streambuf> 
#include <string> 

struct wrap_vector_as_istream : std::streambuf 
{ 
    wrap_vector_as_istream(std::vector<char> & vec) { 
     this->setg(&vec[0], &vec[0], &vec[0]+vec.size()); 
    } 
}; 

一件事但要注意。您創建的對象包含指向矢量內存的指針。因此,如果您在將此包裝浮動的同時向矢量添加或刪除值,那麼您就要崩潰了。

(哦,如果你投了我,請投了我從適應了這個帖子。)使用Boost

10

#include <boost/iostreams/stream.hpp> 
#include <boost/iostreams/device/array.hpp> 
using namespace boost::iostreams; 

basic_array_source<char> input_source(&my_vector[0], my_vector.size()); 
stream<basic_array_source<char> > input_stream(input_source); 

或更簡單:

#include <boost/interprocess/streams/bufferstream.hpp> 
using namespace boost::interprocess; 

bufferstream input_stream(&my_vector[0], my_vector.size()); 
0

如果您交換vector<char>可以,您可以使用Boost Interprocess' vectorstream。例如:

#include <boost/interprocess/streams/vectorstream.hpp> 

#include <vector> 
#include <string> 
#include <iostream> 


using namespace std; 

int main(int argc, char **argv) 
{ 
    static const char inp[] = "123 45 666"; 
    vector<char> v(inp, inp + sizeof inp - 1); 
    using ivectorstream = 
    boost::interprocess::basic_ivectorstream<std::vector<char>>; 
    ivectorstream is; 
    is.swap_vector(v); 
    while (!is.eof()) { 
    int i = 0; 
    is >> i; 
    cout << i << '\n'; 
    } 
    is.swap_vector(v); 
    cout << string(v.begin(), v.end()) << '\n'; 
    return 0; 
} 

或者,如果您不能或不想發生變異的vector<char>,您可以使用Boost Interprocess' bufferstream。使用bufferstream時,您不必將矢量切換到它。例如:

#include <boost/interprocess/streams/bufferstream.hpp> 

#include <vector> 
#include <string> 
#include <iostream> 


using namespace std; 

int main(int argc, char **argv) 
{ 
    static const char inp[] = "123 45 666"; 
    vector<char> v(inp, inp + sizeof inp - 1); 
    boost::interprocess::ibufferstream is(v.data(), v.size()); 
    while (!is.eof()) { 
    int i = 0; 
    is >> i; 
    cout << i << '\n'; 
    } 
    return 0; 
}