Contenu connexe
Similaire à Partie 14: Entrée/Sortie — Programmation orientée objet en C++ (20)
Partie 14: Entrée/Sortie — Programmation orientée objet en C++
- 2. Vue d'Ensemble
Notions de base
Types, variables, opérateurs
Contrôle d'exécution
Fonctions
Mémoire dynamique
Qualité du logiciel
Evolution du modèle objet
Objets et classes
Fonctions membres
Classes génériques
Héritage
Polymorphisme
Héritage multiple
Entrée/sortie
POO en C++: Entrée/Sortie 479 © 1997-2003 Fabio HERNANDEZ
- 3. Table des Matières
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 480 © 1997-2003 Fabio HERNANDEZ
- 4. Introduction
Les mécanismes d'entrée/sortie ne font pas partie du langage
C++ proprement dit
Ils ont été implémentés en C++ et font partie de la bibliothèque
standard livrée avec tout compilateur
Au niveau le plus bas, un fichier est vu comme comme une
séquence (stream) d'octets
Des composants de la bibliothèque standard s'occupent du
transfert de ces octets
pas de notion de type
Au plus haut niveau, un fichier est vu comme une séquence de
données de type différent (caractères, valeurs arithmétiques,
objets,...)
POO en C++: Entrée/Sortie 481 © 1997-2003 Fabio HERNANDEZ
- 5. Introduction (suite)
La bibliothèque standard fournit un ensemble d'opérations pour
l'entrée/sortie des objets des types de base du langage (char,
int, float, long,...)
Le programmeur peut étendre quelques unes de ces opérations
pour l'entrée/sortie des objets des classes définies par lui
Un flux (stream) est une abstraction logicielle représentant un
flot de données entre
une source (producteur de données)
une cible (consommateur des données)
Opérateur de sortie ou d'injection dans le flot: <<
une valeur/donnée est dite injectée dans le flot de sortie
Opérateur d'entrée ou d'extraction du flot: >>
une valeur/donnée est dite extraite du flot d'entrée
POO en C++: Entrée/Sortie 482 © 1997-2003 Fabio HERNANDEZ
- 6. Introduction (suite)
La direction de l'opérateur indique le sens du flux de données
transfert de données du flot vers la variable counter
cin >> counter;
transfert de données de la variable counter vers le flot
cout << counter;
Par défaut, un programme en C++ peut utiliser trois flots
prédéfinis
cout: flot de sortie correspondant à la sortie standard (instance de la
classe ostream_withassign)
cin: flot d'entrée correspondant à l'entrée standard (instance de la
classe istream_withassign)
cerr: flot de sortie correspondant à la sortie standard d'erreur
(instance de la classe ostream_withassign)
POO en C++: Entrée/Sortie 483 © 1997-2003 Fabio HERNANDEZ
- 7. Introduction (suite)
Pour utiliser ces flots il est nécessaire d'inclure le fichier
iostream
POO en C++: Entrée/Sortie 484 © 1997-2003 Fabio HERNANDEZ
- 8. Hiérarchie de classes
ios
ostream istream
ostream_withassign iostream istream_withassign
iostream_withassign
POO en C++: Entrée/Sortie 485 © 1997-2003 Fabio HERNANDEZ
- 9. Hiérarchie de classes - standard
ios_base
basic_ios<>
ios / wios
basic_stream<> basic_ostream<>
istream / wistream ostream / wostream
basic_iostream<>
iostream / wiostream
POO en C++: Entrée/Sortie 486 © 1997-2003 Fabio HERNANDEZ
- 10. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 487 © 1997-2003 Fabio HERNANDEZ
- 11. Flot de sortie
La méthode générale est d'appliquer l'opérateur de sortie au
flot cout
#include <iostream>
void main()
{
cout << "The result of 13+89 is " << 13+89 << endl;
}
A l'écran sera affiché
The result of 13+89 is 102
Le flot cout accepte des arguments de tous les types primitifs
du langage, y compris les pointeurs (char*, int*, ...) qui sont
affichés comme des valeurs hexadécimales
POO en C++: Entrée/Sortie 488 © 1997-2003 Fabio HERNANDEZ
- 12. Flot de sortie (suite)
Affichage de pointeurs
int counter = 1024;
int* counterPtr = &counter;
cout << "counter = " << counter
<< " &counter = " << &counter << endl;
cout << "*counterPtr = " << *counterPtr
<< " counterPtr = " << counterPtr << endl;
affichera à l'écran
counter = 1024 &counter = 0x7ffff0b4
*counterPtr = 1024 counterPtr = 0x7ffff0b4
POO en C++: Entrée/Sortie 489 © 1997-2003 Fabio HERNANDEZ
- 13. Flot de sortie (suite)
Affichage de pointeurs à des chaînes de caractères
char* author = "Carl Sagan";
cout << "author = " << author << endl;
affichera à l'écran
author = Carl Sagan
Les objets de type char* ne sont pas interprétés comme des pointeurs
mais comme des chaînes de caractères
Une conversion forcée est nécessaire pour afficher l'adresse mémoire
du pointeur
cout << "author = " << (void*)author << endl;
POO en C++: Entrée/Sortie 490 © 1997-2003 Fabio HERNANDEZ
- 14. Flot de sortie (suite)
Les opérateurs de sortie sont de la forme
class ostream: public ios {
...
ostream& operator<<(int value);
...
};
chaque opérateur retourne une référence à l'objet ostream sur lequel il
a été appelé, afin de pouvoir le cascader dans une seule instruction
cout << 1234 << "hello";
La valeur de
ce qui est équivalent à retour de
cout.operator<<(1234).operator<<("hello"); l'opération est
une référence
à un objet de la
classe ostream
POO en C++: Entrée/Sortie 491 © 1997-2003 Fabio HERNANDEZ
- 15. Flot de sortie (suite)
En plus de l'opérateur d'injection <<, la classe ostream
contient d'autres méthodes, parmi lesquelles
ostream& put(char aChar) pour insérer un caractère dans le flot
Exemple:
cout.put('A');
ostream& write(const char* buffer, int howmany) pour
insérer howmany caractères à partir de buffer dans le flot
Exemple:
cout.write("This is a string", 3);
ostream& flush() pour vider les tampons du flux et forcer l'envoi
immédiat des données sur le fichier/écran
POO en C++: Entrée/Sortie 492 © 1997-2003 Fabio HERNANDEZ
- 16. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 493 © 1997-2003 Fabio HERNANDEZ
- 17. Flot d'entrée
L'opérateur d'entrée >> fonctionne de façon similaire à
l'opérateur de sortie
Tous les opérateurs d'extraction pour les types primitifs sont
fournis, y compris pour char*
int min;
int max;
cout << "Please enter min and max: " << endl;
cin >> min >> max;
cout << "Values just read are: " << min << " and "
<< max << endl;
POO en C++: Entrée/Sortie 494 © 1997-2003 Fabio HERNANDEZ
- 18. Flot d'entrée (suite)
L'opérateur d'entrée peut être utilisé comme la condition d'une
boucle
char nextChar;
while (cin >> nextChar) {
// process nextChar here
}
extraction d'un caractère à la fois de l'entrée standard
quand la fin de l'entrée est atteinte, la condition est fausse et la boucle
finit
POO en C++: Entrée/Sortie 495 © 1997-2003 Fabio HERNANDEZ
- 19. Flot d'entrée (suite)
La séquence de caractères
ab c
d e
est traitée comme une suite de cinq caractères
('a','b','c','d','e'): les espaces et les changements de ligne
servent uniquement pour séparer les différents valeurs et ne
sont pas traités comme caractères
Extraction d'une chaîne de caractères
char string[20];
cin >> string;
une chaîne est traitée comme une suite de caractères délimitée par des
espaces
POO en C++: Entrée/Sortie 496 © 1997-2003 Fabio HERNANDEZ
- 20. Flot d'entrée (suite)
Extraction d'une chaîne de caractères (suite)
l'instruction
cin >> string;
avec l'entrée
Gone with the wind
produit comme résultat la chaîne Gone dans la variable string
Le caractère nulle ('0') est rajouté en fin de chaîne pendant
l'entrée
la taille de la variable doit être au moins la longueur de la chaîne plus un
POO en C++: Entrée/Sortie 497 © 1997-2003 Fabio HERNANDEZ
- 21. Flot d'entrée (suite)
Exemple: déterminer la longueur maximum d'une suite de
chaînes de caractères extraites de l'entrée standard
char buffer[100];
int maxLength = -1;
int currentLength = 0;
while (cin >> buffer) {
currentLength = strlen(buffer);
if (maxLength < currentLength)
maxLength = currentLength;
}
cout << "The max length is " << maxLength << endl;
POO en C++: Entrée/Sortie 498 © 1997-2003 Fabio HERNANDEZ
- 22. Flot d'entrée (suite)
Le manipulateur setw peut être utilisé pour éviter le
dépassement de la capacité du buffer d'entrée
const int MaxCapacity = 100;
char buffer[MaxCapacity];
while (cin >> setw(MaxCapacity) >> buffer) {
...
}
setw divise une chaîne d'une longueur égale ou supérieure à
MaxCapacity en deux ou plusieurs chaînes d'une longueur maximum de
MaxCapacity-1
le fichier d'en-tête iomanip.h doit être inclus pour pouvoir utiliser
setw
POO en C++: Entrée/Sortie 499 © 1997-2003 Fabio HERNANDEZ
- 23. Flot d'entrée (suite)
En plus de l'opérateur d'extraction >>, la classe istream
contient d'autres méthodes, parmi lesquelles
int get() pour extraire le caractère suivant dans le flot d'entrée
int nextChar = cin.get();
while (nextChar != EOF) {
cout.put(nextChar);
nextChar = cin.get();
}
istream& get(char& aChar) extrait le caractère suivant dans le
flux (même si c'est un espace) et le place dans aChar
istream& get(char* buffer, int count, char delim='n')
extrait count-1 caractères du flux et les place dans buffer. La
lecture s'arrête au délimiteur delim ou à la fin du fichier. Le délimiteur
n'est pas extrait du flux
POO en C++: Entrée/Sortie 500 © 1997-2003 Fabio HERNANDEZ
- 24. Flot d'entrée (suite)
Autres méthodes de istream (suite)
istream& getline(char* buffer,
int count,
char delim='n')
comme la méthode précédente sauf que le délimiteur est extrait du flux
mais pas recopié dans buffer
istream& read(char* buffer, int count) pour extraire un bloc
d'au plus count octets et les placer dans buffer. Le nombre d'octets
effectivement lus peut être obtenu par la méthode gcount()
int gcount() retourne le nombre d'octets extraits lors de la dernière
lecture
POO en C++: Entrée/Sortie 501 © 1997-2003 Fabio HERNANDEZ
- 25. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 502 © 1997-2003 Fabio HERNANDEZ
- 26. Fichiers et flots
ios
ostream fstreambase istream
ofstream ifstream
iostream
fstream
POO en C++: Entrée/Sortie 503 © 1997-2003 Fabio HERNANDEZ
- 27. Fichiers et flots - standard
ios_base
basic_ios<>
ios / wios
basic_istream<> basic_ostream<>
istream / wistream ostream / wostream
basic_iostream<>
iostream / wiostream
basic_ifstream<> basic_fstream<> basic_ofstream<>
ifstream / wifstream fstream / wfstream ofstream / wofstream
POO en C++: Entrée/Sortie 504 © 1997-2003 Fabio HERNANDEZ
- 28. Fichiers et flots (suite)
Il est possible de créer un objet flot associé à un fichier sur
disque
Plusieurs classes prédéfinies dans le fichier fstream.h
ifstream permet d'attacher un fichier à un flot d'entrée
ofstream permet d'attacher un fichier à un flot de sortie
fstream permet d'attacher un fichier à un flot d'entrée et de sortie
Pour associer un flot à un fichier de sortie on utilise le
constructeur ou la méthode open
ofstream outFile("MyFile.dat", ios::out);
outFile << "Ceci n'est pas une chaine" << endl;
les arguments spécifiés sont le nom du fichier et le mode d'ouverture,
qui peut être ios::out ou ios::app
un fichier existant ouvert en mode ios::out perdra toutes ses données
POO en C++: Entrée/Sortie 505 © 1997-2003 Fabio HERNANDEZ
- 29. Fichiers et flots (suite)
Exemple: lecture des caractères de l'entrée standard et
écriture dans un fichier
#include <fstream>
// Open the file
ofstream outFile("copy.dat", ios::out);
// Copy all the characters from input to the file
char nextChar = cin.get();
while (nextChar != EOF) {
outFile.put(nextChar);
nextChar = cin.get();
}
POO en C++: Entrée/Sortie 506 © 1997-2003 Fabio HERNANDEZ
- 30. Fichiers et flots (suite)
Sur un flot on peut envoyer des objets d'une classe définie par
nous, pourvu que l'opérateur << soit défini pour la classe
ofstream outFile("Points.dat", ios::out);
Point aPoint(14.0, 34.0);
outFile << aPoint;
Pour lire un fichier on utilise la classe ifstream
#include <fstream>
ifstream inputFile("copy.dat", ios::in);
char nextChar;
while (inputFile.get(nextChar))
cout.put(nextChar);
POO en C++: Entrée/Sortie 507 © 1997-2003 Fabio HERNANDEZ
- 31. Fichiers et flots (suite)
Exemple: lire les chaînes des caractères d'un fichier d'entrée
et les envoyer vers un fichier de sortie séparées d'un retour de
chariot
const char* inputFileName = "Input.dat";
const char* outputFileName = "Output.dat";
ifstream inputFile(inputFileName, ios::in);
ofstream outputFile(outputFileName, ios::out);
const int MaxCapacity = 1024;
char buffer[MaxCapacity];
while (inputFile >> setw(MaxCapacity) >> buffer)
outputFile << buffer << endl;
POO en C++: Entrée/Sortie 508 © 1997-2003 Fabio HERNANDEZ
- 32. Fichiers et flots (suite)
L'ouverture du fichier (d'entrée et de sortie) peut être faite
après la construction du flot
ifstream inputFile;
// Do something here
inputFile.open("Input.dat", ios::in);
Le flot peut être déconnecté du fichier avec la méthode
close() et connecté à un autre fichier ultérieurement
inputFile.close();
// ...
inputFile.open("AnotherInputFile.dat", ios::in);
Le comportement est similaire pour les objets de la classe
ofstream
POO en C++: Entrée/Sortie 509 © 1997-2003 Fabio HERNANDEZ
- 33. Fichiers et flots (suite)
Un flot de la classe fstream peut être attaché à un fichier
pour la lecture ou pour l'écriture de données
fstream file;
file.open("MyFile.dat", ios::out);
file << 1234;
file.close();
file.open("MyFile.dat", ios::in);
int i;
file >> i;
file.close();
cout << "i = " << i << endl;
POO en C++: Entrée/Sortie 510 © 1997-2003 Fabio HERNANDEZ
- 34. Fichiers et flots (suite)
Attachement d'un flot à un fichier en entrée et en sortie
simultanément
fstream file("MyFile.dat", ios::in|ios::out);
istream offre des méthodes pour se positionner dans le
fichier
istream& seekg(streampos position);
istream& seekg(streamoff offset,
ios::seek_dir direction);
streampos et streamoff sont des synonymes de long
ios::seek_dir est une énumération qui définit trois valeurs
ios::beg, ios::cur et ios::end
ios::beg pour se positionner offset octets à partir du début du
fichier
POO en C++: Entrée/Sortie 511 © 1997-2003 Fabio HERNANDEZ
- 35. Fichiers et flots (suite)
Positionnement dans le fichier (suite)
ios::end pour se positionner offset octets à partir de la fin du
fichier
ios::cur pour se positionner offset octets à partir de la position
actuelle du fichier
Avec la méthode tellg() on obtient la position actuelle dans le
fichier
streampos mark = outputFile.tellg();
// ....
if (cancelOutput)
outputFile.seekg(mark);
// ...
POO en C++: Entrée/Sortie 512 © 1997-2003 Fabio HERNANDEZ
- 36. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 513 © 1997-2003 Fabio HERNANDEZ
- 37. Etat d'un flot
La classe ios décrit les caractéristiques communes des flots
d'entrée et de sortie
C'est une classe de base de toute la hiérarchie des flots
Elle fournit des méthodes pour
interroger l'état d'un flot
formater l'information à envoyer dans un flot
Parmi les méthodes publiques de cette classe on peut citer
int good() retourne une valeur différente de zéro si la dernière
opération d'entrée/sortie s'est effectuée avec succès et zéro dans le
cas contraire
int fail() fait l'inverse de good()
int eof() retourne une valeur différente de zéro si la fin du fichier a
été atteinte et zéro dans le cas contraire
POO en C++: Entrée/Sortie 514 © 1997-2003 Fabio HERNANDEZ
- 38. Etat d'un flot (suite)
On peut utiliser ce mécanisme de contrôle de l'état pour
déterminer si l'ouverture d'un fichier s'est effectuée
correctement
ifstream inputFile("MyFile.dat", ios::in);
// Is the file really open?
if (inputFile.fail()) { // or: if (!inputFile.good())
cout << "Error opening file" << end;
return false;
}
// File is open, so continue...
POO en C++: Entrée/Sortie 515 © 1997-2003 Fabio HERNANDEZ
- 39. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 516 © 1997-2003 Fabio HERNANDEZ
- 40. Formatage
Chaque objet flot conserve en permanence un ensemble
d'indicateurs pour contrôler les opérations de formatage de
l'information
Ces indicateurs sont contenus dans la classe ios dont toutes
les classes de la bibliothèque standard d'entrée/sortie héritent
Cette classe fournit des méthodes permettant d'interroger et
de modifier les caractéristiques du formatage
précision des valeurs en virgule flottante
justification de la sortie à droite ou à gauche
modification de la base de représentation pour les valeur numériques
(hexadécimal, octal, décimal, ...)
notation scientifique pour les valeurs en virgule flottante
POO en C++: Entrée/Sortie 517 © 1997-2003 Fabio HERNANDEZ
- 41. Formatage (suite)
Par défaut les entiers sont lus et écrits en notation décimale
Pour changer la base on utilise des manipulateurs (hex, dec,
oct)
int i = 512;
cout << "Default i = " << i << endl;
cout << "Octal i = " << oct << i << endl;
cout << "Hexadecimal i = " << hex << i << endl;
cout << "Decimal i = " << dec << i << endl;
affiche
Default i = 512 Utilisation des
Octal i = 1000 manipulateurs
Hexadecimal i = 200 de changement
Decimal i = 512 de base
POO en C++: Entrée/Sortie 518 © 1997-2003 Fabio HERNANDEZ
- 42. Formatage (suite)
Par défaut, une valeur en virgule flottante est affichée avec 5
chiffres décimaux
Ce nombre peut être obtenu à l'aide de la fonction membre int
ios::precision() const et modifié avec la fonction
membre int ios::precision(int newPrecision)
cout << "Precision: " << cout.precision()
<< "sqrt(2.0): " << sqrt(2.0) << endl;
cout.precision(12);
cout << "Precision: " << cout.precision()
<< "sqrt(2.0): " << sqrt(2.0) << endl;
cout.precision(3);
cout << "Precision: " << cout.precision()
<< "sqrt(2.0): " << sqrt(2.0) << endl;
POO en C++: Entrée/Sortie 519 © 1997-2003 Fabio HERNANDEZ
- 43. Formatage (suite)
Affichage
Precision: 6 sqrt(2.0): 1.41421
Precision: 12 sqrt(2.0): 1.41421356237
Precision: 3 sqrt(2.0): 1.41
D'une façon générale, l'état de formatage de chaque flot fait
partie de ces attributs (classe ios)
Cet état est maintenu dans une variable de type long et
modifié via des méthodes de la classe ios et des masques de
bits
Exemple: contrôler l'affichage de la virgule pour les valeurs en
virgule flottante
POO en C++: Entrée/Sortie 520 © 1997-2003 Fabio HERNANDEZ
- 44. Formatage (suite)
Exemple (suite)
cout << 10.70 << endl;
affichera
10.7
et
cout << 10.0 << endl;
affichera
10
Pour afficher les zéros après la virgule
cout.setf(ios::showpoint);
POO en C++: Entrée/Sortie 521 © 1997-2003 Fabio HERNANDEZ
- 45. Formatage (suite)
Plusieurs notations pour les valeurs en virgule flottante
fixe (1.4142)
scientifique (1.41424e+000)
// show in default mode
cout << sqrt(2.0) << endl;
// set to fixed mode
cout.setf(ios::fixed, ios::floatfield);
cout << sqrt(2.0) << endl;
// set to scientific mode
cout.setf(ios::scientific, ios::floatfield);
cout << sqrt(2.0) << endl;
POO en C++: Entrée/Sortie 522 © 1997-2003 Fabio HERNANDEZ
- 46. Formatage (suite)
Pour les valeurs entières on peut afficher l'indicateur de la
base
décimal
octal
hexadécimal
cout.setf(ios::showbase);
cout << 15 << endl;
cout << hex << 15 << endl;
cout << oct << 15 << endl;
affichera
15
0xf
017
POO en C++: Entrée/Sortie 523 © 1997-2003 Fabio HERNANDEZ
- 47. Formatage (suite)
La largeur du champ de sortie peut être modifiée ainsi que le
caractère de remplissage pour la justification
cout.width(5);
cout.fill('*');
cout << 123 << endl;
affiche
**123
et si l'on modifie la justification
cout.setf(ios::left);
cout << 123 << endl;
affiche
123**
POO en C++: Entrée/Sortie 524 © 1997-2003 Fabio HERNANDEZ
- 48. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 525 © 1997-2003 Fabio HERNANDEZ
- 49. Manipulateurs
Ce sont des fonctions associées au flots d'entrée/sortie qui
permettent de modifier l'état du flot dans la même instruction
d'entrée/sortie
// Display in hexadecimal mode Manipulateurs
cout << hex << 512 << endl; sans arguments
// Change the width and padding character
cout << setw(5) << setfill('*') << endl;
Manipulateurs
avec des
arguments
POO en C++: Entrée/Sortie 526 © 1997-2003 Fabio HERNANDEZ
- 50. Manipulateurs (suite)
Un certain nombre de manipulateurs sont prédéfinis
dec, hex et oct pour les changements de base
endl, ends et flush
ws pour sauter les espaces
setbase(int newBase) pour modifier la base
setfill(int fillChar) pour modifier le caractère de remplissage
setprecision(int newPrecision) pour modifier la précision
setw(int width) pour modifier la largeur
...
On peut aussi définir ses propres manipulateurs (voir
documentation)
POO en C++: Entrée/Sortie 527 © 1997-2003 Fabio HERNANDEZ
- 51. Contrôle d'Avancement
Introduction
Flot de sortie
Flot d'entrée
Fichiers et flots
Etat d'un flot
Formatage
Manipulateurs
Résumé
POO en C++: Entrée/Sortie 528 © 1997-2003 Fabio HERNANDEZ
- 52. Résumé
C++ offre en standard une bibliothèque de classes pour
l'entrée/sortie de données
Une abstraction logicielle est introduite pour représenter un
flot de données entre une source productrice d'information et
une cible consommatrice
On utilise les même mécanismes pour injecter ou extraire des
données des flots standards et des fichiers disque
Des fonctions de formatage de l'information sont fournies et
peuvent être étendues
POO en C++: Entrée/Sortie 529 © 1997-2003 Fabio HERNANDEZ