Menu

Flux de chaînes en C++ : analyse et construction avec stringstream

Comment utiliser std::stringstream, istringstream et ostringstream pour analyser du texte, découper des chaînes selon les espaces, convertir entre chaînes et nombres, et construire des chaînes formatées en mémoire.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Un flux qui vit dans une chaîne

Vous connaissez déjà cin et cout - des flux reliés au clavier et à l'écran. Un flux de chaîne repose sur la même idée, sauf que les données vivent dans une std::string en mémoire. Vous y écrivez avec << et vous en extrayez des valeurs avec >>, exactement comme avec les flux de la console, mais rien ne touche le terminal.

Cette seule idée résout deux problèmes du quotidien : analyser du texte pour le décomposer en valeurs typées, et construire une chaîne formatée à partir de morceaux hétérogènes. Tout se trouve dans l'en-tête <sstream> et se décline en trois variantes :

  • istringstream - lecture seule, pour analyser une entrée.
  • ostringstream - écriture seule, pour construire une sortie.
  • stringstream - dans les deux sens.

ss.str() renvoie tout ce qui a été écrit jusqu'ici sous forme de simple string. Les opérateurs << ont effectué le même formatage int-vers-texte que cout - vous avez simplement capturé le résultat au lieu de l'afficher.

Analyse : extraire des valeurs typées

La vraie puissance apparaît avec >>. Donnez du texte à un flux et l'extraction convertit chaque jeton dans le type que vous demandez, en sautant les espaces qui les séparent. C'est la manière propre de découper une ligne en plusieurs champs typés :

Chaque >> lit jusqu'au prochain espace et convertit : "Ada" en une string, "36" en un int, "5.5" en un double. Remarquez le istringstream ici - le type en lecture seule indique clairement que vous ne faites qu'analyser.

Convertir des chaînes en nombres (en toute sécurité)

Une tâche fréquente consiste à transformer une seule chaîne comme "42" en un int. Un stringstream le fait et vous indique si le texte était réellement un nombre valide - ce que atoi ne fait jamais :

Ici ss >> value lit 123, s'arrête au a et réussit - validez donc toujours la chaîne entière si cela compte. Une vérification robuste consiste à lire le nombre puis à confirmer qu'il ne reste rien de significatif. Pour des conversions simples à valeur unique, std::stoi, std::stod et leurs équivalents (abordés avec la conversion de types) sont plus courts ; tournez-vous vers stringstream lorsqu'une chaîne porte plusieurs valeurs mélangées.

Découper une chaîne selon un délimiteur

Découper du texte est la tâche de flux de chaîne la plus recherchée sur Google. Combinez un flux avec std::getline, qui peut lire jusqu'à n'importe quel caractère délimiteur, pas seulement un saut de ligne :

Le motif while (getline(...)) boucle jusqu'à ce que le flux soit épuisé, car getline renvoie le flux et celui-ci s'évalue à false lorsqu'il ne reste plus rien. Supprimez le troisième argument et vous découpez plutôt selon les jetons séparés par des espaces avec >> - choisissez le délimiteur que vos données utilisent.

Construire des chaînes en mémoire

Dans l'autre sens, ostringstream assemble une chaîne formatée sans le risque de débordement de tampon de sprintf ni la fragile concaténation manuelle. C'est parfait pour des lignes de journal, des noms de fichiers ou des messages cousus à partir de nombres et de texte :

Tout le formatage <iomanip> que vous utiliseriez avec cout - setw, setfill, setprecision, hex - fonctionne de façon identique sur un flux de chaîne, vous obtenez donc une sortie complétée, à largeur fixe ou en hexadécimal capturée directement dans une string.

Le piège : réinitialiser avant de réutiliser

Le piège qui attrape tout le monde, c'est de réutiliser un flux sans le réinitialiser. Une fois qu'un flux atteint la fin de ses données, ses indicateurs eof et fail se verrouillent, et chaque >> ultérieur ne fait silencieusement rien - aucune erreur, juste des valeurs périmées :

stringstream ss("10");
int a, b;
ss >> a;            // a = 10, le flux est maintenant à la fin -> indicateur eof activé
ss.str("20");       // charge un nouveau texte...
ss >> b;            // ÉCHOUE SILENCIEUSEMENT - les indicateurs d'erreur sont toujours activés, b est inchangé

Vous devez effacer l'état d'erreur et le contenu. Le bon ordre est clear() d'abord, puis str() :

Deux erreurs apparentées : ss.clear() réinitialise les indicateurs mais ne vide pas le tampon (utilisez ss.str("") pour cela), et un stringstream auquel vous continuez d'ajouter avec << ne cesse de grossir - créez-en un neuf à l'intérieur d'une boucle plutôt que d'en réutiliser un sale à chaque itération.

Suivant : les tableaux

Les flux de chaînes vous ont donné un moyen propre de transformer du texte en valeurs typées et inversement - souvent toute une liste d'entre elles, comme le vector que vous avez rempli en découpant un CSV. Pour stocker et indexer des collections fixes de ces valeurs, vous avez besoin du conteneur le plus fondamental du langage. Ensuite, nous aborderons les tableaux : comment les déclarer, les indexer, les parcourir et éviter l'accès hors limites qui provoque tant de comportements indéfinis en C++.

Questions fréquentes

Qu'est-ce qu'un stringstream en C++ ?

Un std::stringstream est un flux adossé à une string plutôt qu'au clavier ou à un fichier. Vous y écrivez avec << et vous y lisez avec >>, exactement comme cout et cin, ce qui en fait l'outil standard pour analyser du texte et construire des chaînes en mémoire. Il se trouve dans l'en-tête <sstream>.

Comment convertir une chaîne en int en C++ avec stringstream ?

Placez le texte dans un flux et extrayez-le vers un nombre : stringstream ss("42"); int n; ss >> n;. Vérifiez avec if (ss) (ou if (ss >> n)) que la conversion a réellement réussi. Pour les cas simples, std::stoi est plus court, mais stringstream excelle lorsqu'une seule chaîne contient plusieurs valeurs mélangées.

Pourquoi dois-je appeler clear() sur un stringstream ?

Une fois qu'un flux atteint la fin de ses données, ses bits eof/fail restent activés et chaque >> suivant ne fait silencieusement rien. Si vous réutilisez le même stringstream avec un nouveau contenu, appelez ss.clear() pour réinitialiser ces indicateurs d'erreur, puis ss.str(newText) pour charger de nouvelles données ; sinon, les lectures échouent silencieusement.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER