
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.
15.1. Manipulation de la console (8)
15.2. Manipulation des fichiers (14)
15.3. Repr�sentation - Formatage (4)
- � quoi sert std::endl ?
- Comment utiliser les flux pour afficher ou saisir mes objets ?
- Comment effacer le contenu d'un ostringstream ?
- [Exemple] Comment convertir un tableau en cha�ne ?
- Comment rediriger l'entr�e ou la sortie standard ?
- Comment utiliser les it�rateurs de flux ?
- Comment fonctionne le test de r�ussite de conversion if ( str >> num ) ?
- Qu'est-ce qu'un tampon, un buffer ?
- Que signifie vider ou purger un tampon ?
En plus de faire un retour � la ligne en ajoutant un caract�re '\n', std::endl purge le buffer de sortie et force ainsi son �criture en appelant ostream::flush() (cela a le m�me fonctionnement que la fonction fflush() du C).
Les deux lignes de code suivantes sont donc �quivalentes :
Code c++ : | S�lectionner tout |
1 2 | std::cout << "coucou" << std::endl; std::cout << "coucou\n" << std::flush; |
Il faut donc �tre prudent avec son utilisation, notamment avec les fichiers, car une op�ration de flush n'est pas gratuite. Son utilisation fr�quente peut m�me s�rieusement grever les performances en annulant tous les b�n�fices d'une �criture bufferis�e.
Pour injecter un objet de type quelconque dans un flux de sortie, il suffit de d�finir un op�rateur << prenant en param�tre le flux, ainsi que l'objet � injecter.
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 | #include <ostream> #include <string> class MaClasse { friend std::ostream& operator <<(std::ostream&, const MaClasse&); private : int Integer; std::string String; }; std::ostream& operator <<(std::ostream& Stream, const MaClasse& Obj) { Stream << Obj.Integer << " " << Obj.String; return Stream; // N'oubliez pas de renvoyer le flux, afin de pouvoir cha�ner les appels } MaClasse Obj; std::cout << "Ma classe : " << Obj << std::endl; |
Le fonctionnement est le m�me pour l'extraction de valeurs � partir d'un flux d'entr�e, via l'op�rateur >> :
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 | #include <istream> #include <string> class MaClasse { friend std::istream& operator >>(std::istream&, MaClasse&); private : int Integer; std::string String; }; std::istream& operator >>(std::istream& Stream, MaClasse& Obj) { Stream >> Obj.Integer >> Obj.String; return Stream; // N'oubliez pas de renvoyer le flux, afin de pouvoir cha�ner les appels } MaClasse Obj; std::cin >> Obj; |
Notez bien que ce genre de surcharge ne peut pas �tre membre de la classe, car cela impliquerait que l'op�rande gauche soit l'objet et non le flux.
Enfin, si vous devez g�rer l'injection et l'extraction sur une hi�rarchie d'objets polymorphes, il faudra mettre en place une petite astuce (voir

