-
Nicolas M. Thiéry authoredNicolas M. Thiéry authored
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 :
- interactions avec le système pour lire et écrire du texte dans un fichier
- 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 :
- Construire le texte représentant l'entrée dans l'annuaire.
- 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.