Skip to content
Snippets Groups Projects
jupytext:
  text_representation:
    extension: .md
    format_name: myst
    format_version: 0.13
kernelspec:
  display_name: C++17
  language: C++17
  name: xcpp17
rise:
  auto_select: first
  autolaunch: false
  centered: false
  controls: false
  enable_chalkboard: true
  height: 100%
  margin: 0
  maxScale: 1
  minScale: 1
  scroll: true
  slideNumber: true
  start_slideshow_at: selected
  transition: none
  width: 90%

+++ {"slideshow": {"slide_type": "slide"}}

Lecture et écriture dans des chaînes de caractères

+++ {"slideshow": {"slide_type": "notes"}}

Nous avons vu comment lire et écrire facilement des valeurs de types divers (entiers, flottants) dans un fichier texte. Sous le capot cela a requis des opérations de natures différentes :

  1. interactions avec le système pour lire et écrire du texte dans un fichier
  2. conversions de valeurs en texte et réciproquement

Ne pourrait-on pas utiliser ce deuxième point pour lire et écrire des valeurs dans des chaînes de caractères? Après tout, elles contiennent du texte elles aussi! Allons-y.

+++ {"slideshow": {"slide_type": "fragment"}}

Au préalable, nous aurons besoin de la bibliothèque suivante :

---
slideshow:
  slide_type: fragment
---
#include <sstream>
using namespace std;

+++ {"slideshow": {"slide_type": "slide"}}

Lecture depuis une chaîne de caractères

+++ {"slideshow": {"slide_type": "fragment"}}

Exemple

+++ {"slideshow": {"slide_type": "fragment"}}

La chaîne de caractère suivante contient -- sous forme de texte -- plusieurs nombres :

---
slideshow:
  slide_type: fragment
---
string s = "1 2 4 8 16";

Comment extraire ces nombres de s?

+++ {"slideshow": {"slide_type": "notes"}}

On souhaiterait extraire ces nombres en les convertissant en entiers. Pour cela on créé un flux de type istringstream (pour flux entrant depuis une chaîne de caractères) rattaché à s :

---
slideshow:
  slide_type: fragment
---
istringstream flux = istringstream(s)

+++ {"slideshow": {"slide_type": "fragment"}}

Maintenant il est possible de lire le premier nombre, en procédant comme s'il était dans un fichier :

---
slideshow:
  slide_type: fragment
---
int i;
---
slideshow:
  slide_type: fragment
---
flux >> i;
i

+++ {"slideshow": {"slide_type": "fragment"}}

Lorsque l'on effectue de nouvelles lectures, les nombres suivants sont lus un à un :

---
slideshow:
  slide_type: fragment
---
flux >> i;
i
---
slideshow:
  slide_type: fragment
---
flux >> i;
i
---
slideshow:
  slide_type: fragment
---
flux >> i;
i

+++ {"slideshow": {"slide_type": "slide"}}

L'exemple suivant illustre que l'on peut lire successivement des valeurs de types mixtes, qu'un nombre quelconque d'espaces sert de séparateur, et que l'on peut enchaîner ces lectures :

---
slideshow:
  slide_type: fragment
---
string s = "truc 33 bidule   2.5 reste"
---
slideshow:
  slide_type: fragment
---
istringstream flux = istringstream(s);
---
slideshow:
  slide_type: fragment
---
string a, b;
int i;
float f;
---
slideshow:
  slide_type: fragment
---
flux >> a >> i >> b >> f;
---
slideshow:
  slide_type: fragment
---
a
---
slideshow:
  slide_type: fragment
---
b
---
slideshow:
  slide_type: fragment
---
i
---
slideshow:
  slide_type: fragment
---
f

+++ {"slideshow": {"slide_type": "slide"}}

Syntaxe et sémantique

+++ {"slideshow": {"slide_type": "fragment"}}

:::{admonition} Syntaxe

istringstream flux = istringstream(s);
flux >> variable1;
flux >> variable2;
          ...

:::

+++ {"slideshow": {"slide_type": "fragment"}}

:::{admonition} Sémantique

Affecte aux variables variable1, variable2, ... les valeurs lues successivement depuis la chaîne de caractères s, en tenant compte de leurs types respectifs.

:::

+++ {"slideshow": {"slide_type": "slide"}}

Écriture dans une chaîne de caractères

Réciproquement, on peut souhaiter écrire le contenu de variables non pas directement à l'écran ou dans un fichier mais dans une chaîne de caractères. Le principe sera le même que pour une lecture.

+++ {"slideshow": {"slide_type": "fragment"}}

Exemple

+++ {"slideshow": {"slide_type": "fragment"}}

On commence par définir un flux de type ostringstream (pour flux sortant vers une chaîne de caractères) :

