我想用vector<char>
包裹std::istream
(因此,通过istream
界面读取向量)
这样做的方法是什么?
答案 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。