On peut lire et écrire des données de type simple (booléens, caractères,
types entiers et flottants) et des chaînes de type string sur
un flot à l'aide des opérateurs >>
et <<
: le premier
argument est un flot, le second argument la donnée à lire ou à écrire.
Les opérations de lecture s'attendent à ce que les données soient
séparées par des espaces (blancs, tabulations, retour à la ligne).
int i; double x; string s; in >> i >> x >> s; out << "pi = " << 4 * atan(1.0);
Ces lectures et écritures en cascade sont possibles parce que ces
opérateurs sont associés de gauche à droite : in >> i >> x >> s
signifie ((in
>>
i)
>>
x)
>> s
. Cette syntaxe impose que le
résultat de l'opérateur >>
soit une référence à un flot, de
sorte que ce résultat puisse à son tour être l'argument gauche d'un
autre >>
.
L'opération de lecture peut échouer si les caractères lus ne
représentent pas la donnée attendue. Par exemple, si i est une
variable de type int, l'opération in >> i
échoue si
elle tente de lire les caractères 3.14, dès qu'elle rencontre
le '.' qui ne peut figurer dans l'écriture d'un entier : le
dernier caractère lu est le 3, les caractères suivants pourront
être lus par un autre >>
. On peut déterminer si une lecture a
réussi à l'aide de la méthode bool good() :
istream& in = cin >> i; // in est le flot après lecture de i cout << in.good() << "\n"; // 1 si la lecture précédente a réussi
Une opération de lecture appliquée à un flot sur lequel good() retournerait false n'est pas exécutée, de sorte que le second argument n'est pas modifié dans ce cas. C'est cette méthode qui est invoquée, quand un flot est testé dans une expression conditionnelle. On peut l'utiliser pour copier un flot d'entiers sur un autre, le test permettant de détecter la fin du fichier :
void copie_int(ifstream& in, ofstream& out) { int i; while (in >> i) out << i << endl; }
Il faut savoir que, pour des raisons d'efficacité, une écriture sur un flot n'implique pas nécessairement une écriture immédiate sur la cible du flot : l'écriture peut se faire d'abord sur un tampon qui est ultérieurement vidé vers la cible. La méthode ostream& flush() permet de provoquer le vidage du tampon associé au flot, pour s'assurer de l'écriture immédiate d'une donnée sur la cible :
cout.flush(); cin.synch();Il est cependant inutile d'effectuer ce vidage après l'écriture de
\n
, si le tampon est plein, ou juste avant la fermeture d'un flot
: dans tous ces cas, le vidage est automatique. En lecture, le vidage se
fait à l'aide de la méthode sync().
Pour lire des fichiers textuels, normalement composés de lignes
terminées par '\n'
, il est commode d'utiliser la fonction
istream& getline(istream&, string&), qui lit une ligne entière,
sauf le caractère de fin de ligne ; par exemple :
string ligne; getline(cin, ligne);