FAQ C++Consultez toutes les FAQ
Nombre d'auteurs : 34, nombre de questions : 368, dernière mise à jour : 14 novembre 2021 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.
Je tiens à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes ; les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur ou si vous souhaitez devenir rédacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Quelle est la différence entre #include <iostream.h> et #include <iostream> ?
- cout n'est pas reconnu à la compilation, que se passe-t-il ?
- Comment saisir une chaîne contenant des espaces ?
- Pourquoi std::getline ne lit-il rien, et faut-il l'exécuter deux fois pour que la ligne soit lue ?
- Comment purger le buffer clavier ?
- Comment vérifier les valeurs saisies avec cin ?
- Est-il possible de simuler une saisie clavier ?
- Comment faire une pause (attendre que l'utilisateur tape une touche) ?
Avant que le C++ ne soit normalisé, <iostream.h> était le seul fichier d'en-tête existant livré avec les compilateurs de l'époque. La normalisation ISO du C++ en 1998 a défini que <iostream> serait l'en-tête standard pour les entrées-sorties. L'absence de .h dans son nom indique qu'il s'agit désormais d'un en-tête standard, et donc que toutes ses définitions font partie de l'espace de nommage standard std. Inclure <iostream.h> est donc obsolète depuis ce temps là (techniquement parlant, <iostream.h> n'est pas obsolète car il n'a jamais fait partie du standard, mais son utilisation l'est).
Pour laisser le temps aux programmeurs de modifier leur code, les compilateurs ont fourni chacun de ces fichiers d'en-tête. <iostream.h> n'est donc encore présent que dans un but de compatibilité.
Mais maintenant certains compilateurs comme Visual C++ 7.1 (2003) ne fournissent plus que l'en-tête standard <iostream> et presque tous les autres émettent au moins un avertissement comme quoi utiliser <iostream.h> est obsolète. En le faisant, la portabilité et la compatibilité future de votre code sont menacées.
Voilà pourquoi il faut remplacer toute inclusion de <iostream.h>
Code c++ : | Sélectionner tout |
1 2 3 | #include <iostream.h> cout << "coucou" << endl; |
Code c++ : | Sélectionner tout |
1 2 3 4 | #include <iostream> using namespace std; cout << "coucou" << endl; |
Code c++ : | Sélectionner tout |
1 2 3 | #include <iostream> std::cout << "coucou" << std::endl; |
Code c++ : | Sélectionner tout |
1 2 3 4 5 | #include <iostream> using std::cout; using std::endl; cout << "coucou" << endl; |
Par exemple
Code c++ : | Sélectionner tout |
1 2 | #include <stdlib.h> #include <stdio.h> |
Code c++ : | Sélectionner tout |
1 2 | #include <cstdlib> #include <cstdio> |
cin, cout. sont des objets standards. Ils doivent être déclarés et utilisés de la façon suivante :
Code c++ : | Sélectionner tout |
1 2 3 | #include <iostream> std::cout << "Test cout" << std::endl; |
Code c++ : | Sélectionner tout |
1 2 3 4 | #include <iostream> using namespace std; cout << "Test cout" << endl; |
L'opérateur >> de saisie d'une string permet de saisir des mots et donc considère les espaces comme des séparateurs.
Pour saisir une chaîne entière contenant des espaces, il faut récupérer l'intégralité de la ligne au moyen de la fonction libre std::getline() définie dans <string> (et non pas avec la fonction membre cin.getline() qui opère sur des char *).
Code c++ : | Sélectionner tout |
1 2 | std::string chaine; std::getline( std::cin, chaine ); |
Remarque : l'implémentation de la fonction getline de la bibliothèque standard fournie par Microsoft avec Visual C++ 6.0 comporte un bug ; getline lit un caractère supplémentaire après la rencontre du délimiteur. Se référer au support Microsoft pour la correction de ce bug.
Si vous constatez ce problème, il est fort probable que vous veniez d'appeler std::getline(std::cin) juste après une lecture sur le flux avec l'opérateur d'extraction : std::cin >> (c'est parfaitement valable avec les flux fichiers également).
Ce que vous observez est normal. L'opérateur d'extraction (operator>>) consomme ce qui vient sur le flux, mais il s'arrête juste avant le premier espace blanc ou saut de ligne -- voire encore avant selon le type de la donnée à extraire et de ce qui se trouve véritablement sur le flux (ex : l'extraction d'un int depuis "125douze").
De ce fait, operator >> va s'arrêter avant le saut de ligne, et quand std::getline va vouloir extraire la ligne qui suit, en fait il va récupérer les caractères entre la position courante et la fin de la ligne avant de passer à la ligne suivante. Dans le cas d'une interaction avec l'utilisateur, une chaine vide sera obtenue, et le flux sera positionné à la ligne suivante. C'est pour cela qu'un double appel à std::getline fonctionne.
« - Donc si je comprends bien il faut appeler deux fois std::getline ? »
Seulement si vous voulez récupérer les miettes qui trainent après la dernière chose lue avec >>.
En pratique, on a le choix entre :
- un simple std::cin.get() qui marchera uniquement si ce qui suit est un saut de ligne ;
- std::cin >> std::ws qui consommera les blancs et les sauts de lignes (c'est faire ce qui est fait de manière implicite par la plupart des operator>>) ;
- ou purger le buffer clavier (cf. entrée correspondante : Comment purger le buffer clavier ?) qui fonctionnera également si des miettes trainent et que l'on préfère les ignorer.
Pour supprimer une ligne saisie par l'utilisateur qui se trouve dans le buffer d'entrée, il faut utiliser ignore().
Code c++ : | Sélectionner tout |
1 2 3 4 | #include <iostream> #include <limits> std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); |
L'opérateur >> utilisé pour la saisie permet de vérifier la validité de celle-ci via le test suivant :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <iostream> int main() { std::cout << "Entrez un nombre : "; int nombre; while ( ! ( std::cin >> nombre ) ) { std::cerr << "Erreur de saisie.\n"; } std::cout << "Le nombre entré est " << nombre << ".\n"; } |
Si vous testez cet exemple en entrant un mot au lieu d'un nombre le programme entrera dans une boucle infinie affichant « Erreur de saisie. ».
En effet, après une erreur de saisie, le flux d'entrée std::cin se retrouve dans un état invalide, et la chaîne invalide qui a provoqué l'erreur est toujours dans le buffer puisque son extraction a échoué.
Ainsi la tentative suivante échoue à nouveau, ce qui provoque une boucle infinie dans l'exemple précédent.
Il faut donc supprimer la ligne invalide du buffer et restaurer l'objet std::cin dans un état valide. Ceci est fait grâce aux deux lignes suivantes :
Code c++ : | Sélectionner tout |
1 2 | std::cin.clear(); // effacer les bits d'erreurs std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); // supprimer la ligne erronée dans le buffer |
Le code suivant corrige le précédent problème, et effectue différents tests en cas d'erreur afin d'identifier l'origine de l'échec :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <iostream> #include <limits> bool read_choice( int & N ) { std::cout << "Entrez un chiffre entre 1 et 6 : " ; while ( ! ( std::cin >> N ) || N < 1 || N > 6 ) { if ( std::cin.eof() ) { // ^D (^Z sous windows); Fin du flux d'entree ! return false; } else if ( std::cin.fail() ) { std::cout << "Saisie incorrecte, recommencez : "; std::cin.clear(); std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); } else { std::cout << "Le chiffre n'est pas entre 1 et 6, recommencez : "; } } return true; // succès } int main () { int choix; if ( read_choice( choix ) ) { std::cout << "Vous avez choisi : " << choix << '\n'; } return 0; } |
Code : | Sélectionner tout |
1 2 3 4 5 | Entrez un chiffre entre 1 et 6 : abcdef Saisie incorrecte, recommencez : -3 Le chiffre n'est pas entre 1 et 6, recommencez : 17 Le chiffre n'est pas entre 1 et 6, recommencez : 5 Vous avez choisi : 5 |
La fonction putback() du flux std::cin permet cela. Le caractère passé en paramètre de cette fonction est ajouté à la fin du flux, comme si l'utilisateur l'avait tapé au clavier.
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | #include <iostream> // simuler la saisie du mot 'Test'; std::cin.putback('T'); std::cin.putback('e'); std::cin.putback('s'); std::cin.putback('t'); |
Il n'y a pas de moyen en C++ standard pour attendre que l'utilisateur tape sur n'importe quelle touche. Ce dernier doit en effet terminer sa saisie par un retour chariot (touche entrée). On peut donc faire une pause dans son programme en invitant l'utilisateur à appuyer sur la touche entrée et en ignorant sa saisie en purgeant le buffer clavier.
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 | #include <iostream> #include <limits> int main() { std::cout << "Appuyez sur entrée pour continuer..."; std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.