繁体   English   中英

自定义缓冲的输入流。 输入结束

[英]Custom buffered input stream. End of input

问题如下:我正在编写一个自定义的缓冲输入流,该流读取应转换大小的特定大小的块中的字符串(多种方式:更改的符号,如果找到特定内容则跳过整个块等)。 转换本身是无关紧要的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)? 为什么按Enter键不够? 还是我这样做是完全错误的? 在VS2010中工作。


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

按下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()进行循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM