自定义输入流.流缓冲和底流法



为了理解输入流是如何工作的,我设计了以下2个类:

#include <iostream>
class my_streambuf: public std::streambuf
{
private:
  std::streambuf* buffer;
  char ch;
protected:
  virtual std::streambuf::int_type underflow()
  {
    std::streambuf::int_type result = buffer->sbumpc();
    if (result != traits_type::eof())
    {
      ch = traits_type::to_char_type(result);
      setg(&ch, &ch, &ch + 1);
    }
    return result;
  }
public:
  my_streambuf(std::streambuf* buffer) : buffer(buffer) {};
  virtual ~my_streambuf() {};
};
class my_istream: public std::istream
{
public:
  my_istream(std::istream& stream) : std::istream(new my_streambuf(stream.rdbuf())) {};
  virtual ~my_istream()
  {
    delete rdbuf();
  }
};
int main()
{
  char s[32];
  my_istream is(std::cin);
  is >> s;
  std::cout << s;
  return 0;
}

工作良好,直到我改变underflow方法的逻辑。主要目标是将数据保存在c字符串变量s中,这与用户输入不同。为了做一个简单的测试,我将underflow方法改为如下:

virtual std::streambuf::int_type underflow()
{
  std::streambuf::int_type result = buffer->sbumpc();
  if (result != traits_type::eof())
  {
    result = traits_type::to_int_type('+'); // <-- this was added
    ch = traits_type::to_char_type(result);
    setg(&ch, &ch, &ch + 1);
  }
  return result;
}

的想法是使方法只返回+符号,而不是用户输入的字符。例如,如果输入是123,我希望+++存储在变量s中。这是行不通的。控制台挂起,好像正在等待更多输入。只有一定数量的按键(或发送EOF)才有帮助。

我在这里错过了什么?


正如@ferosekhanj所指出的,问题是缺少换行符,underflow的修改版本没有将换行符返回给调用者。因此,为了使代码正常工作,它必须返回。这个版本的方法可以正常工作。

virtual std::streambuf::int_type underflow()
{
  std::streambuf::int_type result = buffer->sbumpc();
  if ((result != traits_type::eof()) && !traits_type::eq(traits_type::to_char_type(result), 'n'))
  {
     result = traits_type::to_int_type('+');
     ch = traits_type::to_char_type(result);
     setg(&ch, &ch, &ch + 1);
  }
  return result;
}

从我以前的c++经验来看,流buf是流的底层缓冲区。当流需要更多数据时,它调用下流。在此方法中,您应该从源代码中读取并设置。当流有数据要写回源时,它调用overflow。在这个方法中,从流中读取数据,写回源文件并设置。例如,如果您正在从streambuf

中的套接字读取数据
socketbuf::int_type socketbuf::underflow(){
  int bytesRead = 0;
  try{
    bytesRead = soc->read(inbuffer,BUFFER_SIZE-1,0);
    if( bytesRead <= 0 ){
      return traits_type::eof();
    }
  }catch(IOException ioe){
    cout<<"Unable to read data"<<endl;
    return traits_type::eof();
  }
  setg(inbuffer,inbuffer,inbuffer+bytesRead);
  return traits_type::to_int_type(inbuffer[0]);
}
socketbuf::int_type socketbuf::overflow(socketbuf::int_type c){
  int bytesWritten = 0;
  try{
    if(pptr() - pbase() > 0){
      bytesWritten = soc->write(pbase(),(pptr() - pbase()),0);
      if( bytesWritten <= 0 )  return traits_type::not_eof(c);
    }
  }catch(IOException ioe){
    cout<<"Unable to write data"<<endl;
    return traits_type::eof();
  }
  outbuffer[0] = traits_type::to_char_type(c);
  setp(outbuffer,outbuffer+1,outbuffer+BUFFER_SIZE);
  return traits_type::not_eof(c);
}
现在进入你的代码,你添加了
result = traits_type::to_int_type('+'); // <-- this was added

流读取一个字符串,直到它看到一个LF(换行)。因此,当LF字符出现时,您将用'+'覆盖它,因此流将永远等待(LF)。通过添加此检查,您的代码应该能够执行您所期望的操作。输入'abc'输出'+++'

if (result != 10)// <-- add this in addition
    result = traits_type::to_int_type('+'); // <-- this was added

希望对你有帮助。

相关内容

  • 没有找到相关文章

最新更新