restableciendo una secuencia de cadenas

86

¿Cómo "restablezco" el estado de un stringstream al que tenía cuando lo creé?

int firstValue = 1;
int secondValue = 2;

std::wstringstream ss;

ss << "Hello: " << firstValue;

std::wstring firstText(ss.str());

//print the value of firstText here


//How do I "reset" the stringstream here?
//I would like it behave as if I had created
// stringstream ss2 and used it below.


ss << "Bye: " << secondValue;

std::wstring secondText(ss.str());

//print the value of secondText here
usuario974967
fuente

Respuestas:

134

Esta es la forma en que suelo hacerlo:

ss.str("");
ss.clear(); // Clear state flags.
Darcy Rayner
fuente
Gracias; depurando el C ++ de otra persona y necesitaba esto para solucionar un error de infracción de acceso que recibían debido a que no usaban el método .clear (). Funcionó bien en una caja de Intel pero vomitó cada vez en una máquina AMD.
Chris Townsend
3
Desafortunadamente clear, no reinicia los manipuladores de io. Ejemplo de prueba fallida: std :: stringstream ss; ss << "Hola" << std :: setw (15) << "Mundo" << std :: setw (15); reiniciar (ss); ss << "Hola mundo"; asert ("Hola mundo" == buf.str ()); // falla, recoge el último estándar :: setw
GameSalutes
9

yo lo haría

std::wstringstream temp;
ss.swap(temp);

Editar: se corrigió el error informado por christianparpart y Nemo. Gracias.

PD: El código anterior crea un nuevo objeto stringstream en la pila e intercambia todo sscon los del nuevo objeto.

Ventajas:

  1. Garantiza ssque ahora estará en un estado nuevo.
  2. El nuevo objeto se crea en línea y en la pila, para que el compilador pueda optimizar fácilmente el código. Al final, será como restablecer todos sslos datos internos al estado inicial.

Más:

  1. En comparación con el operador de asignación: los métodos de intercambio de STL pueden ser más rápidos que el operador de asignación en los casos en que el nuevo objeto tiene un búfer asignado en el montón. En tal caso, el operador de asignación tiene que asignar el búfer para el nuevo objeto, luego PUEDE necesitar asignar otro búfer para el objeto antiguo y luego copiar los datos del búfer del nuevo objeto al búfer nuevo del objeto antiguo. Es muy fácil implementar un intercambio rápido, que simplemente intercambia punteros de los búferes, por ejemplo.

  2. C ++ 11. He visto alguna implementación del operador de asignación de movimiento que es más lento que el intercambio, aunque eso se puede arreglar, pero probablemente el desarrollador de STL no querrá dejar un objeto movido con muchos datos

  3. std::move()no garantiza que el objeto movido se vacíe. return std::move(m_container);no borra m_container. Entonces tendrás que hacer

    auto to_return (std :: move (m_container)); m_container.clear (); return to_return;

Que no puede ser mejor que

auto to_return;
m_container.swap(to_return);
return to_return;

porque este último garantiza que no copiará búferes.

Por eso siempre prefiero siempre que me swap()quede bien.

Yong
fuente
2
Deberías explicar por qué harías esto. Este código no es muy útil por sí solo.
Machavity
1
Si bien esta respuesta puede ser correcta, agregue alguna explicación. Impartir la lógica subyacente es más importante que solo dar el código, porque ayuda al OP y a otros lectores a solucionar este y otros problemas similares.
CodeMouse92
Me gusta la solucion Es muy corto y la misma plantilla funciona para prácticamente todos los tipos de datos estándar.
martinus
1
Esta respuesta no es del todo correcta ya que es posible que no se vincule a una variable temporal, es decir, cree una variable temporal para intercambiar la secuencia de cadena vacía recién creada (temporalmente) con la existente "ss". No permitido.
christianparpart
¿No implica esto toda la sobrecarga de construir una configuración regional, que se supone que debe evitar el restablecimiento del flujo de cadenas?
caps
2

Sobre la base de la respuesta anterior, también debemos restablecer cualquier formato. En general, estamos restableciendo el contenido del búfer, las banderas de estado de la secuencia y cualquier formato a sus valores predeterminados cuando se construye una nueva instancia de std :: stringstream.

void reset(std::strinstream& stream)
{
    const static std::stringstream initial;

    stream.str(std::string());
    stream.clear();
    stream.copyfmt(initial);
}
GameSalutes
fuente