2009-03-08 14 views
111

Vorrei eliminare e riutilizzare un ostringstream (e il buffer sottostante) in modo che la mia app non debba fare tante assegnazioni. Come faccio a ripristinare l'oggetto al suo stato iniziale?Come riutilizzare un ostringstream?

+0

possibile duplicato del [In C++, come si fa a cancellare una variabile stringstream?] (Http://stackoverflow.com/questions/20731/in-c-how-do-you-clear-a-stringstream -variabile) – mpromonet

risposta

145

Ho usato una sequenza di chiaro e str in passato:

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

che ha fatto la cosa giusta per entrambi stringstreams ingresso e di uscita. In alternativa, è possibile cancellare manualmente, poi cercare la sequenza appropriata per l'inizio:

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

che impedirà alcune riassegnazioni effettuate da str sovrascrivendo tutto ciò che è nel buffer di output attualmente invece. I risultati sono in questo modo:

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

Se si desidera utilizzare la stringa per C-funzioni, è possibile utilizzare std::ends, mettendo un nullo di terminazione come questo:

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 è un relitto del deprecato std::strstream, che è stato in grado di scrivere direttamente su un array di caratteri che è stato assegnato nello stack. Dovevi inserire un null che termina manualmente. Tuttavia, std::ends non è deprecato, penso perché è ancora utile come nei casi precedenti.

+0

Sto cercando di usare s.str() con un ostream. La dimensione è un pasticcio (posso vedere il primo carattere è nullo ma stampa molto di più). C'è un buon modo per risolvere la str str? sto usando s.str(). c_str(); ATM e funziona bene –

+0

In realtà anche questo non è corretto. Ho appena fatto 's.str (" ");' invece. 'auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); S.seekp (0); s << ends; ' –

+0

std :: ends non funziona per me nel google test ' boost :: any a = 1; std :: buffer di ostringstream; buffer << a << std :: ends; EXPECT_EQ (buffer.str(), "qualsiasi <(int)1>"); '' TestUtilsTest.cpp: 27: Guasto atteso: buffer.str() Quale è: "qualsiasi <(int)1> \ 0" essere pari a: "qualsiasi " e se riutilizzo con stringhe di lunghezza diversa, rimango sui bit –

5

Sembra che sia la chiamata ostr.str("") a fare il trucco.

+8

Vale la pena sottolineare che questo non riutilizzerà il buffer sottostante dal ostringstream - assegna solo un nuovo buffer. Quindi mentre riutilizzi l'oggetto ostringstream, stai ancora assegnando due buffer. Non penso che lo stringstream sia progettato per essere riutilizzato nel modo che tu intendi. – razlebe

+2

Inoltre non cancella lo stato, che è ciò che fa .clear(). Sono d'accordo, non è pensato per essere usato in questo modo. Basta crearne uno nuovo per essere sicuro. Solo se il tuo profilo scoprirai se fa alcuna differenza. –

+1

sgreeve, Brian, giusto. Si noti, tuttavia, come il metodo di litb sopra richiede l'uso di std :: ends. Riusa il buffer, ma rende il codice in modo diverso come al solito con gli stringstreams (normalmente non si usa std :: ends). –

0

Non è così. Usate due stream con nomi diversi per chiarezza e lasciate che il compilatore ottimizzante capisca che può riutilizzare quello vecchio.

+6

... e naturalmente spero che lo faccia, capirlo. –

+4

consideriamo il caso d'uso in cui il codice sta eseguendo il looping sui dati di input, scrivendo su un 'stringstream' (basato sulla lettura dei dati) e quindi deve scrivere la stringa incorporata nel' stringstream' di tanto in tanto (ad esempio dopo un certo la sequenza di caratteri è stata letta) e inizia a creare una nuova stringa. –

2

Se si desidera cancellare il buffer in un modo che causerà la cancellazione prima del primo utilizzo, sarà necessario aggiungere qualcosa al buffer 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 
    } 
}; 
+0

Non vedo il comportamento anomalo su VS2012. Inoltre, chiamando ['clear'] (http://www.cplusplus.com/reference/ios/ios/clear/) verrà _cause_ il' failbit' da impostare se lo stream è vuoto. Mentre solo chiamare ['seekp'] (http://www.cplusplus.com/reference/ostream/ostream/seekp/) dovrebbe semplicemente tornare se non esiste alcun flusso. –