2016-08-18 1 views
3

Um zu verstehen, wie Eingangsströme arbeiten ich entworfen 2 der folgenden Klassen:Benutzerdefinierter Eingabestream. Strompuffer und Unterlauf Methode

#include <iostream> 

class my_streambuf: public std::streambuf 
{ 
private: 
    std::streambuf* buffer; 

    char ch; 

protected: 

    virtual std::streambuf::int_type underflow() 
    { 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if (result != traits_type::eof()) 
    { 
     ch = traits_type::to_char_type(result); 

     setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
    } 

public: 
    my_streambuf(std::streambuf* buffer) : buffer(buffer) {}; 

    virtual ~my_streambuf() {}; 
}; 

class my_istream: public std::istream 
{ 
public: 
    my_istream(std::istream& stream) : std::istream(new my_streambuf(stream.rdbuf())) {}; 

    virtual ~my_istream() 
    { 
    delete rdbuf(); 
    } 
}; 

int main() 
{ 
    char s[32]; 
    my_istream is(std::cin); 

    is >> s; 
    std::cout << s; 
    return 0; 
} 

Welche funktionieren, bis ich die Logik der underflow Methode ändern. Das Hauptziel ist das Speichern von Daten in der C-String-Version s, die sich von der Benutzereingabe unterscheidet. Um einen einfachen Test zu machen, änderte ich die underflow Methode, die folgenden sein:

virtual std::streambuf::int_type underflow() 
{ 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if (result != traits_type::eof()) 
    { 
    result = traits_type::to_int_type('+'); // <-- this was added 

    ch = traits_type::to_char_type(result); 

    setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
} 

Mit der Idee, die Methode Rückkehr nur + Symbole anstelle von Benutzereingaben Zeichen zu machen ist. Wenn also zum Beispiel 123 eingegeben wird, erwarte ich, dass +++ in der Variablen s gespeichert wird. Und das funktioniert nicht. Die Konsole hängt, als ob sie auf weitere Eingaben wartet. Nur ein bestimmter Tastendruck (oder Senden von EOF) hilft.

Was fehlt mir hier?


Wie von @ferosekhanj weist darauf hin, das Problem war die fehlenden Newline, die nicht durch die modifizierte Version von underflow an den Aufrufer zurückgegeben wurde. Damit der Code ordnungsgemäß funktioniert, muss er zurückgegeben werden. Diese Version der Methode funktioniert gut.

virtual std::streambuf::int_type underflow() 
{ 
    std::streambuf::int_type result = buffer->sbumpc(); 

    if ((result != traits_type::eof()) && !traits_type::eq(traits_type::to_char_type(result), '\n')) 
    { 
    result = traits_type::to_int_type('+'); 

    ch = traits_type::to_char_type(result); 

    setg(&ch, &ch, &ch + 1); 
    } 

    return result; 
} 

Antwort

2

Von meiner alten C++ - Erfahrung ist ein Stream-Buf der zugrunde liegende Puffer für den Stream. Wenn der Stream mehr Daten benötigt, ruft er Unterlauf auf. Innerhalb dieser Methode sollen Sie von Ihrer Quelle lesen und festlegen. Wenn der Datenstrom Daten enthält, die zurück in die Quelle geschrieben werden sollen, ruft er einen Überlauf auf. Innerhalb dieser Methode lesen Sie aus dem Stream, schreiben Sie zurück zu Ihrer Quelle und setp. Zum Beispiel, wenn Sie die Daten aus einer Steckdose in Ihrem streambuf

socketbuf::int_type socketbuf::underflow(){ 
    int bytesRead = 0; 
    try{ 
    bytesRead = soc->read(inbuffer,BUFFER_SIZE-1,0); 
    if(bytesRead <= 0){ 
     return traits_type::eof(); 
    } 
    }catch(IOException ioe){ 
    cout<<"Unable to read data"<<endl; 
    return traits_type::eof(); 
    } 
    setg(inbuffer,inbuffer,inbuffer+bytesRead); 
    return traits_type::to_int_type(inbuffer[0]); 
} 

socketbuf::int_type socketbuf::overflow(socketbuf::int_type c){ 
    int bytesWritten = 0; 
    try{ 
    if(pptr() - pbase() > 0){ 
     bytesWritten = soc->write(pbase(),(pptr() - pbase()),0); 
     if(bytesWritten <= 0) return traits_type::not_eof(c); 
    } 
    }catch(IOException ioe){ 
    cout<<"Unable to write data"<<endl; 
    return traits_type::eof(); 
    } 
    outbuffer[0] = traits_type::to_char_type(c); 
    setp(outbuffer,outbuffer+1,outbuffer+BUFFER_SIZE); 
    return traits_type::not_eof(c); 
} 

Nun zu Ihrem Code lesen gerade kommen, Sie

result = traits_type::to_int_type('+'); // <-- this was added 

hinzugefügt Ein Strom einen String liest, bis er eine LF (Zeilenvorschub) sieht . Wenn also der LF-Charakter kommt, bist du damit fertig, das mit einem '+' zu schreiben, so dass der Stream für immer auf LF wartet. Wenn du diesen Check hinzufügst, sollte dein Code das tun, was du erwartest. gib '+++' aus, wenn du 'abc' eingibst

if (result != 10)// <-- add this in addition 
    result = traits_type::to_int_type('+'); // <-- this was added 

Hoffe es hilft dir.

+0

Wenn ich nicht viel falsch bin, liest nur 'cin' einen String, bis er einen Zeilenvorschub sieht. Andere Streams tun dies bis "EOF". – HighPredator

+0

Was meinst du mit anderen Streams? cin ist nur eine Instanz von std: istream – ferosekhanj

+0

Ich meine, dass dies nach meinem Wissen in 'cin implementiert ist, nicht die Stream-Klasse. – HighPredator

Verwandte Themen