C ++:使用istream </char>包装vector <char>

时间:2012-01-11 06:39:21

标签: c++

我想用vector<char>包裹std::istream(因此,通过istream界面读取向量)

这样做的方法是什么?

6 个答案:

答案 0 :(得分:30)

您定义了一个包含streambuf的{​​{1}}子类,并将其实例传递给istream构造函数。

如果构建后数据没有变化,使用vector设置数据指针就足够了;其他成员的默认实现做了正确的事情:

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); 方法。

答案 1 :(得分:14)

使用Boost:

#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());

答案 2 :(得分: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() );
    }
};

但有一点需要注意。您创建的对象包含指向向量内存的指针。因此,如果您在将此包装器浮动时向向量添加或移除值,那么您将面临崩溃。

(哦,如果你投票给我,请投票给我改编的帖子。)

答案 3 :(得分:2)

你可以简单地构建一个实现&gt;&gt;的类。像流一样的运算符,如下所示:

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并实现必要的功能。以下是一些值得一看的链接:

答案 4 :(得分: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;
}

答案 5 :(得分:-1)

您必须编写一个继承自istream的自定义流实现。这可以使用Boost.Iostreams轻松完成 - 您所要做的就是实现一个简单的Source