2009-03-08 10 views
111

Me gustaría borrar y reutilizar un ostringstream (y el buffer subyacente) para que mi aplicación no tenga que hacer tantas asignaciones. ¿Cómo reinicio el objeto a su estado inicial?¿Cómo reutilizar un ostringstream?

+0

posible duplicado del [En C++, ¿cómo se borra una variable stringstream?] (Http://stackoverflow.com/questions/20731/in-c-how-do-you-clear-a-stringstream -variable) – mpromonet

Respuesta

145

He usado una secuencia de claro y str en el pasado:

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

¿Qué ha hecho lo tanto stringstreams de entrada y salida. Alternativamente, se puede borrar manualmente, a continuación, busque la secuencia apropiada al comenzar:

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

que evitará que algunas reasignaciones realizadas por str sobreescribiendo lo que está en el búfer de salida actualmente en su lugar. Los resultados son como sigue:

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

Si desea utilizar la cadena de c-funciones, puede utilizar std::ends, poniendo un cero terminador de esta manera:

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 es un relicto de la obsoleta std::strstream, que fue capaz de escribir directamente en una matriz de caracteres que asignó en la pila. Debes insertar un nulo de terminación manualmente. Sin embargo, std::ends no está en desuso, creo que porque sigue siendo útil como en los casos anteriores.

+0

Estoy tratando de usar s.str() con un ostream. El tamaño lo está arruinando (puedo ver que el primer carácter es nulo pero imprime mucho más). ¿Hay una buena manera de arreglar la longitud de str? estoy usando s.str(). c_str(); ATM y funciona muy bien –

+0

En realidad, incluso esto no es correcto. Acabo de hacer 's.str (" ");' en su lugar. 'auto str = s.str(); auto cstr = str.c_str(); archivo << cstr; s.clear(); s.buscar (0); s << ends; ' –

+0

std :: ends no funciona en google test ' boost :: any a = 1; std :: buffer de ostringstream; buffer << a << std :: ends; EXPECT_EQ (buffer.str(), "cualquier <(int)1>"); '' TestUtilsTest.cpp: 27: Si no esperado: buffer.str() que es: "cualquier <(int)1> \ 0" que es igual a: "any <(int)1>" ' y si reutilizo con diferentes cadenas de longitud, me quedan los bits –

5

Parece ser que la llamada ostr.str("") hace el truco.

+8

Vale la pena señalar que esto no reutilizará el buffer subyacente del ostringstream - simplemente asigna un nuevo buffer. Entonces, mientras reutiliza el objeto ostringstream, todavía está asignando dos almacenamientos intermedios. No creo que ostringstream esté diseñado para su reutilización de la manera que usted pretende. – razlebe

+2

Tampoco borra el estado, que es lo que .clear() hace. Estoy de acuerdo, realmente no debe ser usado así. Solo crea uno nuevo para estar seguro. Solo si su perfil descubrirá si hace alguna diferencia. –

+1

sgreeve, Brian, eso es correcto. Tenga en cuenta, sin embargo, cómo el método anterior del litb requiere el uso de std :: ends. Reutiliza el búfer, pero te hace codificar de manera diferente con cadenas de caracteres (normalmente no usas std :: ends). –

0

No es así. Utilice dos secuencias con nombres diferentes para mayor claridad y deje que el compilador optimizador descubra que puede reutilizar el anterior.

+6

... y, por supuesto, espero que sí, averígualo que sí. –

+4

considere el caso de uso donde el código se repite sobre datos de entrada, escribiendo en un 'ostringstream' (basado en la lectura de datos) y luego tiene que escribir la cadena construida en el' ostringstream' en algún lugar de vez en cuando (por ejemplo, después de un cierto secuencia de caracteres fue leída) y comienza a construir una nueva cadena. –

2

Si va a borrar el búfer de forma que lo borre antes de usarlo por primera vez, deberá agregar algo al búfer primero con 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

No veo el comportamiento defectuoso en VS2012. Además, al llamar a ['clear'] (http://www.cplusplus.com/reference/ios/ios/clear/) se establecerá el' failbit' si la transmisión está vacía. Si solo llama a ['seekp'] (http://www.cplusplus.com/reference/ostream/ostream/seekp/), simplemente debe devolver si no existe una transmisión. –

Cuestiones relacionadas