resetowanie stringstream

86

Jak „zresetować” stan stringstream do tego, jaki był, kiedy go utworzyłem?

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
źródło

Odpowiedzi:

134

Zwykle to robię:

ss.str("");
ss.clear(); // Clear state flags.
Darcy Rayner
źródło
Dzięki; debugowanie czyjegoś C ++ i potrzebowaliśmy tego do rozwiązania błędu naruszenia dostępu, który otrzymywali, ponieważ nie wykonali metody .clear (). Działał dobrze na pudełku z danymi, ale za każdym razem wymiotował na komputerze AMD.
Chris Townsend
3
Niestety clearnie resetuje manipulatorów io. Przykład testu zakończonego niepowodzeniem: std :: stringstream ss; ss << "Witaj" << std :: setw (15) << "Świat" << std :: setw (15); reset (ss); ss << "Witaj świecie"; assert ("Witaj świecie" == buf.str ()); // nie udaje się, odbiera ostatni std :: setw
GameSalutes,
9

chciałbym zrobić

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

Edycja: naprawiono błąd zgłoszony przez christianparpart i Nemo. Dzięki.

PS: Powyższy kod tworzy nowy obiekt stringstream na stosie i zamienia wszystko ssz obiektami w nowym obiekcie.

Zalety:

  1. Gwarantuje, że ssbędzie teraz w świeżo nowym stanie.
  2. Nowy obiekt jest tworzony w tekście i na stosie, dzięki czemu kompilator może łatwo zoptymalizować kod. Na koniec będzie to jak zresetowanie wszystkich ssdanych wewnętrznych do stanu początkowego.

Jeszcze:

  1. W porównaniu z operatorem przypisania: metody wymiany STL mogą być szybsze niż operator przypisania w przypadkach, gdy nowy obiekt ma przydzielony bufor w stercie. W takim przypadku operator przypisania musi przydzielić bufor dla nowego obiektu, wtedy MOŻE być zmuszony przeznaczyć inny bufor dla starego obiektu, a następnie skopiować dane z bufora nowego obiektu do nowego bufora starego obiektu. Bardzo łatwo jest zaimplementować szybką zamianę, która po prostu zamienia na przykład wskaźniki buforów.

  2. C ++ 11. Widziałem pewną implementację operatora przypisania przenoszenia, która jest wolniejsza niż swap, chociaż można to naprawić, ale prawdopodobnie programista STL nie będzie chciał zostawić przeniesionego obiektu z dużą ilością danych

  3. std::move()nie gwarantuje, że przeniesiony obiekt zostanie opróżniony. return std::move(m_container);nie czyści m_container. Więc będziesz musiał zrobić

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

Co nie może być lepsze niż

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

ponieważ ta ostatnia gwarantuje, że nie skopiuje buforów.

Więc zawsze wolę swap()tak długo, jak pasuje.

Yong
źródło
2
Powinieneś wyjaśnić, dlaczego to zrobiłeś. Ten kod sam w sobie nie jest zbyt przydatny.
Machavity
1
Chociaż ta odpowiedź może być poprawna, proszę dodać wyjaśnienie. Przekazanie podstawowej logiki jest ważniejsze niż samo podanie kodu, ponieważ pomaga OP i innym czytelnikom samodzielnie naprawić to i podobne problemy.
CodeMouse92
Podoba mi się rozwiązanie. Jest bardzo krótki i ten sam szablon działa dla praktycznie wszystkich standardowych typów danych.
martinus
1
Ta odpowiedź nie jest całkiem poprawna, ponieważ możesz nie wiązać się z tymczasową, to znaczy, tworzysz zmienną tymczasową, aby zamienić nowo utworzony (tymczasowo) pusty strumień ciągów na istniejący „ss”. Nie dozwolony.
christianparpart
Czy nie pociąga to za sobą całego narzutu związanego z konstruowaniem ustawień regionalnych, których resetowanie ciągu łańcuchów ma uniknąć?
czapki
2

Opierając się na powyższej odpowiedzi, musimy również zresetować wszelkie formatowanie. We wszystkim resetujemy zawartość bufora, flagi stanu strumienia i wszelkie formatowanie do wartości domyślnych, gdy konstruowana jest nowa instancja std :: stringstream.

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

    stream.str(std::string());
    stream.clear();
    stream.copyfmt(initial);
}
GameSalutes
źródło