自定义缓冲输入流。输入结束
Custom buffered input stream. End of input
问题如下:我正在编写一个自定义缓冲输入流,它读取应转换的特定大小块中的字符串(各种方式:更改符号,如果找到特定内容则跳过整个块等) .转换本身与 atm 无关,因为我一般都坚持理解输入。这是代码(基于 ):
#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
中的指针设置有问题吗?
按 Enter 将字符发送到 i/o 缓冲区。这并不意味着 'end of input'。
在您的文件中,您可以轻松拥有类似
的内容
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);
这意味着 "give me m_size characters or less if end of input occurred"。
查看 streambuf 的文档以获得更好的解释。
http://www.cplusplus.com/reference/streambuf/streambuf
std::streambuf 按字符工作。这里没有 getline() 或 operator>>。
如果您想在特定字符处停止(例如 ),您可能需要使用 sgetc() 进行循环。
问题如下:我正在编写一个自定义缓冲输入流,它读取应转换的特定大小块中的字符串(各种方式:更改符号,如果找到特定内容则跳过整个块等) .转换本身与 atm 无关,因为我一般都坚持理解输入。这是代码(基于 ):
#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
中的指针设置有问题吗?
按 Enter 将字符发送到 i/o 缓冲区。这并不意味着 'end of input'。 在您的文件中,您可以轻松拥有类似
的内容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);
这意味着 "give me m_size characters or less if end of input occurred"。 查看 streambuf 的文档以获得更好的解释。 http://www.cplusplus.com/reference/streambuf/streambuf
std::streambuf 按字符工作。这里没有 getline() 或 operator>>。 如果您想在特定字符处停止(例如 ),您可能需要使用 sgetc() 进行循环。