自定义输入流。流缓冲和下溢方法 [英] Custom input stream. Stream buffer and underflow method

查看:133
本文介绍了自定义输入流。流缓冲和下溢方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

To understand how input streams work I designed 2 of the following classes:

#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;
}

哪个工作正常,直到我更改的逻辑下溢方法。主要目标是将数据保存在c-string valiable s 中,这与用户输入不同。为了进行简单的测试,我将下溢方法改为:

Which work fine, until I change the logic of underflow method. The primary goal is to save data in c-string valiable s which differs from user-input. To make a simple test, I changed the underflow method to be the following:

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 ,我希望 +++ 存储在变量<$中ç$ C>取值。
这不起作用。控制台挂起就像等待更多输入一样。只有一定数量的按键(或发送EOF)才有帮助。

With the idea being to make the method return only + symbols instead of user-input chars. So for example if input is 123, I expect +++ to be stored in variable s. And that does not work. Console hangs as if it is waiting more input. Only a certain amount of keypressing (or sending EOF) helps.

我在这里缺少什么?

正如@ferosekhanj所指出的,问题是缺少的换行符,修改后的 underflow 未被返回到呼叫者。因此,为了使代码正常工作,必须返回它。此版本的方法工作正常。

As was pointed out by @ferosekhanj, the problem was the missing newline, which was not returned by the modified version of underflow to the caller. So in order for the code to work properly it has to be returned. This version of the method works fine.

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 ++经验来看stream buf是流的底层缓冲区。当流需要更多数据时,它会调用下溢。在此方法中,您可以从源和setg中读取。当流有数据要写回源时,它会调用溢出。在此方法中,您从流中读取,写回源和setp。例如,如果您正在读取streambuf中套接字的数据

From my old C++ experience a stream buf is the underlying buffer for the stream. When the stream needs more data it calls underflow. Inside this method you are suppose to read from your source and setg. When the stream has data to be written back to the source it calls overflow. Inside this method you read from the stream,write back to your source and setp. For example if you are reading the data from a socket in your 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);
}

现在来到你的代码,你添加了

Now coming to your code, you added

result = traits_type::to_int_type('+'); // <-- this was added

一个流读取一个字符串,直到它看到一个LF(行饲料)。因此,当LF字符出现时,你会用'+'来编写,所以流将永远等待(对于LF)。通过添加此检查,您的代码应该按照您的预期进行操作。如果您输入'abc',则输出'+++'

A stream reads a string until it sees a LF(line feed). So when the LF character come you are over writing that with a '+' so the stream will wait (for LF) forever.By adding this check your code should do what you are expecting. output '+++' if you input 'abc'

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

希望它可以帮到你。

这篇关于自定义输入流。流缓冲和下溢方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