104 votes

réinitialisation d'un flux de chaînes

Comment puis-je "réinitialiser" l'état d'un stringstream à ce qu'il était lorsque je l'ai créé ?

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

155voto

Darcy Rayner Points 1481

C'est ainsi que je procède habituellement :

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

1 votes

Merci ; je déboguais le C++ de quelqu'un d'autre et j'en avais besoin pour résoudre une erreur de violation d'accès qu'ils obtenaient parce qu'ils n'utilisaient pas la méthode .clear(). Cela a bien fonctionné sur une machine Intel mais a dégueulé à chaque fois sur une machine AMD.

4 votes

Malheureusement clear ne remet pas à zéro les io manipulateurs. Exemple de test échoué : std::stringstream ss ; ss << "Hello" << std::setw(15) << "World" << std::setw(15) ; reset(ss) ; ss << "Hello World" ; assert("Hello World" == buf.str()) ; // échoue, reprend le dernier std::setw.

15voto

Yong Points 305

Je ferais

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

Edit : corrigé l'erreur signalée par christianparpart et Nemo. Merci.

PS : Le code ci-dessus crée un nouvel objet stringstream sur la pile et échange tout dans ss avec ceux du nouvel objet.

Avantages :

  1. Il garantit ss sera maintenant dans un état frais et neuf.
  2. Le nouvel objet est créé en ligne et sur la pile, de sorte que le compilateur peut facilement optimiser le code. A la fin, ce sera comme réinitialiser tous les objets ss les données internes à l'état initial.

Plus :

  1. Par rapport à l'opérateur d'affectation : Les méthodes de swap STL peuvent être plus rapides que l'opérateur d'affectation dans les cas où le nouvel objet a un tampon alloué dans le tas. Dans ce cas, l'opérateur d'affectation doit allouer le tampon pour le nouvel objet, puis il PEUT avoir besoin d'allouer un autre tampon pour l'ancien objet, et enfin copier les données du tampon du nouvel objet vers le nouveau tampon de l'ancien objet. Il est très facile de mettre en œuvre un échange rapide, qui ne fait qu'échanger les pointeurs des tampons, par exemple.

  2. C++11. J'ai vu certaines implémentations de l'opérateur d'affectation move qui sont plus lentes que swap, bien que cela puisse être corrigé, mais probablement le développeur STL ne voudra pas laisser un objet déplacé avec beaucoup de données.

  3. std::move() ne garantit pas que l'objet déplacé soit vidé. return std::move(m_container); n'efface pas m_container. Vous devrez donc faire

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

Ce qui ne peut pas être mieux que

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

car ce dernier garantit qu'il ne copiera pas les tampons.

Je préfère donc toujours swap() tant qu'il est adapté.

6voto

GameSalutes Points 774

Dans le prolongement de la réponse ci-dessus, nous devons également réinitialiser tout formatage. En tout, nous réinitialisons le contenu du tampon, les drapeaux d'état du flux, et tout formatage à leurs valeurs par défaut lorsqu'une nouvelle instance de std::stringstream est construite.

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X