La fonction membre ostringstream::str() a deux surcharges : une sans param�tre qui renvoie le contenu du flux sous forme de string, et une autre qui accepte une cha�ne en param�tre pour r�initialiser le contenu du flux. Pour vider le flux il suffit donc d'appeler cette fonction avec comme param�tre la cha�ne vide.
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include <sstream> #include <string> std::ostringstream oss; std::string Fichier[10]; // G�n�re une suite de noms de fichiers num�rot�s de 0 � 9 for (int i = 0; i < 10; ++i) { oss.str(""); oss << "Image_" << i << ".bmp"; Fichier[i] = oss.str(); } |
De la m�me mani�re que dans Comment obtenir la repr�sentation hexad�cimale d'un entier ?, on peut obtenir la repr�sentation hexad�cimale d'un buffer de caract�res en repr�sentation hexad�cimale � l'aide du manipulateur std::hex.
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #include <algorithm> #include <iomanip> #include <sstream> #include <string> std::string array_to_string(const unsigned char* buffer, std::size_t size) { std::ostringstream oss; // Afficher en hexad�cimal et en majuscule oss << std::hex << std::uppercase; // Injecter tous les caract�res sous forme d'entiers dans le flux std::copy(buffer, buffer + size, std::ostream_iterator<int>(oss, "")); return oss.str(); } |
Si l'on souhaite personnaliser la repr�sentation hexad�cimale, on peut d�velopper la boucle de copie comme ceci :
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 | #include <algorithm> #include <iomanip> #include <sstream> #include <string> std::string array_to_string(const unsigned char* buffer, std::size_t size) { std::ostringstream oss; // Afficher en hexad�cimal et en majuscule oss << std::hex << std::uppercase; // Remplir les blancs avec des z�ros oss << std::setfill('0'); for (std::size_t i = 0; i < size; ++i) { // S�parer chaque octet par un espace if (i != 0) oss << ' '; // Afficher sa valeur hexad�cimale pr�c�d�e de "0x" // setw(2) permet de forcer l'affichage � 2 caract�res oss << "0x" << std::setw(2) << static_cast<int>(buffer[i]); } return oss.str(); } int main() { const std::size_t size = 5; const unsigned char data[size] = {0x0C, 0x10, 0xFF, 0x00, 0xDA}; std::cout << array_to_string(data, size) << '\n'; } |
0x0C 0x10 0xFF 0x00 0xDA
Afin de rediriger l'entr�e ou l'une des sorties standard (cin, cout, cerr ou clog) vers un autre flux, il suffit de r�affecter leur streambuf (le streambuf est l'objet qui fait le lien entre le flux et ce vers quoi il lit / �crit).
Afin d'acc�der au streambuf d'un flux, il faut utiliser la fonction membre rdbuf (ses deux surcharges pour �tre pr�cis) :
Code c++ : | S�lectionner tout |
1 2 3 4 5 | // R�cup�rer le streambuf d'un flux std::streambuf* std::ios::rdbuf(); // Changer le streambuf d'un flux void std::ios::rdbuf(std::streambuf*); |
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <fstream> #include <iostream> int main() { std::cout << "Affichage sur la console"<< std::endl; // Redirection de std::cout vers le fichier Toto.txt std::ofstream Out("Toto.txt"); std::streambuf* OldBuf = std::cout.rdbuf(Out.rdbuf()); std::cout << "Affichage dans Toto.txt"<< std::endl; // Restauration du streambuf initial de std::cout (affichage sur la console) std::cout.rdbuf(OldBuf); return 0; } |
� noter �galement que si vous ne souhaitez effectuer une telle redirection que ponctuellement et pour toute la dur�e de l'ex�cution, vous pouvez plus simplement utiliser une redirection au niveau de votre invite de commande (avec une syntaxe d�pendante de l'OS) :
>MonProgramme.exe > Toto.txt
La STL propose deux classes pour it�rer sur les flux : istream_iterator et ostream_iterator (d�finies dans l'en-t�te <iterator>).
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 | std::vector<int> Tab; Tab.push_back(1); Tab.push_back(3); Tab.push_back(6); // Plus besoin de boucle pour afficher les �l�ments du tableau : std::copy(Tab.begin(), Tab.end(), std::ostream_iterator<int>(std::cout, "\n")); |
Le second param�tre de l'it�rateur est simplement le d�limiteur qui sera plac� entre chaque �l�ment.
Vous pouvez �galement utiliser les stream_iterator avec des classes quelconques, pourvu que leur op�rateur << soit correctement d�fini.
Cela marche aussi dans l'autre sens : avec un std::istream_iterator vous pourrez extraire des valeurs / objets d'un flux les unes apr�s les autres, et les placer par exemple dans un tableau.
Code c++ : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | // On va extraire � partir d'un fichier, par exemple std::ifstream File("Data.txt"); // M�thode 1 : std::copy std::vector<MaClasse> Tab1; std::copy(istream_iterator<MaClasse>(File), istream_iterator<MaClasse>(), std::back_inserter(Tab1)); // std::back_inserter va remplacer les affectations par des push_back // M�thode 2 : utiliser le constructeur prenant une paire d'it�rateurs std::vector<MaClasse> Tab2(istream_iterator<MaClasse>(File), (istream_iterator<MaClasse>())); |
La paire de parenth�ses a priori inutile autour du second istream_iterator est n�cessaire : sans cela le compilateur croirait � une d�claration de fonction. Pour �viter cela vous pouvez �galement d�clarer les variables correspondant aux it�rateurs en dehors de l'appel :
Code c++ : | S�lectionner tout |
1 2 3 | istream_iterator<MaClasse> Begin(File); istream_iterator<MaClasse> End; std::vector<MaClasse> Tab2(Begin, End); |
Pour que le code suivant compile :
Code c++ : | S�lectionner tout |
1 2 3 4 5 | istringstream s( "10" ); int n; if ( s >> n ) { } |
Code c++ : | S�lectionner tout |
1 2 3 4 5 | istringstream s( "10" ); int n; if ( s.operator >>( n ) ) { } |
Le compilateur essaye alors de convertir cette r�f�rence (qui correspond � s apr�s l'appel de l'op�rateur >>, donc apr�s avoir tent� la conversion en int) en bool�en. istream ne d�finit pas d'op�rateur de conversion vers bool, mais une conversion implicite est possible gr�ce � l'op�rateur operator void*(). Ce dernier retourne un pointeur nul si les indicateurs d'�chec du flux sont positionn�s, ce qui est le cas en cas d'�chec de conversion. L'ensemble du processus effectu� par le compilateur correspond donc aux appels explicites suivants :
Code c++ : | S�lectionner tout |
1 2 3 4 5 | istringstream s( "10" ); int n; if ( s.operator >>( n ).operator void*() != 0 ) { } |
Un tampon (buffer en anglais) est un moyen d'assouplir l'utilisation d'un syst�me lent par un autre plus rapide.
Au lieu d'acc�der directement au syst�me lent, l'utilisateur va simplement compl�ter une liste de demandes en attente.
Ainsi, l'utilisateur n'a plus besoin d'attendre le traitement, et peut poursuivre son activit�.
En C++, le flux de sortie standard, std::cout, utilise comme tampon un tableau de caract�res (cach� dans la biblioth�que standard).
Cela, parce que l'image affich�e � l'�cran n'est pas disponible en permanence. Il en est de m�me avec un fichier.
On retrouve cette id�e avec les files d'attente d'un p�age, ou celles � l'entr�e d'un routeur.
Le m�canisme d'un tampon est assez simple :
� chaque occasion qui se pr�sente, le syst�me lent regarde si le tampon contient au moins une entr�e. Si c'est le cas, il en retire une et la traite.
Laquelle est tir�e en premier d�pend du besoin, mais c'est souvent la plus ancienne.
En g�n�ral, un tampon est limit� en taille. Quand il est plein, deux traitements sont possibles : rejeter les nouvelles demandes ou mettre en attente l'utilisateur.
Un routeur rejette les demandes, ce qui provoque des messages d'erreur tels que "Cette page ne r�pond pas."
Le p�age va plutot prendre son temps, l'utilisateur se retrouve � attendre (c'est un bouchon).
Les tampons fonctionnent bien quand les demandes arrivent en rafales : une s�rie de demandes, puis rien pendant un temps largement suffisant pour toutes les traiter.
Un tampon permet de r�duire l'impact de la lenteur d'acc�s � une ressource, mais d�synchronise celle-ci de l'utilisateur.
Purger un tampon (flush en anglais) consiste � demander � la ressource de traiter toutes les demandes et attendre qu'il l'ait fait.
Cela permet de resynchroniser l'ensemble, par exemple pour s'assurer que le syst�me lent est bien dans l'�tat demand�.
Cela signifie ralentir le programme, certes, mais c'est un bon moyen de synchroniser des choses qui ne le sont pas de base, comme le flux de sortie standard et celui de saisie, ou encore les flux de sortie standard et d'erreur: std::cout et std::cerr.
En C++, il y a deux manipulateurs de flux de sortie qui sont utilisables pour cela: std::flush et std::endl.
La seule diff�rence entre les deux, c'est que endl ajoute un retour � la ligne avant de purger le buffer.
Ainsi cout << 2 << flush affiche 2 imm�diatement, parce que cela ajoute 2 au bout du buffer puis purge celui-ci.
De m�me, cout << endl se comporte comme cout << '\n' << flush.
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 � 2025 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.