Jak wyczyścić zmienną typu stringstream?

486

Próbowałem już kilku rzeczy,

std::stringstream m;
m.empty();
m.clear();

oba nie działają.

CodingWithoutComments
źródło

Odpowiedzi:

771

Dla wszystkich standardowych typów bibliotek funkcja członka empty()jest zapytaniem, a nie poleceniem, tzn. Oznacza „czy jesteś pusty?” nie „wyrzuć swoją zawartość”.

Funkcja clear()członka jest dziedziczona iosi używana do kasowania stanu błędu strumienia, np. Jeśli w strumieniu pliku ustawiono stan błędu na eofbit(koniec pliku), wówczas wywołanie clear()spowoduje przywrócenie stanu błędu do goodbit(brak błędu) .

Aby wyczyścić zawartość a stringstream, używając:

m.str("");

jest poprawne, chociaż używa:

m.str(std::string());

jest technicznie bardziej wydajny, ponieważ unikasz wywoływania std::stringkonstruktora const char*. Ale każdy kompilator w dzisiejszych czasach powinien być w stanie wygenerować ten sam kod w obu przypadkach - więc wybrałbym coś, co jest bardziej czytelne.

Wilka
źródło
105
Oto, co dzieje się, gdy zapomnisz część „clear ()”. stackoverflow.com/q/2848087/635549
galath
8
@KshitijBanerjee Myślę, że w C ++ m.str () i m.str ("") to dwie różne funkcje. m.str () wywołuje funkcję, która nie oczekiwała żadnego parametru, podczas gdy m.str ("") wywołuje funkcję, która akceptuje parametr const char *. m.str () mógł zostać zaimplementowany jako funkcja get, która zwraca ciąg znaków, podczas gdy m.str ("") mógł zostać zaimplementowany jako funkcja set .
Dinesh PR
4
Jak powiedział galath, bardzo ważne jest również dodanie m.clear (); oprócz m.str („”) ;. W przeciwnym razie możesz mieć problemy, jeśli w pewnym momencie wypełnisz ciąg znaków pustym ciągiem.
Sputnik,
1
@anthropod Tak, to było w zeszłym roku. Od tamtej pory działam.
James
1
Och, chłopiec jest taki intuicyjny. Podobnie jak wszystko inne w C ++!
słoneczny księżyc
47

Możesz usunąć stan błędu i opróżnić ciąg znaków wszystkie w jednym wierszu

std::stringstream().swap(m); // swap m with a default constructed stringstream

To skutecznie resetuje m do domyślnego stanu skonstruowanego

Nikos Athanasiou
źródło
3
Jest to najbardziej wydajny i najbardziej elegancki sposób na zrobienie tego w porównaniu do wszystkich innych odpowiedzi tutaj. Jednak std :: stringstream :: swap jest funkcją c ++ 11 i to rozwiązanie nie działa w przypadku poprzednich kompilatorów c ++ 11.
101010
4
Funkcji wciąż brakuje w GNU g ++ v4.8, patrz stackoverflow.com/questions/24429441/...
Joachim W
7
@ 101010: W jaki sposób wymiana jest lepsza niż przypisanie do ruchu?
Deduplicator,
2
@AsetD: Nawet jeśli nie jest to wyjątek, czy zapomniałeś domyślnie skonstruowanego tymczasowego?
Deduplicator
3
Jest to mało skuteczne. Kiedy chcę ponownie użyć oryginalnego ss. Dla mnie zamienia puste.
Zhang
36
m.str("");

wydaje się działać.

CodingWithoutComments
źródło
3
Zostałoby to usunięte przez .clear (), który jest określony w OP.
Dave Lugg
33

Powinien to być najbardziej niezawodny sposób niezależnie od kompilatora:

m=std::stringstream();
jerron
źródło
2
Moim zdaniem jest to lepsze, ponieważ m.str („”); spowodowało, że mój ciąg znaków blokował się z tą pustą wartością, niezależnie od tego, co próbowałem. Ale używając tego nie mam tego problemu
gelatine1
3
Wpadłem na ten sam problem, ponieważ mm.clear(); mm.str("");załatwiłem sprawę. (bez C ++ 11, w przeciwnym razie lepiej byłoby swap).
hochl
1
@hochl: Dlaczego byłoby swaplepsze niż przypisanie do ruchu?
Deduplicator,
4
To nie jest dobre na każdą sytuację. Spowodowałoby to ponowne przydzielenie bufora za każdym razem, podczas gdy mm.str („”) nie.
Shital Shah
3
Moim podstawowym przypadkiem użycia do opróżnienia obiektu łańcucha znaków jest utrzymywanie wokół niego obiektu łańcucha znaków w wierszu, aby zapobiec niepotrzebnej instancji łańcucha znaków - tworzenie nowego obiektu łańcucha znaków kopiuje globalny obiekt ustawień regionalnych - teoretycznie jest to szybkie i wymaga jedynie inkrementacji atomowej, ale na poziomie współbieżności mam do czynienia z często paraliżującymi.
Spacemoose,
12

Zawsze szukam:

{
    std::stringstream ss;
    ss << "what";
}

{
    std::stringstream ss;
    ss << "the";
}

{
    std::stringstream ss;
    ss << "heck";
}
TimoK
źródło
Czy to jest lepsze niż wyczyszczeniestringstream?
Robur_131
11

moje 2 centy:

wydawało mi się, że działa to dla mnie w xcode i dev-c ++, miałem program w formie menu, który jeśli zostanie wykonany iteracyjnie zgodnie z żądaniem użytkownika, wypełni zmienną typu stringstream, która zadziała ok za pierwszym razem uruchom, ale nie wyczyści strumienia znaków następnym razem, gdy użytkownik uruchomi ten sam kod. ale dwa wiersze kodu poniżej ostatecznie wyczyściły zmienną stringstream za każdym razem przed wypełnieniem zmiennej string. (2 godziny prób i błędów oraz wyszukiwań w Google), przy okazji, użycie każdej linii osobno nie załatwi sprawy.

//clear the stringstream variable

sstm.str("");
sstm.clear();

//fill up the streamstream variable
sstm << "crap" << "morecrap";
Francisco Cortes
źródło
-1

To problem koncepcyjny.

Strumień ciągu jest strumieniem, więc jego iteratory są przesyłane do przodu i nie mogą zwrócić. W wyjściowym łańcuchu znaków potrzebujesz flush (), aby zainicjalizować go, jak w każdym innym strumieniu wyjściowym.

Alcino Dall Igna Junior
źródło
1
en.cppreference.com/w/cpp/io/basic_ostream/flush flush synchronizuje się z urządzeniem pamięci, z którym jest powiązane. To nie jest ta sama inicjalizacja.
Jaśniejsze
-11

Nie odrzucają one danych ze strumienia w gnu c ++

    m.str("");
    m.str() = "";
    m.str(std::string());

Poniższe polecenie opróżnia dla mnie ciąg znaków:

    m.str().clear();
Jan
źródło
7
Nie jestem pewien, czy to zadziała, z tych samych powodów, dla których Bernhardrusch nie zadziałał. Funkcja .str () zwraca kopię, a jej wyczyszczenie nic by nie zrobiło.
Verdagon
1
To rozwiązanie NIE działa dla Microsoft Visual C ++.
Zak
Błędny. Clear działałby na łańcuchu zwróconym ze strumienia, a nie na samym strumieniu.
Joey Carson