M1103 AMphi03
M1103 AMphi03
M1103 AMphi03
{ A. Casali / M. Laporte
• Exam de vendredi (quand, quoi)
• Evaluation des enseignements
• Projet
Plan
A. Flux de sortie
B. Flux d’entrée
F. Classe stringstream
A. Flux de sortie
On souhaite écrire le résultat de l’application dans un fichier de sortie
Problèmes :
• Comment fait-on si on souhaite écrire dans un fichier depuis une
interface graphique (ie, on n’a pas accès à la console);
• Comment peut on écrire dans plusieurs fichiers en même temps (on ne
peut faire que 2 redirections : la sortie standard et le flux d’erreur).
#include <fstream>
using namespace std;
ofstream ofs;
Exemple :
ofs.open ("test.txt");
A.3 Déclaration et Ouverture
En même temps qu’on déclare un flux sur un fichier, il est possible de spécifier:
• le fichier en question;
• Son mode d’ouverture.
Exemple :
ofstream ofs ("test.txt");
Exemple :
ofstream ofs ("test.txt", ios_base::out|ios_base::binary);
Exemple :
ofs.close ();
A.6 Ecriture dans un flux de sortie
L’injecteur fonctionne :
• Pour tous les types (int, char, bool, …);
• Pour certaines classes (string).
Exemple :
ofs << 10 << endl;
ofs << true << endl;
ofs << ‘a’ << endl;
ofs << "coucou" << endl;
more test.txt
10
1
a
coucou
De la même façon qu’on ne peut afficher un vecteur (vector)
sur la console, on ne peut pas l’injecter directement dans un
flux de sortie.
Exemple :
CVInt V (10);
ofs << V;
Exemple :
for (int x : V)
ofs << setw (3) << x;
more test.txt
0 0 0 0 0 0 0 0 0 0
Plan
A. Flux de sortie
B. Flux d’entrée
F. Classe stringstream
B. Flux d’entrée
On souhaite lire des données pour une application depuis un fichier d’entrée
Problèmes :
• Comment fait-on si on souhaite lire des données depuis le Net (voir
S3);
• Comment peut on lire depuis plusieurs fichiers en même temps (on ne
peut faire qu’une redirections : l’entrée standard).
#include <fstream>
using namespace std;
ifstream ifs;
Exemple :
ifstream ifs ("test.txt");
Exemple :
ifs.close ();
B.6 Existence d’un flux d’entrée
Exemple :
if (!ifs.is_open ())
{
cerr << "File not found" << endl;
return;
}
//le fichier existe et est accessible
B.7 Lecture depuis un flux d’entrée
int x;
ifs >> x;
cout << x << endl; 0
bool b;
ifs >> b;
cout << b << endl; 0
char c;
ifs >> c;
cout << c << endl; 0
string str;
ifs >> str;
cout << str << endl; 0
B.7 Lecture du contenu d’un fichier
Solution :
boucle
UnType Resultat <- lire_quelque_chose;
si (fin_de_fichier) sortie;
Manipuler (Resultat);
fboucle
Pour détecter la fin d’un fichier, on appelle la méthode eof () sur le flux
d’entrée. Cette méthode renvoie vrai si la fin d’un fichier a été atteint, faux sinon.
Exemple :
while (true)
{
AType VarIdent = ReadSomething ();
if (ifs.eof ()) break;
Manipulate (VarIdent);
}
Problème (1) :
Lire un vecteur d’entier préalablement stocké
CVInt V;
while (true)
{
int x;
ifs >> x;
if (ifs.eof ()) break;
V.push_back (x);
}
Problème (2) :
Connaître le nombre de mots d’un fichier texte
Commande wc –w sous Linux
unsigned wc (0);
string str;
while (true)
{
ifs >> str;
if (ifs.eof ()) break;
++wc;
}
cout << setw (8) << wc << ' ' << __FILE__ << endl;
Solution 1 :
unsigned wc (0);
char c;
while (true)
{
ifs >> c;
if (ifs.eof ()) break;
++wc;
}
cout << setw (8) << wc << ' ' << __FILE__ << endl;
unsigned wc = 0;
char c;
while (true)
{
ifs.get (c);
if (ifs.eof ()) break;
++wc;
}
cout << setw (8) << wc << ' ' << __FILE__ << endl;
Problème (4) :
Connaitre le nombre de lignes d’un fichier texte
Commande wc –l sous Linux
cout << setw (8) << wc << ' ' << __FILE__ << endl;
Plan
A. Flux de sortie
B. Flux d’entrée
F. Classe stringstream
C. Gestion des erreurs de
lecture
Ca aurait pu être n’importe quel
C.1 Echec de lecture ifstream, le résultat aurait été le même
int i;
for ( ; ; )
{
cout << "Taper un entier suivi de <CR> : ";
cin >> i;
if (cin.eof ()) break;
cout << "i = " << i << endl;
}
Taper un entier suivi de <CR> : x10
i = 1075991360
Taper un entier suivi de <CR> : i = 1075991360
Taper un entier suivi de <CR> : i = 1075991360
Taper un entier suivi de <CR> : i = 1075991360
...
1. L’utilisateur n’a pas entré un int;
2. La chaine de caractère "x10" reste dans le tampon;
3. Le tampon n’a pas pu se vider;
4. A chaque tour de boucle, l’extracteur essaye de convertir ce
qu’il y a dans le tampon en un int (retour en 2)
Solution :
Appeler la méthode fail () de la classe istream pour savoir si
l’extraction a pu se faire.
…
if (cin.fail ())
{
cout << "echec de lecture" << endl;
string Buf;
getline (cin, Buf);
}
même exécution
même résultat !!!
C.2 Restauration
Pour pourvoir restaurer un flux positionné dans un état fail (), il faut
appeler la méthode clear () sur ce flux.
…
if (cin.fail ())
{
cout << "echec de lecture" << endl;
cin.clear (); = remise en état du flux
string Buf;
getline (cin, Buf);
}
Taper un entier suivi de <CR> : x10
echec de lecture
Taper un entier suivi de <CR> : 10
i = 10
Taper un entier suivi de <CR> : Ctrl+D
Problème : tous les entiers sur la ligne après le caractère invalide sont perdus.
…
if (cin.fail ())
{
cout << "echec de lecture" << endl;
cin.clear ();
char c;
for (c = cin.peek (); !isdigit (c); c = cin.peek ())
cin.get ();
}
string email;
cout << "Entrer votre email : ";
cin >> email;
cout << email << endl;
unsigned age;
cout << "Entrer votre age : ";
cin >> age;
cout << age << endl;
string email;
cout << "Entrer votre email : "; On ignore tout le reste du flux
cin >> email;
cout << email << endl;
cin.ignore (numeric_limits<streamsize>::max(), '\n');
unsigned age;
cout << "Entrer votre age : ";
cin >> age;
cout << age << endl;
Plan
A. Flux de sortie
B. Flux d’entrée
F. Classe stringstream
D. Positionnement dans
un flux
On appelle la méthode seekg () de la classe istream de profil
~void seekg (streamoff, ios_base::seekdir);
at end
if (0 == ios.tellg()) return 0;
for (char c; ; )
{
cout << ios.tellg();
ios.get (c) ;
cout << ' ' << c << '\n'; 5 5
4 4
if (1 == ios.tellg()) break; 3 3
ios.seekg (-2, ios_base::cur); 2 2
} 1 1
return 0; 0 0
Plan
A. Flux de sortie
B. Flux d’entrée
F. Classe stringstream
E. Etat d’un flux
Un flux peut avoir 4 états :
• eof () : fin de fichier;
• fail () : erreur E/S
• bad () : erreur sur le flux (propagation d’exception, …)
• good () : le flux est OK
Nouveau profil:
ifstream getline (ifstream &, string &);
Lecture jusqu’à la fin d’un fichier :
string str;
for (getline (ifs, str); !ifs.eof (); getline (ifs, str))
Manipulate (str);
B. Flux d’entrée
F. Classe stringstream
F. Classe stringstream
Pour éviter la gestion des erreurs des E/S des utilisateurs, certains langages
(Java, C#, …) ne permettent que de saisir des chaines de caractères. Ensuite
il faut convertir la chaine vers le type en question (par exemple un int).
Exemple C++ :
int x;
cin >> x;
Le flux peut être dans un état invalide
Exemple C#:
int x;
string str = Console.ReadLine ();
if (Int32.TryParse (str, out x));
…
Le flux est toujours dans un état valide
Se comportent
comme des strings et
comme des streams !!!
#include <sstream>
ostringstream ostr;
ostr << "L'expr 0 == 1 est "
<< boolalpha << (0 == 1) << '\n';
cout << ostr.str(); ou
string S = ostr.str() + "..."; renvoie une copie de la
chaîne
Les manipulateurs marchent
comment transformer un nombre en string ?
par injection :
#include <sstream>
char C;
for (istr.get (C); ! istr.eof(); istr.get (C))
cout << C;
for (int Val; Nombres >> Val; ) cout << Val << '\t';
affiche :
1 2 3 4 5
Autre utilisation
Port-Saguenay 158 627 456 348 327 350 162 304 327 92 308 0
Port-Menier 152 330 200 107 83 60 147 487 79 293 0
Pointe-au-Pic 126 595 424 355 303 318 131 208 303 0
Percé 191 331 140 28 25 128 194 511 0
string Str;
getline (cin, Str);