2014-03-01 104 views
1

我有一个非常简单的流缓冲区设置,将流中的字节转发到缓冲区。当我打印时,我得到一个奇怪的输出,即"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

你有(也许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(); 
} 

你还有一个错误的位置:性病:: 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

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

这可能是a bug

+0

缓冲区大小是一个默认参数。而且我很小心确保它变得很小,以便他可以测试'underflow()'。 – 0x499602D2

+0

是的,但设置为“4”,需要更大的数字。 –

+0

他有意将它设置为4,以便他可以测试'underflow()'。 – 0x499602D2