FAQ C++Consultez toutes les FAQ

Nombre d'auteurs : 35, nombre de questions : 368, dernière mise à jour : 17 novembre 2018  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.


SommaireEntrées / sorties avec les fluxManipulation de la console (8)
précédent sommaire suivant
 

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;
par <iostream> et une utilisation du namespace std

Code c++ : Sélectionner tout
1
2
3
4
#include <iostream>  
using namespace std; 
  
cout << "coucou" << endl;
ou

Code c++ : Sélectionner tout
1
2
3
#include <iostream>  
  
std::cout << "coucou" << std::endl;
ou encore

Code c++ : Sélectionner tout
1
2
3
4
5
#include <iostream>  
using std::cout; 
using std::endl; 
  
cout << "coucou" << endl;
Il est en de même avec tous les fichiers d'en-tête standards en C++, y compris avec ceux de la bibliothèque standard C. Pour des raisons d'uniformisation, il faut désormais les inclure sans le .h et en préfixant leur nom par la lettre c (pour souligner le fait qu'ils sont issus du C).
Par exemple

Code c++ : Sélectionner tout
1
2
#include <stdlib.h> 
#include <stdio.h>
devient

Code c++ : Sélectionner tout
1
2
#include <cstdlib> 
#include <cstdio>

Mis à jour le 22 novembre 2004 Anomaly Aurelien.Regat-Barrel

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;
ou alors

Code c++ : Sélectionner tout
1
2
3
4
#include <iostream> 
using namespace std; 
  
cout << "Test cout" << endl;

Mis à jour le 20 avril 2003 LFE

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
3
4
5
#include <iostream> 
#include <string>  
  
std::string chaine;  
std::getline( std::cin, chaine );
À noter que si une variable a été extraite à l'aide de l'opérateur >> avant l'appel à std::getline, le caractère de fin de ligne peut subsister dans le flux d'entrée ; il peut donc être nécessaire de vider celui-ci avant d'extraire une nouvelle ligne (voir Comment purger le buffer clavier ?).

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.

Mis à jour le 3 février 2007 Laurent Gomila Luc Hermitte

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.

Mis à jour le 6 juillet 2014 Luc Hermitte

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' );
Le code précédent demande d'ignorer le maximum de caractères différents de '\n' possibles. Ce maximum possible est obtenu grâce à numeric_limits.

Mis à jour le 19 octobre 2004 Laurent Gomila LFE

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"; 
}
Pour savoir comment ce test fonctionne, lisez Comment fonctionne le test de réussite de conversion if ( str >> num ) ?.
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;  
}
Le résultat produit est le suivant :

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

Mis à jour le 22 novembre 2004 Aurelien.Regat-Barrel Luc Hermitte

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');

Mis à jour le 30 août 2004 LFE

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' ); 
}

Mis à jour le 18 avril 2005 Aurelien.Regat-Barrel

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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 © 2019 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.

 
Contacter le responsable de la rubrique C++

Partenaire : Hébergement Web