2009-03-08 8 views
111

Ich möchte einen ostringstream (und den zugrunde liegenden Puffer) löschen und wiederverwenden, damit meine App nicht so viele Zuordnungen vornehmen muss. Wie setze ich das Objekt in den Ausgangszustand zurück?Wie man einen ostringstream wiederverwendet?

+0

möglich Duplikat [In C++, wie Sie eine string Variable löschen?] (Http://stackoverflow.com/questions/20731/in-c-how-do-you-clear-a-stringstream -variable) – mpromonet

Antwort

145

Ich habe eine Reihe von klaren und str in der Vergangenheit verwendet:

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

, die die Sache für beide Eingangs- und Ausgangs stringstreams getan hat. Alternativ können Sie manuell löschen, suchen Sie dann 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 

, dass einige Umschichtungen von str durch Überschreiben getan wird verhindert, dass, was auch immer in dem Ausgangspuffer zur Zeit statt ist. Die Ergebnisse sind wie folgt:

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

Wenn Sie die Zeichenfolge für c-Funktionen nutzen möchten, können Sie std::ends verwenden, eine abschließende Null wie folgt setzen:

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 Relikt der veraltet std::strstream, das direkt in ein char-Array schreiben konnte, das Sie auf dem Stack zugewiesen hatten. Sie mussten einen abschließenden Null manuell einfügen. Allerdings ist std::ends nicht veraltet, ich denke, weil es immer noch nützlich ist, wie in den oben genannten Fällen.

+0

Ich versuche, s.str() mit einem Ostream zu verwenden. Die Größe ist verwirrend (ich kann sehen, das erste Zeichen ist Null, aber es druckt viel mehr). Gibt es eine gute Möglichkeit, die Str Länge zu beheben? Ich benutze s.str(). c_str(); ATM und es funktioniert gut –

+0

Eigentlich ist das sogar nicht korrekt. Ich habe einfach 's.str (" "); 'auto str = s.str(); auto cstr = str.c_str(); Datei << cstr; s.clear(); s.suchep (0); s << endet; ' –

+0

das std :: endet funktioniert nicht für mich in google test ' boost :: any = 1; Std :: ostringstream Puffer; Puffer << a << std :: endet; EXPECT_EQ (buffer.str(), "any <(int)1>"); '' TestUtilsTest.cpp: 27: Failure Erwartet: buffer.str() Welche ist: "any <(int)1> \ 0" zu sein gleich: "any <(int)1>" ' und wenn ich mit verschiedenen Länge Strings wiederbenutze ich über Bits übrig –

5

Scheint so zu sein, dass der ostr.str("") Anruf den Trick macht.

+8

Es sollte darauf hingewiesen werden, dass der zugrundeliegende Puffer aus dem ostringstream nicht wiederverwendet wird - er weist nur einen neuen Puffer zu. Während Sie also das ostringstream-Objekt erneut verwenden, weisen Sie immer noch zwei Puffer zu. Ich denke nicht, dass ostringstream für die Wiederverwendung in der Art und Weise, wie Sie beabsichtigen, entworfen wurde. – razlebe

+2

Es löscht auch nicht den Zustand, was .clear() tut. Ich stimme zu, es ist wirklich nicht so gemeint. Erstellen Sie einfach einen neuen, um sicher zu sein. Nur wenn du dich profilierst, wirst du herausfinden, ob es einen Unterschied macht. –

+1

sgreeve, Brian, das stimmt. Beachten Sie jedoch, wie die obige litb-Methode die Verwendung von std :: endet erfordert. Es verwendet den Puffer wieder, aber Sie lassen sich wie gewohnt mit Stringstreams programmieren (normalerweise verwenden Sie nicht std :: ends). –

0

Sie nicht. Verwenden Sie zur besseren Übersicht zwei unterschiedlich benannte Streams und lassen Sie den optimierenden Compiler herausfinden, dass er den alten wiederverwenden kann.

+6

... und natürlich hoffe ich, dass es funktioniert, finde es heraus. –

+4

betrachte den Anwendungsfall, bei dem der Code Eingabedaten überschleifen, in einen 'ostringstream' schreiben (basierend auf den gelesenen Daten) und dann von Zeit zu Zeit die in 'ostringstream' eingebaute Zeichenkette schreiben muß (zB nach einem bestimmten Zeichenfolge wurde gelesen) und beginnt mit dem Erstellen einer neuen Zeichenfolge. –

2

Wenn Sie den Puffer so löschen wollen, dass er vor der ersten Verwendung gelöscht wird, müssen Sie zuerst etwas zum Puffer 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

Ich sehe das fehlgeschlagene Verhalten auf VS2012 nicht. Darüber hinaus wird das Aufrufen von ['clear'] (http://www.cplusplus.com/reference/ios/ios/clear/) _cause_ das' failbit' gesetzt, wenn der Stream leer ist. Während Sie einfach ['seekp'] (http://www.cplusplus.com/reference/ostream/ostream/seekp/) aufrufen, sollten Sie einfach zurückkehren, wenn kein Stream existiert. –