122 Stimmen

Wie kann man einen ostringstream wiederverwenden?

Ich möchte einen ostringstream (und den zugrundeliegenden Puffer) löschen und wiederverwenden, damit meine App nicht so viele Zuweisungen vornehmen muss. Wie setze ich das Objekt auf seinen Ausgangszustand zurück?

0 Stimmen

165voto

Johannes Schaub - litb Punkte 479831

Ich habe in der Vergangenheit eine Abfolge von Clear und Str verwendet:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

Dies gilt sowohl für die Eingabe- als auch für die Ausgabe-Stringströme. Alternativ können Sie manuell löschen, dann suchen Sie die entsprechende Sequenz an den Anfang:

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

Dadurch werden einige Umwidmungen verhindert, die von str indem Sie stattdessen das überschreiben, was sich gerade im Ausgabepuffer befindet. Das Ergebnis sieht wie folgt aus:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

Wenn Sie die Zeichenkette für c-Funktionen verwenden wollen, können Sie std::ends und setzen eine abschließende Null wie folgt:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::ends ist ein Überbleibsel des veralteten std::strstream das direkt in ein Char-Array schreiben konnte, das Sie auf dem Stack zugewiesen hatten. Sie mussten manuell eine abschließende Null einfügen. Wie auch immer, std::ends ist nicht veraltet, ich denke, weil es immer noch nützlich ist, wie in den oben genannten Fällen.

0 Stimmen

Ich versuche, s.str() mit einem ostream zu verwenden. Die Größe ist es durcheinander (ich kann sehen, das erste Zeichen ist null, aber es druckt viel mehr). Gibt es einen guten Weg, um die str Länge zu beheben? ich bin mit s.str().c_str(); ATM und es funktioniert gut

0 Stimmen

Eigentlich ist nicht einmal das richtig. Ich habe gerade s.str(""); stattdessen. auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;

0 Stimmen

Std::ends funktioniert bei mir im Google-Test nicht boost::any a = 1; std::ostringstream buffer; buffer << a << std::ends; EXPECT_EQ( buffer.str(), "any<(int)1>" ); TestUtilsTest.cpp:27: Failure Expected: buffer.str() Which is: "any<(int)1>\0" To be equal to: "any<(int)1>" und bei der Wiederverwendung mit unterschiedlich langen Strings bleiben Reste übrig

6voto

Diego Sevilla Punkte 27639

Es scheint so zu sein, dass die ostr.str("") Aufforderung erfüllt den Zweck.

11 Stimmen

Es ist erwähnenswert, dass dabei der zugrunde liegende Puffer aus dem ostringstream nicht wiederverwendet wird - es wird lediglich ein neuer Puffer zugewiesen. Also, während Sie das ostringstream-Objekt wiederverwenden, sind Sie noch zwei Puffer zuweisen. Ich glaube nicht, dass ostringstream ist für die Wiederverwendung in der Art und Weise Sie beabsichtigen konzipiert.

2 Stimmen

Außerdem wird der Status nicht gelöscht, was mit .clear() geschieht. Ich stimme zu, es ist wirklich nicht dafür gedacht, auf diese Weise verwendet zu werden. Erstellen Sie einfach eine neue, um sicherzugehen. Nur wenn Sie ein Profil erstellen, werden Sie herausfinden, ob es einen Unterschied macht.

1 Stimmen

Sgreeve, Brian, das ist richtig. Beachten Sie jedoch, dass die obige Methode von litb die Verwendung von std::ends erfordert. Sie verwendet den Puffer wieder, zwingt Sie aber dazu, anders zu kodieren als sonst bei Stringstreams (normalerweise verwenden Sie std::ends nicht).

2voto

Unkle George Punkte 106

Wenn Sie gehen, um den Puffer in einer Weise zu löschen, die dazu führen, dass es vor der ersten Verwendung gelöscht werden, müssen Sie etwas in den Puffer zuerst mit MSVC hinzufügen.

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
    template<class T>
    inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

0 Stimmen

Ich sehe das fehlerhafte Verhalten nicht auf VS2012. Außerdem, Aufruf clear wird verursachen die failbit gesetzt werden, wenn der Stream leer ist. Während der bloße Aufruf von seekp sollte einfach zurückkehren, wenn kein Stream existiert.

-2voto

Sie haben keine. Verwenden Sie der Übersichtlichkeit halber zwei unterschiedlich benannte Streams und lassen Sie den optimierenden Compiler herausfinden, dass er den alten Stream wiederverwenden kann.

5 Stimmen

Betrachten Sie den Anwendungsfall, in dem der Code eine Schleife über Eingabedaten durchläuft, die in ein ostringstream (basierend auf den gelesenen Daten) und muss dann die in der ostringstream von Zeit zu Zeit (z.B. nachdem eine bestimmte Zeichenfolge gelesen wurde) und beginnen Sie mit dem Aufbau einer neuen Zeichenkette.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X