L'utilisation de cette bibliothèque d'entrée-sortie offre l'avantage de gérer directement et sans risque d'erreur les types des variables ou objets entrés et sortis dans toutes les situations standard. C'est à comparer avec la bibliothèque d'entrée-sortie du C où le type des variables manipulées doit être indiqué dans la chaîne de format. Au contraire, C++ nomme les objets à l'endroit où ils doivent apparaître :
//bibliotheque du C printf("la valeur du %d eme element est %f\n",i,x[i]); //bibliotheque du C++ cout << "la valeur du " << i << "eme element est : " << x[i+1] << "\n";
On constate une plus grande lisibilité et un plus faible risque d'erreur :
C'est le compilateur qui, connaissant le type de i et x[i] insère leur valeur convenablement décodée dans le flux cout.
Ces manipulations sont gérés par des objets appartenant aux classes suivantes :
Les deux classes istream et ostream dérivent de la classe de base ios qui contient les données et fonctions communes, tels que les flags de format.
Elles sont classes de base de la classe iostream, qui par ce double héritage permet de manipuler des flux dans les deux directions, en particulier les fichiers par la classe fstream qui en hérite.
Les opérateurs d'insertion << et d'extraction >> permettent respectivement d'écrire et de lire une information dans (depuis) des objets ostream (istream) (ou des classes dérivées). Ce sont des surcharges dans les classes ostream et istream (définies pour tous les types courants) des opérateurs de décalage bien connus.
Il pointe (graphiquement) sur l'objet ostream dans lequel l'information est insérée.
Si par exemple cette information est une chaîne de caractères, le prototype de la surcharge de l'opérateur d'insertion est :
ostream &ostream::operator <<(char const *text);
Il opère donc sur la chaîne pointée par text et retourne une référence ostream & sur l'objet de classe ostream qui l'a appelé.
L'opérateur est donc associatif, ce qui permet d'écrire des instructions telles que
cout << "bonjour " << "monsieur";
Dans ce cas :
cout << "bonjour "est d'abord évalué, qui retourne une référence sur l'objet cout dans lequel la chaîne "bonjour" a été insérée
la même opération peut donc se répéter avec la deuxième chaîne :
cout << "monsieur"qui se trouve ainsi insérée dans cout à son tour.
Une variante de cette surcharge existe pour de nombreux types du membre de droite de l'opérateur, l'utilisateur peut en définir de nouveaux, spécifiques à son application.
Grâce à l'amitié, des nouvelles classes peuvent contenir une surcharge de << utilisable avec des objets ostream.
Remarque
Si l'opérande de droite de l'opérateur d'insertion est un pointeur sur caractère, c'est la chaîne pointée qui est insérée, ce qui correspond à ce qui est souhaité le plus souvent. Si on veut insérer la valeur du pointeur, il faut le convertir en void *.
char *tampon=newDup("Bonjour !"); cout << "Chaine pointee : " << tampon << "\n"; cout << "Valeur du pointeur : " << (void *)tampon << "\n";
Ces lignes donnent à l'exécution :
Chaine pointee : Bonjour ! Valeur du pointeur : 0x003000E0
Comme pour la fonction scanf(), les blancs sont ignorés par cet opérateur et indiquent la fin de la saisie d'une chaîne. On ne peut donc pas l'utiliser pour entrer une chaîne de caractères contenant des blancs, comme par exemple "rue de la paix".
Il reçoit une référence sur une variable dont on veut fixer la valeur et retourne la référence à l'objet auquel il appartient, ce qui assure son associativité.
cin >> x; cin >> c >> y;
Les chaînes ordinaires (tableau de caractères terminé par '\0') peuvent être traitées comme les fichiers si des objets istrstream ou ostrstream sont créés et leur sont associés.
Ces objets lisent des informations dans la mémoire ou écrivent des informations dans la mémoire, sous forme de caractères (octets).
Exemple, pour écrire une chaîne dans un bloc mémoire pointé par buffer :
char buffer[100]; //le bloc memoire ostrstream memoire(buffer,100); //déclaration de l'objet //constructeur avec parametres //qui connecte l'objet à buffer memoire << "Bonjour monsieur" << endl << ends; cout << memoire.str();
Fonctions membres :
constructeur pour un flux associé au bloc mémoire pointé par str et de dimension size. Si la dimension size n'est pas précisée, le bloc mémoire est traité comme une chaîne terminée par le caractère nul.
constructeur pour un flux de sortie qui sera géré dynamiquement : la taille et l'adresse du bloc mémoire associé ne sont pas précisés.
constructeur pour un flux de sortie vers une chaîne définie par les arguments. Le mode optionnel peut être l'un des modes iostream. par défaut : ios::out.
retourne la longueur courante de la chaîne associée .
retourne un pointeur sur la chaîne associée à l'objet. Cette fonction implique freeze() ci-dessous.
Si n est non nul (par défaut), la chaîne associée à l'objet ne peut plus être modifiée dynamiquement. Elle ne sera pas réallouée (si plus d'espace est nécessaire), ni désallouée quand l'objet sera détruit.
Teste si la chaîne est gelée.
On a vu que les objets de la classe string permettent de manipuler des séquences quelconques de caractères, sans avoir à se soucier de la gestion de la mémoire qui est prise en charge par les fonctions membres de la classe de façon transparente. Il n'y a aucune contrainte sur la nature des caractères de la séquence. En particulier le caractère '\0' n'est pas utilisé pour marquer la fin de la chaîne, et peut figurer à n'importe quelle place dans la séquence.
Les objets des classes istringstream et ostringstream permettent de connecter le programme à ces objets de la classe string.
Le fichier d'en-tête <sstream> doit être inclus, et il faut se placer dans l'espace de nom std
ostringstream adresse; adresse << "18" << " rue des pierres "; string texte=sortie.str(); cout << texte << endl;
Donne à l'exécution l'affichage de la chaîne "18 rue des pierres".
C'est la déclaration d'un objet istream (lecture) ou ostream (écriture) ou des classes dérivées selon la nature du flux. Plusieurs constructeurs existent:
ofstream fichier_sortie("SORTIE.DAT");
Création de l'objet fichier_sortie associé au fichier physique SORTIE.DAT, qui est ouvert en écriture s'il existe ou créé en écriture s'il n'existe pas.
Les informations éventuellement présentes dans ce fichier seront écrasées.
ofstream fichier_sortie("SORTIE.DAT",ios::out);
Précise le mode d'ouverture par la valeur out d'une énumération de la classe ios
Même résultat que ci-dessus puisque c'est le mode par défaut pour les objets ofstream.
ofstream fichier_sortie("SORTIE.DAT",ios::app);
Ouverture en mode ajout à la fin du fichier (append).
La valeur retournée par ces constructeurs est nulle en cas d'échec.
ostrstream texte;
création d'un objet vide
ostrstream texte_sortie("Introduction");
création et initialisation par la chaîne passée en argument.
Ces chaînes grandissent dynamiquement au fur et à mesure que des informations y sont insérées.
Elles ne sont pas automatiquement terminées par le caractère de fin de chaîne.
ifstream fichier_entree("ENTREE.DAT");
Le fichier ENTREE.DAT est ouvert en lecture et associé à l'objet fichier. Le fichier doit exister au préalable, sinon la création de l'objet fichier échoue (et la valeur 0 est retournée).
ifstream fichier_entree("ENTREE.DAT", ios::in);
même effet.
istrstream texte_entree("Conclusion");
Le mode texte est le mode par défaut.
On peut préciser ce mode par ios::binary ou ios::text.
ofstream fichier_sortie("SORTIE.DAT",ios::app|ios::binary);
Les objets ouverts en écriture utilisent l'opérateur d'insertion << :
fichier_sortie << "Chapitre 1\n";
Les objets ouverts en lecture utilisent l'opérateur d'extraction >> qui en extrait l'information :
fichier_entree >> x >> y;
Il faut se souvenir que, par défaut, l'opérateur d'extraction saute les blancs qui lui indiquent la fin des champs :
si fichier_entree contient
56 23 a b bonjour Monsieur
quel est l'effet du code suivant ?
int i,j; char c, mot[10]; fichier_entree >> i >> j >> c >> c >> mot >> mot;
Si les deux opérations doivent être faites sur un fichier (une chaîne), un objet fstream (strstream) doit être créé.
fstream fichier("DATA.ES",ios::in|ios::out);
Les deux opérateurs d'extraction et d'insertion peuvent alors être utilisés sur cet objet.
La séquence copiée en mémoire est terminée par '\0'.
La valeur par défaut de delim est '\n'.
La valeur par défaut de delim est '\n'.
Utile si le flux est coincé par un caractère indésirable.
Valeur par défaut de d : EOF.
On dispose pour cela de fonctions membres et de manipulateurs.
Il faut inclure iomanip.h pour les utiliser.
Ils sont définis dans la surcharge des opérateurs d'extraction et d'insertion et doivent être insérés dans une instruction d'extraction ou d'insertion. En voici quelques uns :
cout << setw(10) << i ;
Les mêmes résultats peuvent être obtenus en appelant des fonctions membres du flux manipulé :
cout.precision(4); cout << sqrt(2) << endl; cout.precision(6); cout << -sqrt(2) << endl;
positionnement des drapeaux de format.
La fonction membre setf() définit le format d'affichage des nombres en activant des flags de la classe ios.
Elle reçoit un ou deux arguments (des flags de la classe ios).
La fonction membre unsetf() désactive au contraire des flags de la classe iosm
Par exemple :
cout.setf(ios::showbase); cout << 16 << ", " << hex << 16 << ", " << oct << 16 << endl;
donne le résultat :
16, 0x10, 020
Pour l'affichage des réels :
cout.setf(ios::fixed, ios::floatfield); cout << sqrt(200) << endl; cout.setf(ios::scientific, ios::floatfield); cout << sqrt(200) << endl;
donne :
14.142136 1.414214e+01
Également :
ios::left ,ios::internal, ios::skipws,setf(ios::showbase) (affiche la base de numération des entiers), setf(ios::showpoint) pour afficher le point décimal des réels, setf(ios::dec, ios::basefield), setf(ios::hex, ios::basefield), setf(ios::oct, ios::basefield) : même effet que les manipulateurs dec, hex et oct
Les fonctions membres seekg(), tellg() (pour les flux en lecture (g est pour getpointer) et seekp(), tellp() (pour les flux en écriture (putpointer) permettent de se positionner (seek) ou de donner la position (tell) dans un flux.
Par exemple :
seekg(long offset, seek_dir position = ios::beg);
seek_dir position peut être :