2016-08-17 4 views
0

Das Problem ist folgendes: Ich schreibe einen benutzerdefinierten gepufferten Eingabestream, der Strings in Chunks bestimmter Größe liest, die transformiert werden sollen (verschiedene Wege: geänderte Symbole, ganze Chunks übersprungen, wenn bestimmte Inhalte gefunden werden etc.) . Die Transformation selbst ist irrelevant, weil ich im Allgemeinen daran bin, Input zu verstehen. Hier ist der Code (auf der Basis von https://stackoverflow.com/a/14086442/3651664):Benutzerdefinierter gepufferter Eingabestream. Ende der Eingabe

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

Und die Frage ist: Warum muss ich ausdrücklich Eingabe beenden (durch EOF zum Beispiel das Senden)? Warum drücken Sie nicht genug? Oder mache ich das völlig falsch? Arbeiten in VS2010.


Update: ein anderes Problem mit diesem Code gefunden: wenn angegebene Zeichenanzahl nicht ein Vielfach von Puffergröße ist, wird underflow Methode nicht automatisch (nur einmal auf dem ersten) genannt. Warum das? Ist etw mit Zeigereinstellungen in setg falsch?

Antwort

1

Durch Drücken von Enter wird ein Zeichen an den E/A-Puffer gesendet. Das bedeutet nicht "Ende der Eingabe". In Ihrer Datei können Sie einfach so etwas wie

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

Der Standard-Stream Sie haben viel Flexibilität gibt, wie diese Eingabe zu lesen.

Zum Beispiel:

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" 

Sie können auch ihr Verhalten an Ihre Bedürfnisse anpassen. So können Sie so viel oder so wenig lesen, wie Sie möchten.

In Ihrem Code der Lesevorgang:

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

was bedeutet, „gib mir Zeichen oder weniger m_size wenn Ende der Eingabe aufgetreten“. Werfen Sie einen Blick auf die Dokumentation von streambuf für eine bessere Erklärung. http://www.cplusplus.com/reference/streambuf/streambuf

Std :: streambuf funktioniert auf Zeichenbasis. Keine getline() oder operator >> hier. Wenn Sie bei einem bestimmten Zeichen anhalten möchten (z. B.), benötigen Sie wahrscheinlich eine Schleife mit sgetc().

+0

Ok. Obwohl ich immer noch nicht verstehe, was los ist. Der Input-Stream, den ich verwende, stammt von istream, genau wie 'cin' zum Beispiel. Und 'cin' stoppt auf Newline. Was soll ich machen? – HighPredator

+1

'stoppt auf newline' ist in cin implementiert. Du solltest es selbst schreiben. – Sergei

+0

Verstanden, danke. – HighPredator

Verwandte Themen