redefinindo um stringstream


86

Como faço para "redefinir" o estado de um stringstream para o que era quando eu o criei?

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

Respostas:


134

É assim que costumo fazer:

ss.str("");
ss.clear(); // Clear state flags.

Obrigado; depurando o C ++ de outra pessoa e precisava disso para resolver um erro de violação de acesso que eles estavam recebendo por não usar o método .clear (). Funcionou bem em uma caixa Intel, mas vomitou todas as vezes em uma máquina AMD.
Chris Townsend,

3
Infelizmente clearnão reinicializa os manipuladores io. Exemplo de teste de falha: std :: stringstream ss; ss << "Olá" << std :: setw (15) << "Mundo" << std :: setw (15); reset (ss); ss << "Olá, Mundo"; assert ("Olá, Mundo" == buf.str ()); // falha, pega o último std :: setw
GameSalutes de

9

eu faria

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

Edit: corrigido o erro relatado por christianparpart e Nemo. Obrigado.

PS: O código acima cria um novo objeto stringstream na pilha e troca tudo sscom os do novo objeto.

Vantagens:

  1. Ele garante ssque agora estará em um novo estado.
  2. O novo objeto é criado embutido e na pilha, para que o compilador possa otimizar facilmente o código. No final, será como redefinir todos os ssdados internos para o estado inicial.

Mais:

  1. Comparado ao operador de atribuição: os métodos de troca STL podem ser mais rápidos do que o operador de atribuição nos casos em que o novo objeto tem um buffer alocado no heap. Em tal caso, o operador de atribuição tem que alocar o buffer para o novo objeto, então PODE precisar alocar outro buffer para o objeto antigo, e então copiar os dados do buffer do novo objeto para o novo buffer do objeto antigo. É muito fácil implementar uma troca rápida, que apenas troca os ponteiros dos buffers, por exemplo.

  2. C ++ 11. Eu vi alguma implementação do operador de atribuição de movimento que é mais lento do que a troca, embora isso possa ser corrigido, mas provavelmente o desenvolvedor de STL não vai querer deixar um objeto movido com muitos dados

  3. std::move()não garante que o objeto movido seja esvaziado. return std::move(m_container);não limpa m_container. Então você terá que fazer

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

Que não pode ser melhor do que

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

porque o último garante que não copiará buffers.

Então eu sempre prefiro swap()o tempo que couber.


2
Você deve explicar por que faria isso. Este código não é terrivelmente útil por si só.
Machavity

1
Embora essa resposta possa estar correta, adicione alguma explicação. Transmitir a lógica subjacente é mais importante do que apenas fornecer o código, porque ajuda o OP e outros leitores a corrigir esse e outros problemas por conta própria.
CodeMouse92

Gosto da solução. É muito curto e o mesmo modelo funciona para praticamente todos os tipos de dados std.
martinus de

1
Esta resposta não está totalmente correta, pois você não pode vincular a um temporário, ou seja, você cria uma variável temporária para trocar o fluxo de string vazio recém (temporariamente) criado pelo "ss" existente. Não permitido.
christianparpart

Isso não acarreta toda a sobrecarga de construção de uma localidade, que a redefinição do stringstream deve evitar?
tampas

2

Com base na resposta acima, também precisamos redefinir qualquer formatação. Ao todo, estamos redefinindo o conteúdo do buffer, os sinalizadores de estado do stream e qualquer formatação para seus padrões quando uma nova instância std :: stringstream é construída.

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

    stream.str(std::string());
    stream.clear();
    stream.copyfmt(initial);
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.