Zurücksetzen eines Stringstreams

83

Wie "setze" ich den Status eines Stringstreams auf den Stand zurück, als ich ihn erstellt habe?

int firstValue = 1;
int secondValue = 2;

std::wstringstream ss;

ss << "Hello: " << firstValue;

std::wstring firstText(ss.str());

//print the value of firstText here


//How do I "reset" the stringstream here?
//I would like it behave as if I had created
// stringstream ss2 and used it below.


ss << "Bye: " << secondValue;

std::wstring secondText(ss.str());

//print the value of secondText here
user974967
quelle

Antworten:

134

So mache ich es normalerweise:

ss.str("");
ss.clear(); // Clear state flags.
Darcy Rayner
quelle
Vielen Dank; Debuggen von C ++ eines anderen und dies, um einen Zugriffsverletzungsfehler zu beheben, den er erhielt, weil er die .clear () -Methode nicht ausführte. Funktionierte gut auf einer Intel-Box, kotzte aber jedes Mal auf einer AMD-Maschine.
Chris Townsend
2
clearIo-Manipulatoren werden leider nicht zurückgesetzt. Beispiel für einen fehlgeschlagenen Test: std :: stringstream ss; ss << "Hallo" << std :: setw (15) << "Welt" << std :: setw (15); zurücksetzen (ss); ss << "Hallo Welt"; assert ("Hallo Welt" == buf.str ()); // schlägt fehl, nimmt letzte std :: setw
GameSalutes
8

Ich würde es tun

std::wstringstream temp;
ss.swap(temp);

Bearbeiten: Der von christianparpart und Nemo gemeldete Fehler wurde behoben. Vielen Dank.

PS: Der obige Code erstellt ein neues Stringstream-Objekt auf dem Stapel und tauscht alles ssmit denen im neuen Objekt aus.

Vorteile:

  1. Es wird garantiert, dass sses sich jetzt in einem neuen Zustand befindet.
  2. Das neue Objekt wird inline und auf dem Stapel erstellt, sodass der Compiler den Code problemlos optimieren kann. Am Ende wird es so sein, als würden alle ssinternen Daten in den Ausgangszustand zurückgesetzt.

Mehr:

  1. Im Vergleich zum Zuweisungsoperator: STL-Swap-Methoden können schneller sein als der Zuweisungsoperator, wenn das neue Objekt einen zugewiesenen Puffer im Heap hat. In einem solchen Fall muss der Zuweisungsoperator den Puffer für das neue Objekt zuweisen, dann muss er möglicherweise einen anderen Puffer für das alte Objekt zuweisen und dann die Daten aus dem Puffer des neuen Objekts in den neuen Puffer des alten Objekts kopieren. Es ist sehr einfach, einen schnellen Austausch zu implementieren, bei dem beispielsweise nur Zeiger der Puffer ausgetauscht werden.

  2. C ++ 11. Ich habe eine Implementierung des Verschiebungszuweisungsoperators gesehen, die langsamer als der Austausch ist, obwohl dies behoben werden kann, aber wahrscheinlich möchte der STL-Entwickler ein verschobenes Objekt nicht mit vielen Daten belassen

  3. std::move()garantiert nicht, dass das bewegte Objekt geleert wird. return std::move(m_container);löscht m_container nicht. Also musst du tun

    auto to_return (std :: move (m_container)); m_container.clear (); return to_return;

Welches kann nicht besser sein als

auto to_return;
m_container.swap(to_return);
return to_return;

weil letzteres garantiert, dass keine Puffer kopiert werden.

Also bevorzuge ich immer swap()solange es passt.

Yong
quelle
2
Sie sollten erklären, warum Sie dies tun würden. Dieser Code ist an sich nicht besonders nützlich.
Machavity
1
Obwohl diese Antwort richtig sein mag, fügen Sie bitte eine Erklärung hinzu. Die Vermittlung der zugrunde liegenden Logik ist wichtiger als nur die Angabe des Codes, da dies dem OP und anderen Lesern hilft, dieses und ähnliche Probleme selbst zu beheben.
CodeMouse92
Ich mag die Lösung. Es ist sehr kurz und dieselbe Vorlage funktioniert für praktisch alle Standarddatentypen.
Martinus
1
Diese Antwort ist nicht ganz richtig, da Sie möglicherweise nicht an eine temporäre Variable binden. Das heißt, Sie erstellen eine temporäre Variable, um den neu (vorübergehend) erstellten leeren String-Stream gegen den vorhandenen "ss" -Stream auszutauschen. Nicht erlaubt.
Christianparpart
Entsteht dadurch nicht der gesamte Aufwand für die Erstellung eines Gebietsschemas, der durch das Zurücksetzen des Stringstreams vermieden werden soll?
Kappen
2

Aufbauend auf der obigen Antwort müssen wir auch alle Formatierungen zurücksetzen. Insgesamt setzen wir den Pufferinhalt, die Stream-Statusflags und alle Formatierungen auf ihre Standardwerte zurück, wenn eine neue std :: stringstream-Instanz erstellt wird.

void reset(std::strinstream& stream)
{
    const static std::stringstream initial;

    stream.str(std::string());
    stream.clear();
    stream.copyfmt(initial);
}
GameSalutes
quelle