为什么此流缓冲区不起作用?

时间:2014-03-01 03:59:28

标签: c++

我有一个非常简单的流缓冲设置,可以将字节从流转发到缓冲区。当我打印时,我得到一个奇怪的输出,即"HellHelllo,"而不是"Hello"。也许我的眼睛很累,但我在这里找不到问题。为什么我得到输出?

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>

class io_buffer : public std::streambuf
{
public:
    io_buffer(std::istream& is, int buf_size = 4)
        : size(buf_size) , is_(is) , buffer(std::max(buf_size, 1))
    {
        char* end = &buffer.front() + buffer.size();
        setg(end, end, end);
    }

    int_type underflow()
    {
        if (gptr() < egptr())
            return traits_type::to_int_type(*gptr());

        if (is_)
        {
            std::copy_n(std::istreambuf_iterator<char>(is_),
                        size, std::back_inserter(buffer));

            char* beg = &buffer.front();
            setg(beg, beg, beg + buffer.size());
            return traits_type::to_int_type(*gptr());
        }
        return traits_type::eof();
    }
private:
    int size;
    std::istream& is_;
    std::vector<char> buffer;
};

int main()
{
    std::istringstream oss("Hello, World");
    io_buffer buf(oss);

    std::istream is(&buf);
    std::string str;

    is >> str;
    std::cout << str << std::endl; // "HellHelllo,"
}

2 个答案:

答案 0 :(得分:2)

使用(可能是4个)零初始化缓冲区

buffer(std::max(buf_size, 1))

并将内容附加到缓冲区而不清除缓冲区。

您可以将其更改为:

int_type underflow()
{
    if (gptr() < egptr())
        return traits_type::to_int_type(*gptr());

    if (is_)
    {
        char* beg = buffer.data();
        char* end = std::copy_n(
            std::istreambuf_iterator<char>(is_),
            size, beg);
        setg(beg, beg, end);
        return traits_type::to_int_type(*gptr());
    }
    return traits_type::eof();
}

你这里仍然有一个错误:std :: copy_n可能会要求太多的字符。

成功:

int_type underflow()
{
    if (gptr() < egptr())
        return traits_type::to_int_type(*gptr());

    if (is_)
    {
        char* beg = buffer.data();
        char* end = beg;
        char* limit = beg + buffer.size();
        std::istreambuf_iterator<char> in(is_);
        std::istreambuf_iterator<char> eos;
        for( ; end < limit && in != eos; ++end, ++in)
            *end = *in;
        setg(beg, beg, end);
        if(beg < end)
            return traits_type::to_int_type(*gptr());
    }
    return traits_type::eof();
}

消除会员人数。

答案 1 :(得分:1)

我认为这是因为underflow被调用了两次。

这可能是a bug