【问题标题】:Custom buffered input stream. End of input自定义缓冲输入流。输入结束
【发布时间】:2016-12-23 20:39:31
【问题描述】:

问题如下:我正在编写一个自定义缓冲输入流,它以应转换的特定大小的块读取字符串(各种方式:更改符号,如果找到特定内容则跳过整个块等)。转换本身与 atm 无关,因为我通常坚持理解输入。下面是代码(来自https://stackoverflow.com/a/14086442/3651664):

#include <fstream>
#include <iostream>
#include <cstring>

class skipchar_stream_buffer: public std::streambuf
{
private:
  char* m_buffer;
  std::streambuf* m_stream_buffer;
  std::streamsize m_size;
public:
  skipchar_stream_buffer(std::streambuf* stream_buffer);
  virtual ~skipchar_stream_buffer();
  virtual std::streambuf::int_type underflow();
};

skipchar_stream_buffer::skipchar_stream_buffer(std::streambuf* stream_buffer)
{
  m_size = 10;
  m_buffer = new char[m_size]();
  m_stream_buffer = stream_buffer;
}

skipchar_stream_buffer::~skipchar_stream_buffer()
{
  delete[] m_buffer;
}

std::streambuf::int_type skipchar_stream_buffer::underflow()
{
  std::memset(m_buffer, 0, m_size);

  std::streamsize read = m_stream_buffer->sgetn(m_buffer, m_size);

  setg(m_buffer, m_buffer, m_buffer + m_size);

  std::cout << "buffer = '" << m_buffer << "'" << std::endl;

  if (gptr() == egptr())
    return traits_type::eof();
  else
    return traits_type::to_int_type(*gptr());
}

class skipchar_istream: public std::istream
{
public:
  skipchar_istream(std::istream& stream);
  virtual ~skipchar_istream();
};

skipchar_istream::skipchar_istream(std::istream& stream) :
  std::istream(new skipchar_stream_buffer(stream.rdbuf()))
{

}

skipchar_istream::~skipchar_istream()
{
  delete rdbuf();
}

int main()
{
  char s[32];

  skipchar_istream in(std::cin);
  in >> s;
  std::cout << s;

  return 0;
}

问题是:为什么我需要明确地完成输入(例如通过发送 EOF)?为什么按回车还不够?还是我这样做完全错了?在 VS2010 中工作。


更新: 发现此代码的另一个问题:如果提供的字符数不是缓冲区大小的倍数,则不会自动调用 underflow 方法(一开始只调用一次)。这是为什么? setg中的指针设置有问题吗?

【问题讨论】:

    标签: c++ input inputstream iostream istream


    【解决方案1】:

    按 Enter 将字符发送到 i/o 缓冲区。这并不意味着“输入结束”。 在您的文件中,您可以轻松地拥有类似

    Dear Mr. Smith,<CR><EOL>I am writing to you this message.<CR><EOL>Kind regards,<CR><EOL>Your Name<EOF>
    

    标准流在如何读取此输入方面为您提供了很大的灵活性。

    例如:

    istream get() will return you 'D'
    istream operator >> will return "Dear"
    istream getline () will return "Dear Mr. Smith,"
    streambuf sgetn (6) will return "Dear M"
    

    您还可以根据自己的需要调整他们的行为。因此,您可以随心所欲地阅读。

    在您的代码中,读取操作是:

    std::streamsize read = m_stream_buffer->sgetn(m_buffer, m_size);
    

    这意味着“如果发生输入结束,给我 m_size 个字符或更少”。 查看 streambuf 的文档以获得更好的解释。 http://www.cplusplus.com/reference/streambuf/streambuf

    std::streambuf 在每个字符的基础上工作。这里没有 getline() 或 operator>>。 如果你想停在一个特定的字符(例如 ),你可能需要一个带有 sgetc() 的循环。

    【讨论】:

    • 好的。虽然我还是不明白怎么回事。我使用的输入流来自istream,就像cin 一样。而cin 在换行处停止。我该怎么办?
    • 'stops on newline' 在 cin 中实现。你应该自己写..
    猜你喜欢
    • 2016-12-25
    • 2014-01-06
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    相关资源
    最近更新 更多