Frage

Ich versuche, einen Stream -Puffer zu implementieren, und ich habe Probleme damit, es zu machen overflow() Arbeit. Ich habe die Größe des Puffers um 10 weitere Zeichen verändert und den Puffer mithilfe mithilfe der Puffer zurücksetzt setp. Dann erhöhe ich den Zeiger zurück, wo wir aufgehört haben. Aus irgendeinem Grund ist die Ausgabe nicht richtig:

template <class charT, class traits = std::char_traits<charT>>
class stringbuf : public std::basic_stringbuf<charT, traits>
{
public:
    using char_type   = charT;
    using traits_type = traits;
    using int_type    = typename traits::int_type;
public:
    stringbuf()
        : buffer(10, 0)
    {
        this->setp(&buffer.front(), &buffer.back());
    }

    int_type overflow(int_type c = traits::eof())
    {
        if (traits::eq_int_type(c, traits::eof()))
            return traits::not_eof(c);

        std::ptrdiff_t diff = this->pptr() - this->pbase();

        buffer.resize(buffer.size() + 10);
        this->setp(&buffer.front(), &buffer.back());

        this->pbump(diff);

        return traits::not_eof(traits::to_int_type(*this->pptr()));
    }
    // ...
    std::basic_string<charT> str()
    {
        return buffer;
    }
private:
    std::basic_string<charT> buffer;
};

int main()
{
    stringbuf<char> buf;
    std::ostream os(&buf);

    os << "hello world how are you?";
    std::cout << buf.str();
}

Wenn ich die Zeichenfolge drucke, kommt es als:

Hallo Worl wie geht es dir?

Es fehlt die d und die y. Was habe ich falsch gemacht?

War es hilfreich?

Lösung

Das erste, was nicht, ist, dass Sie abgeleitet werden std::basic_stringbuf<char> Aus irgendeinem Grund, ohne alle relevanten virtuellen Funktionen zu überschreiben. Zum Beispiel überschreiben Sie nicht xsputn() oder sync(): Was auch immer diese Funktionen tun, werden Sie erben. Ich würde dringend empfehlen, Ihren Stream -Puffer abzuleiten std::basic_streambuf<char> stattdessen!

Das overflow() Methode kündigt einen Puffer an, der ein Zeichen ist, der kleiner als die Zeichenfolge zum Stream -Puffer ist: &buffer.back() Ist kein Zeiger auf das Ende des Arrays, sondern zum letzten Zeichen in der Zeichenfolge. Persönlich würde ich verwenden

this->setp(&this->buffer.front(), &this->buffer.front() + this->buffer.size());

Bisher gibt es kein Problem. Nachdem Sie jedoch Platz für weitere Zeichen geschafft haben, die Sie weggelassen haben, haben Sie den überfüllten Charakter hinzugefügt, dh das Argument, an das übergeben wurde overflow() zum Puffer:

this->pbump(diff);
*this->pptr() = traits::to_char_type(c);
this->pbump(1);

Es gibt noch ein paar kleine Dinge, die nicht ganz richtig sind:

  1. Es ist im Allgemeinen eine schlechte Idee, übergeordnet zu werden virtual Funktioniert einen Standardparameter. Die Basisklassenfunktion liefert bereits die Standardeinstellung und der neue Standard wird nur aufgegriffen, wenn die Funktion jemals explizit bezeichnet wird.
  2. Die zurückgegebene Zeichenfolge kann am Ende eine Reihe von Nullzeichen enthalten, da die gehaltene Zeichenfolge tatsächlich größer ist als die Sequenz, die bisher geschrieben wurde, es sei denn, der Puffer ist genau voll. Sie sollten wahrscheinlich die implementieren str() anders funktionieren:

    std::basic_string<charT> str() const
    {
        return this->buffer.substr(0, this->pptr() - this->pbase());
    }
    
  3. Das Wachstum der Zeichenfolge um einen konstanten Wert ist ein wichtiges Leistungsproblem: die Kosten des Schreibens n Charaktere ist n * n. Für größere n (Sie müssen nicht wirklich riesig werden) Dies wird zu Problemen führen. Sie sind viel besser dran, Ihre zu wachsen buffer exponentiell, zB, verdoppelt es jedes Mal oder wachsen um einen Faktor von 1.5 Wenn Sie das Gefühl haben, ist es keine gute Idee.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top