Les fonctions d'entrée / sortie de base.
Nous avons distingué au début de ce chapitre les programmes graphiques, qui traitent les événements qu'ils reçoivent du système sous la forme de messages, des autres programmes, qui reçoivent les données à traiter et écrivent leurs résultats sur les flux d'entrée / sortie standards. Les notions de flux d'entrée / sortie standards n'ont pas été définies plus en détail à ce moment, et il est temps à présent de pallier cette lacune.
Généralités sur les flux d'entrée / sortie en C.
Un "flux" est une notion informatique qui permet de représenter un flot de données séquentielles en provenance d'une source de données ou à destination d'une autre partie du système. Les flux sont utilisés pour uniformiser la manière dont les programmes travaillent avec les données, et donc pour simplifier leur programmation. Les fichiers constituent un bon exemple de flux, mais ce n'est pas le seul type de flux existant : on peut traiter un flux de données provenant d'un réseau, d'un tampon mémoire ou de toute autre source de données ou partie du système permettant de traiter les données séquentiellement.
Sur quasiment tous les systèmes d'exploitation, les programmes disposent dès leur lancement de trois flux d'entrée / sortie standards. Généralement, le flux d'entrée standard est associé au flux de données provenant d'un terminal, et le flux de sortie standard à la console de ce terminal. Ainsi, les données que l'utilisateur saisit au clavier peuvent être lues par les programmes sur leur flux d'entrée standard, et ils peuvent afficher leurs résultats à l'écran en écrivant simplement sur leur flux de sortie standard. Le troisième flux standard est le flux d'erreur standard qui, par défaut, est également associé à l'écran, et sur lequel le programme peut écrire tous les messages d'erreur qu'il désire.
Note : La plupart des systèmes permettent de rediriger les flux standards des programmes afin de les faire travailler sur des données provenant d'une autre source de données que le clavier, ou, par exemple, de leur faire enregistrer leurs résultats dans un fichier. Il est même courant de réaliser des « pipelines » de programmes, où les résultats de l'un sont envoyés dans le flux d'entrée standard de l'autre, et ainsi de suite. Ces suites de programmes sont également appelés des "tubes" en français.
La manière de réaliser les redirections des flux standards dépend des systèmes d'exploitation et de leurs interfaces utilisateurs. De plus, les programmes doivent être capables de travailler avec leurs flux d'entrée / sortie standards de manière générique, que ceux-ci soient redirigés ou non. Les techniques de redirection ne seront donc pas décrites plus en détail ici.
Vous remarquerez l'intérêt d'avoir deux flux distincts pour les résultats des programmes et leurs messages d'erreur. Si, lors d'une utilisation normale, ces deux flux se mélangent à l'écran, ce n'est pas le cas lorsque l'on redirige le flux de sortie standard. Seul le flux d'erreur standard est affiché à l'écran dans ce cas, et les messages d'erreur ne se mélangent donc pas aux résultats du programme.
On pourrait penser que les programmes graphiques ne disposent pas de flux d'entrée / sortie standards. Pourtant, c'est généralement le cas. Les événements traités par les programmes graphiques dans leur boucle de messages ne proviennent généralement pas du flux d'entrée standard, mais d'une autre source de données spécifique à chaque système. En conséquence, les programmes graphiques peuvent toujours utiliser les flux d'entrée / sortie standard si cela s'avère nécessaire. 
Afin de permettre aux programmes d'écrire sur leurs flux d'entrée / sortie standards, la bibliothèque C définit plusieurs fonctions extrêmement utiles. Les deux principales fonctions sont sans doute les fonctions codice_1 et codice_2. La fonction codice_1 (« print formatted » en anglais) permet d'afficher des données à l'écran, et codice_2 (« scan formatted ») permet de les lire à partir du clavier.
En réalité, ces fonctions ne font rien d'autre que d'appeler deux autres fonctions permettant d'écrire et de lire des données sur un fichier : les fonctions codice_5 et codice_6. Ces fonctions s'utilisent exactement de la même manière que les fonctions codice_1 et codice_2, à ceci près qu'elles prennent en premier paramètre une structure décrivant le fichier sur lequel elles travaillent. Pour les flux d'entrée / sortie standards, la bibliothèque C définit les pseudo-fichiers "stdin", "stdout" et "stderr", qui correspondent respectivement aux flux d'entrée, au flux de sortie et au flux d'erreur standards. Ainsi, tout appel à codice_2 se traduit par un appel à codice_6 sur le pseudo-fichier "stdin", et tout appel à codice_1 par un appel à codice_5 sur le pseudo-fichier "stdout".
Note : Il n'existe pas de fonction permettant d'écrire directement sur le flux d'erreur standard. Par conséquent, pour effectuer de telles écritures, il faut impérativement passer par la fonction codice_5, en lui fournissant en paramètre le pseudo-fichier "stderr".
La description des fonctions de la bibliothèque C standard dépasse de loin le cadre de ce cours. Aussi les fonctions de lecture et d'écriture sur les fichiers ne seront-elles pas décrites plus en détail ici. Seules les fonctions codice_1 et codice_2 seront présentées, car elles sont réellement indispensable pour l'écriture d'un programme C. Consultez la bibliographie si vous désirez obtenir plus de détails sur la bibliothèque C et sur toutes les fonctions qu'elle contient.
Le C++ dispose également de mécanismes de gestion des flux d'entrée / sortie qui lui sont propres. Ces mécanismes permettent de contrôler plus finement les types des données écrites et lues de et à partir des flux d'entrée / sortie standards. De plus, ils permettent de réaliser les opérations d'écriture et de lecture des données formatées de manière beaucoup plus simple. Cependant, ces mécanismes requièrent des notions objets avancées et ne seront décrits que dans les chapitres dédiés au C++. Comme il est également possible d'utiliser les fonctions codice_1 et codice_2 en C++ d'une part, et que, d'autre part, ces fonctions sont essentielles en C, la suite de cette section s'attachera à leur description. Un chapitre complet est dédié aux mécanismes de gestion des flux du C++ dans la deuxième partie de ce document. 
Les fonctions codice_1 et codice_2 sont toutes deux des fonctions à nombre de paramètres variables. Elles peuvent donc être utilisées pour effectuer des écritures et des lectures multiples en un seul appel. Afin de leur permettre de déterminer la nature des données passées dans les arguments variables, elles attendent toutes les deux en premier paramètre une chaîne de caractères descriptive des arguments suivants. Cette chaîne est appelée "chaîne de format", et elle permet de spécifier avec précision le type, la position et les options de format (précision, etc.) des données à traiter. Les deux sections suivantes décrivent la manière d'utiliser ces chaînes de format pour chacune des deux fonctions codice_1 et codice_2. 
La fonction printf.
La fonction codice_1 s'emploie comme suit :
On peut passer autant de valeurs que l'on veut, pour peu qu'elles soient toutes référencées dans la chaîne de format. Elle renvoie le nombre de caractères affichés.
La chaîne de format peut contenir du texte, mais surtout elle doit contenir autant de "formateurs" que de variables à afficher. Si ce n'est pas le cas, le programme plantera. Les formateurs sont placés dans le texte là où les valeurs des variables doivent être affichées.
La syntaxe des formateurs est la suivante :
Elle renvoie le nombre de variables lues.
Ne cherchez pas à comprendre pour l'instant la signification du symbole & se trouvant devant chacune des variables. Sachez seulement que s'il est oublié, le programme plantera.
La chaîne de format peut contenir des chaînes de caractères. Toutefois, si elle contient autre chose que des formateurs, le texte saisi par l'utilisateur devra correspondre impérativement avec les chaînes de caractères indiquées dans la chaîne de format. codice_2 cherchera à reconnaître ces chaînes, et arrêtera l'analyse à la première erreur.
La syntaxe des formateurs pour codice_2 diffère un peu de celle de ceux de codice_1 :
Seul le paramètre "largeur" change par rapport à codice_1. Il permet de spécifier le nombre maximal de caractères à prendre en compte lors de l'analyse du paramètre. Le paramètre '*' est facultatif, il indique seulement de passer la donnée entrée et de ne pas la stocker dans la variable destination. Cette variable doit quand même être présente dans la liste des paramètres de codice_2.
Note : Tout comme pour les fonctions codice_1 et codice_5, il est nécessaire d'ajouter la ligne "#include <stdio.h>" en début de fichier pour pouvoir utiliser la fonction codice_2. La signification de cette ligne sera donnée dans le chapitre traitant du préprocesseur.
En pratique, la fonction codice_2 n'analyse les caractères provenant du flux d'entrée que lorsqu'une ligne complète a été saisie. Toutefois, elle ne supprime pas du tampon de flux d'entrée le caractère de saut de ligne, si bien qu'il s'y trouvera toujours lors de l'entrée suivante. Cela n'est pas gênant si l'on n'utilise que la fonction codice_2 pour réaliser les entrées de données dans le programme, car cette fonction ignore tout simplement ces caractères de saut de ligne. En revanche, si l'on utilise une autre fonction après un appel à codice_2, il faut s'attendre à trouver ce caractère de saut de ligne dans le flux d'entrée.
La fonction codice_2 n'est pas très adaptée à la lecture des chaînes de caractères, car il n'est pas facile de contrôler la taille maximale que l'utilisateur peut saisir. C'est pour cette raison que l'on a généralement recours à la fonction codice_35, qui permet de lire une ligne sur le flux d'entrée standard et de stocker le résultat dans une chaîne de caractères fournie en premier paramètre et dont la longueur maximale est spécifiée en deuxième paramètre. Le troisième paramètre de la fonction codice_35 est le flux à partir duquel la lecture de la ligne doit être réalisée, c'est à dire généralement "stdin". L'analyse de la chaîne de caractères ainsi lue peut alors être faite avec une fonction similaire à la fonction codice_2, mais qui lit les caractères à analyser dans une chaîne de caractères au lieu de les lire directement depuis le flux d'entrée standard : la fonction codice_38. Cette fonction s'utilise exactement comme la fonction codice_2, à ceci près qu'il faut lui fournir en premier paramètre la chaîne de caractères dans laquelle se trouvent les données à interpréter. La description de ces deux fonctions dépasse le cadre de ce document et ne sera donc pas faite ici. Veuillez vous référer à la documentation de votre environnement de développement ou à la bibliographie pour plus de détails à leur sujet.