2016-08-17 71 views
0

问题是:我正在编写一个自定义缓冲输入流,以特定大小的应该转换的块形式读取字符串(各种方式:更改符号,如果找到特定内容则跳过整个块等) 。转换本身是无关紧要的,因为我一直在理解输入。下面是代码(从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中的指针设置有误吗?

回答

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()循环。

+0

好的。虽然我仍然没有得到什么错误。例如,我使用的输入流是从'istream'派生的,就像'cin'一样。 'cin'停在换行符上。我该怎么办? – HighPredator

+1

'在换行符上停止'在cin中实现。你应该自己写。 – Sergei

+0

了解,谢谢。 – HighPredator