Jak ponownie wykorzystać ostringstream?


Odpowiedzi:


156

W przeszłości użyłem sekwencji clear i str:

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

Co zrobiło to samo dla strumieni tekstowych wejściowych i wyjściowych. Alternatywnie możesz ręcznie wyczyścić, a następnie odszukać odpowiednią sekwencję do początku:

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

Zapobiegnie to niektórym realokacjom dokonanym przez strnadpisanie tego, co jest obecnie w buforze wyjściowym. Wyniki są takie:

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

Jeśli chcesz użyć łańcucha dla funkcji c, możesz użyć std::ends, wstawiając kończący null w następujący sposób:

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

std::endsjest reliktem przestarzałego std::strstream, który był w stanie pisać bezpośrednio do tablicy znaków, którą przydzieliłeś na stosie. Trzeba było ręcznie wstawić kończącą wartość null. Jednak std::endsmyślę, że nie jest przestarzały, ponieważ nadal jest przydatny, jak w powyższych przypadkach.


Próbuję użyć s.str () z ostreamem. Rozmiar go psuje (widzę, że pierwszy znak jest pusty, ale drukuje znacznie więcej). Czy istnieje dobry sposób na ustalenie długości str? używam s.str (). c_str (); Bankomat i działa ładnie

Właściwie nawet to nie jest poprawne. Po prostu to zrobiłem s.str("");. auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;

std :: end nie działa dla mnie w teście google 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>" i jeśli ponownie używam ze strunami o innej długości,
zostaję

Alternatywa to prawdziwa odpowiedź, jeśli chcesz uniknąć ponownej alokacji. A jeśli chcesz naprawdę "zacząć od nowa" bez realokacji, po prostu ponownie wywołaj funkcję seekp (0) po wysłaniu std :: end. s.seekp(0); s << std::ends; s.seekp(0);
Chip Grandits,

5

Wydaje się, że ostr.str("")telefon załatwia sprawę.


9
Warto zauważyć, że nie spowoduje to ponownego wykorzystania podstawowego bufora ze strumienia ostringstream - po prostu przypisuje nowy bufor. Więc kiedy ponownie używasz obiektu ostringstream, nadal przydzielasz dwa bufory. Nie sądzę, by ostringstream był przeznaczony do ponownego wykorzystania w zamierzony sposób.
razlebe

2
Nie usuwa również stanu, co robi .clear (). Zgadzam się, to naprawdę nie jest przeznaczone do tego. Po prostu utwórz nowy, aby mieć pewność. Tylko jeśli utworzysz profil, dowiesz się, czy ma to jakiekolwiek znaczenie.
Brian Neal

1
sgreeve, Brian, zgadza się. Zwróć jednak uwagę, jak powyższa metoda litb wymaga użycia std :: end. Ponownie wykorzystuje bufor, ale sprawia, że ​​kodowanie jest inne jak zwykle za pomocą stringstreams (zwykle nie używasz std :: end).
Diego Sevilla

2

Jeśli zamierzasz wyczyścić bufor w sposób, który spowoduje wyczyszczenie go przed pierwszym użyciem, musisz najpierw dodać coś do bufora w / MSVC.

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
    }
};

Nie widzę niepowodzenia w VS2012. Ponadto, nazywając clearbędzie powodować ten failbitzestaw, aby być, jeśli strumień jest pusty. Podczas gdy samo wywołanie seekppowinno po prostu powrócić, jeśli nie ma strumienia.
Jonathan Mee

0

Ty nie. Użyj dwóch strumieni o różnych nazwach dla zachowania przejrzystości i pozwól optymalizującemu kompilatorowi dowiedzieć się, że może ponownie użyć starego.


4
rozważ przypadek użycia, w którym kod zapętla dane wejściowe, zapisuje do ostringstream(na podstawie odczytanych danych), a następnie musi ostringstreamod czasu do czasu napisać ciąg zbudowany w którymś miejscu (np. po odczytaniu określonej sekwencji znaków) i rozpocząć budowanie nowego ciągu.
Andre Holzner
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.