Récupérer d'une erreur de lecture sur un flux

Contenu du snippet

Le langage C++, comme la plupart des langages de programmation contemporains, permet de lire et d'écrire de et sur des flux de données, ce qui lui permet d'abstraire les accès aux périphériques comme le clavier, la souris ou un écran console de la même manière que celle utilisée pour abstraire l'accès à un fichier.

Le flux en entrée le plus typique avec C++, surtout en début de formation, est l'objet permettant l'asbtraction de l'entrée standard et nommé std::cin. Cette rubrique utilisera std::cin comme référence mais pourrait s'appliquer à tout dérivé de std::istream (si cette dernière phrase ne vous dit rien, ce n'est sans doute qu'une question de temps).

Si on désire reprendre la lecture tant et aussi longtemps qu'une valeur à la fois valide et située entre les bornes n'aura pas été saisie, il faudra remettre le flux en entrée sur ses pattes à chaque erreur. En effet, une entrée intraduisible sur un flux d'entrée a deux conséquences:

elle met le flux en étant d'échec (la méthode fail() retourne true); et
le contenu impossible à traduire reste coincé dans le flux (au cas où on en aurait besoin).
Si on veut lire un entier, comme c'est le cas dans notre exemple, et si le contenu de std::cin est impossible à traduire en entier, alors:

il faut oublier l'échec lors de la traduction, ce qu'on fait en sollicitant la méthode clear() du flux; et
il faut vider le flux des données intraduisibles avant de poursuivre--ou, en d'autres termes, ignorer ce qui y traîne encore, à l'aide de la méthode ignore() du flux.

Source / Exemple :


#include <iostream> // std::cin, std::cout, std::endl

int main ()
{
   const int BORNE_MIN = 1,
             BORNE_MAX = 10;
   std::cout << "Entrez un entier se situant entre "
             << BORNE_MIN
             << " et "
             << BORNE_MAX
             << " inclusivement. Votre choix: ";
   int ValeurLue;
   while (!(std::cin >> ValeurLue) || ValeurLue < BORNE_MIN || ValeurLue > BORNE_MAX)
   {
      std::cin.clear ();  // on oublie l'échec et on poursuit
      std::cin.ignore (); // ignorer le contenu déjà lu
      std::cout << "Erreur. Je veux un entier se situant entre "
                << BORNE_MIN
                << " et "
                << BORNE_MAX
                << " inclusivement. Votre choix: ";
   }
   std::cout << "La valeur choisie est: "
             << ValeurLue
             << "; merci!"
             << std::endl;
}

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.