¿Cómo reutilizar un avestruz?

Respuestas:

156

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

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

Lo que ha hecho lo mismo para los flujos de cadenas de entrada y salida. Alternativamente, puede borrar manualmente y luego buscar la secuencia apropiada para comenzar:

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

Eso evitará que se realicen algunas reasignaciones stral sobrescribir lo que esté en el búfer de salida actualmente. Los resultados son así:

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

Si desea usar la cadena para funciones c, puede usar std::ends, poniendo un nulo de terminación como este:

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

std::endses una reliquia de lo obsoleto std::strstream, que pudo escribir directamente en una matriz de caracteres que asignó en la pila. Debía insertar un nulo de terminación manualmente. Sin embargo, std::endsno está en desuso, creo que porque sigue siendo útil como en los casos anteriores.

Johannes Schaub - litb
fuente
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). ¿Existe una buena forma de arreglar la longitud de str? estoy usando s.str (). c_str (); Cajero automático y funciona bien
De hecho, ni siquiera esto es correcto. Solo lo hice en su s.str("");lugar. auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;
std :: ends no funciona para mí en la prueba de 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>" y si reutilizo con cadenas de diferente longitud, me quedan bits
David van Laatum
La alternativa es la verdadera respuesta si desea evitar la reasignación. Y si realmente desea "comenzar de nuevo" sin reasignación, simplemente llame a seekp (0) nuevamente después de enviar std :: end. s.seekp(0); s << std::ends; s.seekp(0);
Chip Grandits
5

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

Diego Sevilla
fuente
9
Vale la pena señalar que esto no reutilizará el búfer subyacente de ostringstream, solo asigna un nuevo búfer. Entonces, mientras reutiliza el objeto ostringstream, todavía está asignando dos búferes. No creo que ostringstream esté diseñado para ser reutilizado de la manera que pretendes.
razlebe
2
Tampoco aclara el estado, que es lo que hace .clear (). Estoy de acuerdo, realmente no está destinado a usarse así. Simplemente cree uno nuevo para estar seguro. Solo si tu perfil descubrirás si hay alguna diferencia.
Brian Neal
1
sgreeve, Brian, eso es correcto. Sin embargo, tenga en cuenta cómo el método de litb anterior requiere el uso de std :: ends. Reutiliza el búfer, pero hace que codifique de manera diferente como de costumbre con cadenas de cadenas (normalmente no usa std :: ends).
Diego Sevilla
2

Si va a borrar el búfer de una manera que hará que se borre antes de su primer uso, primero deberá agregar algo al búfer 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
    }
};
Unkle George
fuente
No veo el comportamiento fallido en VS2012. Por otra parte, llamando clearva causar el failbitconjunto que ser si la corriente está vacía. Mientras que la llamada seekpdebería simplemente regresar si no existe ninguna transmisión.
Jonathan Mee
0

Tu no Use dos flujos con nombres diferentes para mayor claridad y deje que el compilador de optimización se dé cuenta de que puede reutilizar el anterior.

Sebastián Ganslandt
fuente
4
considere el caso de uso en el que el código se repite sobre los datos de entrada, escribe en un ostringstream(según los datos leídos) y luego tiene que escribir la cadena incorporada en ostringstreamalgún lugar de vez en cuando (por ejemplo, después de leer una determinada secuencia de caracteres) y comenzar construyendo una nueva cuerda.
Andre Holzner