---
slideshow:
  slide_type: fragment
---
ostringstream flux;

+++ {"slideshow": {"slide_type": "fragment"}}

Nous pouvons maintenant écrire dans ce flux :

---
slideshow:
  slide_type: fragment
---
flux << 3.53 << " coucou " << 1 << endl;
flux << 42 << endl;

+++ {"slideshow": {"slide_type": "fragment"}}

et enfin extraire la chaîne de caractère produite :

---
slideshow:
  slide_type: fragment
---
string s = flux.str();
s

+++ {"slideshow": {"slide_type": "slide"}}

Syntaxe et sémantique

+++ {"slideshow": {"slide_type": "fragment"}}

:::{admonition} Syntaxe

ostringstream flux;
flux << variable1;
flux << variable2;
string s = flux.str()

:::

+++ {"slideshow": {"slide_type": "fragment"}}

:::{admonition} Sémantique

Construit une chaîne de caractères s en écrivant successivement le contenu des variables variable1, variable2, ... en tenant compte de leurs types respectifs.

:::

+++ {"slideshow": {"slide_type": "slide"}}

Application typique : séparation calcul et entrées sorties

+++ {"slideshow": {"slide_type": "notes"}}

Ce que nous venons de voir sera très utile pour séparer proprement ce qui relève du calcul et ce qui relève des entrées-sorties. Supposons par exemple que nous souhaitions afficher joliment une entrée d'un annuaire :

---
slideshow:
  slide_type: fragment
---
using namespace std;
#include <iostream>
#include <sstream>
---
slideshow:
  slide_type: fragment
---
void afficheEntreeAnnuaire(string nom, string prenom, string tel) {
    cout << "Nom: " << nom 
         << ", Prénom: " << prenom
         << ", Téléphone: " << tel;
}
---
slideshow:
  slide_type: fragment
---
afficheEntreeAnnuaire("Lovelace", "Ada", "07 23 23 23 23")

+++ {"slideshow": {"slide_type": "fragment"}}

:::{admonition} Questions

  • Comment réutiliser cette fonction pour écrire le texte non pas à l'écran mais dans un fichier?
  • Comment tester cette fonction? :::

+++ {"slideshow": {"slide_type": "fragment"}}

Cela est rendu difficile par le mélange de deux actions de natures différentes dans une seule fonction :

  1. Construire le texte représentant l'entrée dans l'annuaire.
  2. Afficher ce texte à l'écran.

+++ {"slideshow": {"slide_type": "fragment"}}

Il faut donc séparer ces deux actions. L'écriture dans une chaîne va nous aider à le faire.

+++ {"slideshow": {"slide_type": "fragment"}}

La fonction suivante se concentre sur la construction du texte représentant l'entrée dans l'annuaire :

---
slideshow:
  slide_type: fragment
---
string formateEntreeAnnuaire(string nom, string prenom, string tel) {
    ostringstream flux;
    flux << "Nom: " << nom 
         << ", Prénom: " << prenom
         << ", Téléphone: " << tel;
    return flux.str();
}

+++ {"slideshow": {"slide_type": "fragment"}}

Le texte produit est renvoyé par la fonction au lieu d'être affiché. Nous pouvons donc maintenant :

  • l'affecter à une variable :
---
slideshow:
  slide_type: fragment
---
string s = formateEntreeAnnuaire("Lovelace", "Ada", "07 23 23 23 23")

+++ {"slideshow": {"slide_type": "fragment"}}

  • l'afficher :
---
slideshow:
  slide_type: fragment
---
cout << s << endl;

+++ {"slideshow": {"slide_type": "fragment"}}

  • calculer avec :
---
slideshow:
  slide_type: fragment
---
"- " + s

+++ {"slideshow": {"slide_type": "fragment"}}

  • ou nous en servir pour toute autre opération, comme l'écrire dans un fichier.

+++ {"slideshow": {"slide_type": "fragment"}}

De plus, nous pouvons maintenant aisément tester notre fonction :

---
slideshow:
  slide_type: fragment
---
CHECK( formateEntreeAnnuaire("Lovelace", "Ada", "07 23 23 23 23")
       == "Nom: Lovelace, Prénom: Ada, Téléphone: 07 23 23 23 23" );

+++ {"slideshow": {"slide_type": "slide"}}

Résumé

Dans cette feuille:

  • nous avons vu comment lire et écrire des données de types divers dans des chaînes de caractères.
  • Nous l'avons appliqué pour mieux séparer fonctions qui calculent et fonctions d'entrées-sorties.
  • Enfin nous avons noté que, grâce au concept de flux, on peut utiliser la même syntaxe que pour lire et écrire dans un fichier ou pour interagir avec l'utilisateur.