Programmation C/Entrées/sorties
Les fonctions d'entrées/sorties sont celles qui vous permettent de communiquer avec l'extérieur, c'est-à-dire, la console, les fichiers, tubes de communication, socket IP, etc ... Pour utiliser ces fonctions, il faut inclure l'en-tête codice_1, avec la directive d'inclusion :
Manipulation de fichiers.
En C, les fichiers ouverts sont représentés par le type codice_2, qui est un type "opaque" : on ne connaît pas la nature réelle du type, mais seulement des fonctions pour le manipuler. Ainsi, on ne peut créer directement de variables de type codice_2, seules les fonctions de la bibliothèque standard peuvent créer une variable de ce type, lors de l'ouverture d'un fichier. Ces données sont donc uniquement manipulées par des pointeurs de type codice_4.
Ce type est un "flux" de données, qui représente des fichiers, mais peut aussi représenter toute autre source ou destination de données. L'en-tête codice_1 fournit trois flux que l'on peut utiliser « directement » :
Souvent, "l'entrée standard" envoie au programme les données issues du clavier, et les "sorties standard" envoient les données que le programme génère à l'écran. Mais d'où viennent et où vont ces données dépend étroitement du contexte et de l'implémentation ; la bibliothèque standard fournit le type codice_2 comme une abstraction pour les manipuler tous de la même manière, ce qui libère le programmeur de certains détails d'implémentations, et permet à l'utilisateur d'un programme d'employer (suivant son implémentation) aussi bien son clavier qu'un fichier comme entrée standard.
Ouverture.
FILE * fopen(const char * restrict chemin, const char * restrict mode)
Ouvre le fichier désigné par le "chemin" et renvoie un nouveau flux de données pointant sur ce fichier. L'argument "mode" est une chaîne de caractères désignant la manière dont on veut ouvrir le fichier :
Lorsqu'un fichier est ouvert en écriture, les données qui sont envoyées dans le flux ne sont pas directement écrites sur le disque. Elles sont stockées dans un "tampon", une zone mémoire de taille finie. Lorsque le tampon est plein, les données sont purgées ("flush"), elles sont écrites dans le fichier. Ce mécanisme permet de limiter les accès au système de fichiers et donc d'accélérer les opérations sur les fichiers.
À noter une particularité des systèmes Microsoft Windows, est de traiter différemment les fichiers textes, des fichiers binaires. Sur ces systèmes, le caractère de saut de ligne est en fait composé de deux caractères (CR, puis LF, de code ASCII respectif 13 et 10, ou codice_10 et codice_11 écrit sous forme de caractère C). Lorsqu'un fichier est ouvert en mode texte (mode par défaut), toute séquence CRLF lue depuis le fichier sera convertie en LF, et tout caractère LF écrit sera en fait précédé d'un caractère CR supplémentaire. Si le fichier est ouvert en mode binaire, aucune conversion n'aura lieu.
Ce genre de comportement issu d'un autre âge, est en fait bien plus agaçant que réellement utile. Le premier réflexe est en général de désactiver ce parasitage des entrées/sorties, tant il est pénible. Pour cela deux cas de figure :
Fermeture.
int fclose(FILE * flux);
Dissocie le "flux" du fichier auquel il avait été associé par codice_12. Si le fichier était ouvert en écriture, le tampon est vidé. Cette fonction renvoie 0 si la fermeture s'est bien passée (notamment la purge des zones en écriture), ou codice_13 en cas d'erreur (voir le paragraphe sur la gestion d'erreurs).
Suppression.
int remove(const char * path);
Supprime le fichier ou le répertoire nommé 'codice_14'. La fonction renvoie 0 en cas de réussite et une valeur non nulle en cas d'erreur, ce qui peut inclure :
Renommage (ou déplacement).
int rename(const char * ancien_nom, const char * nouveau_nom);
Cette fonction permet de renommer l'ancien fichier ou répertoire nommé 'codice_15' par 'codice_16'. Elle peut aussi servir a déplacer un fichier, en mettant le chemin absolu ou relatif du nouvel emplacement dans 'codice_16'.
La fonction renvoie 0 si elle réussit et une valeur non nulle en cas d'erreur.
Les causes d'erreur dépendent de l'implémentation, et peuvent être:
Déplacement dans le flux.
int fseek( FILE * flux, long deplacement, int methode );
long ftell( FILE * flux );
codice_18 permet de se déplacer à une position arbitraire dans un "flux". Cette fonction renvoie 0 en cas de réussite.
"deplacement" indique le nombre d'octet à avancer (ou reculer si ce nombre est négatif) à partir du point de référence ("methode") :
codice_19 permet de savoir à quelle position se trouve le curseur (ce depuis le début).
En cas d'erreur, ces deux fonctions renvoient -1.
Plusieurs remarques peuvent être faites sur ces deux fonctions :
Synchronisation.
int fflush ( FILE *flux );
Cette fonction purge toutes les zones mémoires en attente d'écriture et renvoie 0 si tout s'est bien passé, ou codice_13 en cas d'erreur. Si codice_29 est passé comme argument, tous les flux ouverts en écriture seront purgés.
À noter que cette fonction ne permet pas de purger les flux ouverts en lecture (Pour répondre à une question du genre « Voulez-vous effacer ce fichier (o/n) ? » ). Une instruction de ce genre sera au mieux ignorée, et au pire provoquera un comportement indéterminé :
fflush( stdin );
Pour effectuer une purge des flux ouverts en lecture, il faut passer par des appels systèmes normalisés dans d'autres documents (POSIX), mais dont la disponibilité est en général dépendante du système d'exploitation.
Sorties formatées.
int printf(const char * restrict format, ...);
int fprintf(FILE * restrict flux, const char * restrict format, ...);
int sprintf(char * restrict chaine, const char * restrict format, ...);
int snprintf(char * restrict chaine, size_t taille, const char * restrict format, ...);
Ces fonctions permettent d'écrire des données formatées dans :
En retour elle indique le nombre de caractères qui a été écrit à l'écran, dans le flux ou la zone mémoire (caractère nul non compris pour codice_32).
Bien que cela ait déjà été traité dans la section dédiée aux chaînes de caractères, il faut faire très attention avec la fonction codice_34. Dans la mesure où la fonction n'a aucune idée de la taille de la zone mémoire transmise, il faut s'assurer qu'il n'y aura pas de débordements. Mieux vaut donc utiliser la fonction codice_35, qui permet de limiter explicitement le nombre de caractère à écrire.
À noter que codice_35 devrait toujours retourner la taille de la chaine à écrire, indépendamment de la limite fixée par le paramètre codice_37. Le conditionnel reste de mise, car beaucoup d'implémentations de cette fonction se limitent à retourner le nombre de caractères "écrit", c'est à dire en s'arrêtant à la limite le cas échéant.
Type de conversion.
Mis à part l'« endroit » où écrivent les fonctions, elles fonctionnent exactement de la même manière, nous allons donc décrire leur fonctionnement en prenant l'exemple de codice_30.
L'argument "format" est une chaîne de caractères qui détermine ce qui sera affiché par codice_30 et sous quelle forme. Cette chaîne est composée de texte « normal » et de séquences de contrôle permettant d'inclure des variables dans la sortie. Les séquences de contrôle commencent par le caractère « % » suivi d'un caractère parmi :
Contraindre la largeur des champs.
Une autre fonctionnalité intéressante du spécificateur de format est que l'on peut spécifier sur combien de caractère les champs seront alignés. Cette option se place entre le '%' et le format de conversion et se compose d'un signe '-' optionnel suivit d'un nombre, éventuellement d'un point et d'un autre nombre (codice_46). Par exemple: codice_47.
Le premier nombre indique sur combien de caractère se fera l'alignement. Si la valeur convertie est plus petite, elle sera alignée sur la droite, ou la gauche si un signe moins est présent au début. Si la valeur est plus grande que la largeur spécifiée, le contenu s'étendra au-delà, décalant tout l'alignement. Pour éviter ça, on peut spécifier un deuxième nombre au delà duquel le contenu sera tronqué. Quelques exemples:
printf("%10s", "Salut"); /* " Salut" */
printf("%-10s", "Salut"); /* "Salut " */
printf("%10s", "Salut tout le monde"); /* "Salut tout le monde" */
printf("%10.10s", "Salut tout le monde"); /* "Salut tout" */
Contraindre la largeur des champs numériques.
On peut aussi paramétrer la largeur du champ, en spécifiant codice_48 à la place. Dans ce cas, en plus de la valeur à afficher (i.e. 1234), il faut donner avant un entier de type codice_24 pour dire sur combien de caractères l'alignement se fera (i.e. 10) :
printf("%-*d", 10, 1234); /* "1234 " */
printf("%*d", 10, 1234); /* " 1234" */
À noter que pour le formatage de nombres entiers, la limite « dure » du spécificateur de format est sans effet, pour éviter de fâcheuses erreurs d'interprétation. On peut toutefois utiliser les extensions suivantes :
Exemples :
printf("%+010d", 543); /* "+000000543" */
printf("%-+10d", 543); /* "+543 " */
printf("%-+10d", 1234567890); /* "+1234567890" */
printf("%-+10.10d", 1234567890); /* "+1234567890" */
printf("%08x", 543); /* "0000021f" */
Contraindre la largeur des champs réels.
Pour les réels, la limite « dure » sert en fait à indiquer la précision voulue après la virgule :
printf("%f", 3.1415926535); /* "3.141593" */
printf("%.8f", 3.1415926535); /* "3.14159265" */
Spécifier la taille de l'objet.
Par défaut, les entiers sont présupposés être de type codice_24, les réels de type codice_41 et les chaînes de caractères de type codice_55. Il arrive toutefois que les types soient plus grands (et non plus petits à cause de la promotion des types, c.f. paragraphes opérateurs et fonction à nombre variable d'arguments), le spécificateur de format permet donc d'indiquer la taille de l'objet en ajoutant les attributs suivants "avant" le caractère de conversion :
Pour résumer les types d'arguments attendus en fonction de l'indicateur de taille et du type de conversion :
codice_65 et codice_66 sont des nouveautés de C99. On notera qu'avec l'attribut codice_65 et les formats codice_68, codice_69, codice_70, codice_71, codice_72 ou codice_73, le type est codice_74 et non codice_75. En effet, comme vu dans le chapitre Types de base, le type codice_75 peut être signé ou non, suivant l'implémentation. Ici, on est sûr de manipuler le type caractère signé.
Quelques exemples :
signed char nb;
printf("%d%hhn", 12345, &nb); /* Affichage de "12345" et nb vaudra 5 */
printf("%ls", L"Hello world!"); /* "Hello world!" */
Arguments positionnels.
Il s'agit d'une fonctionnalité relativement peu utilisée, mais qui peut s'avérer très utile dans le cadre d'une application internationalisée. Considérez le code suivant (tiré du manuel de codice_77) :
printf( gettext("La chaine '%s' a %zu caractères\n"), s, strlen(s) );
codice_77 est un ensemble de fonctions permettant de manipuler des catalogues de langues. La principale fonction de cette bibliothèque est justement codice_79, qui en fonction d'une chaîne de caractère retourne la chaîne traduite selon la locale en cours (où celle passée en argument si rien n'a été trouvé).
Une traduction en allemand du message précédant, pourrait donner :
codice_80
On remarque d'emblée que les spécificateurs de format sont inversés par rapport à la chaîne originale. Or l'ordre des arguments passés à la fonction codice_81 sera toujours le même. Il est quand même possible de s'en sortir avec les arguments positionnels. Pour cela, il suffit d'ajouter à la suite du caractère codice_82 un nombre, suivi d'un signe codice_83. Ce nombre représente le numéro de l'argument à utiliser pour le spécificateur, en commençant à partir de 1. Un petit exemple :
char * s = "Bla bla";
printf("La chaine %2$s a %1$zu caractères\n", strlen(s), s); /* "La chaîne Bla bla a 7 caractères" */
À noter que si un des arguments utilise la référence positionnelle, tous les autres arguments devront faire évidemment de même, sous peine d'avoir un comportement imprévisible.
Écriture par bloc ou par ligne.
Il s'agit d'une fonctionnalité relativement pointue de la bibliothèque codice_84, mais qui peut expliquer certains comportement en apparence étrange (notamment avec les systèmes POSIX). Les réglages par défaut étant bien faits, il y a peu de chance pour que vous ayez à vous soucier de cet aspect, si ce n'est à titre de curiosité.
En règle générale les flux de sortie ouvert par via la bibliothèque codice_84 sont gérés par bloc, ce qui veut dire qu'une "écriture" (via codice_81, codice_87 ou codice_88) ne sera pas systématiquement répercutée dans le fichier associé.
Cela dépend en fait du type d'objet sur lequel les écritures se font :
C'est ce qui fait qu'un programme affichant des messages à intervalle régulier (genre une seconde), affichent ces lignes une à une sur un terminal, et par bloc de plusieurs lignes lorsqu'on redirige sa sortie vers un programme de mise en page (comme codice_90), avec une latence qui peut s'avérer gênante. C'est ce qui fait aussi qu'une instruction comme codice_91 n'affichera en général rien, car il n'y a pas de retour à la ligne.
En fait ce comportement peut être explicitement réglé, avec cette fonction :
int setvbuf(FILE * restrict flux, char * restrict mem, int mode, size_t taille);
Cette fonction doit être appelée juste après l'ouverture du flux et avant la première écriture. Les arguments ont la signification suivante :
La fonction codice_103 renvoie 0 si elle réussit, et une valeur différente de zéro dans le cas contraire (en général le paramètre codice_98 est invalide).
Cette fonctionnalité peut être intéressante pour les programmes générant des messages sporadiques. Il peut effectivement s'écouler un temps arbitrairement long avant que le bloc mémoire soit plein, si cette commande est redirigée vers un autre programme, ce qui peut s'avérer assez dramatique pour des messages signalant une avarie grave. Dans ce cas, il est préférable de forcer l'écriture par ligne (ou immédiate), plutôt que de faire suivre systématiquement chaque écriture de ligne par un appel à codice_105, avec tous les risques d'oubli que cela comporte.
Quelques remarques pour finir.
La famille de fonctions codice_81 permet donc de couvrir un large éventail de besoins, au prix d'une pléthore d'options pas toujours faciles à retenir.
Il faut aussi faire attention au fait que certaines implémentations de codice_81 tiennent compte de la localisation pour les conversions des nombres réels (virgule ou point comme séparateur décimal, espace ou point comme séparateurs des milliers, etc.). Ceci peut être gênant lorsqu'on veut retraiter la sortie de la commande. Pour désactiver la localisation, on peut utiliser la fonction codice_108:
setlocale( LC_ALL, "C" );
printf( ... );
setlocale( LC_ALL, "" );
Entrées formatées.
La bibliothèque codice_84 propose quelques fonctions très puissantes pour saisir des données depuis un flux quelconque. Le comportement de certaines fonctions (codice_110 notamment) peut paraître surprenant de prime abord, mais s'éclaircira à la lumière des explications suivantes.
int scanf(const char * restrict format, ...);
int fscanf(FILE * restrict flux, const char * restrict format, ...);
int sscanf(const char * restrict chaine, const char * restrict format, ...);
Ces trois fonctions permettent de lire des données formatées provenant de :
L'argument "format" ressemble aux règles d'écriture de la famille de fonction codice_30, cependant les arguments qui suivent ne sont plus des variables d'entrée mais des variables de sortie (ie : l'appel à codice_110 va modifier leur valeur, il faut donc passer une référence).
Ces fonctions retournent le nombre d'arguments correctement lus depuis le format, qui peut être inférieur ou égal au nombre de spécificateurs de format, et même nul.
Format de conversion.
Les fonctions codice_116 analysent le spécificateur de format et les données d'entrée, en les comparant caractère à caractère et s'arrêtant lorsqu'il y en a un qui ne correspond pas. À noter que les blancs (espaces, tabulations et retour à la ligne) dans le spécificateur de format ont une signification spéciale : à un blanc de la chaîne "format" peut correspondre un nombre quelconque de blanc dans les données d'entrée, y compris aucun. D'autres part, il est possible d'insérer des séquences spéciales, commençant par le caractère '%' et à l'image de codice_81, pour indiquer qu'on aimerait récupérer la valeur sous la forme décrite par le caractère suivant le '%' :
Contraindre la largeur.
Comme pour la fonction codice_81, il est possible de contraindre le nombre de caractères à lire, en ajoutant ce nombre juste avant le caractère de conversion. Dans le cas des chaînes, c'est même une obligation, dans la mesure où codice_116 ne pourra pas ajuster l'espace à la volée.
Exemple :
/* Lit une chaîne de caractères entre guillemets d'au plus 127 caractères */
char tmp[128];
if (fscanf(fichier, "Config = \"%127[^\"]\"", tmp ) == 1)
 printf("L'argument associé au mot clé 'Config' est '%s'\n", tmp);
Cet exemple est plus subtil qu'il ne paraît. Il montre comment analyser une structure relativement classique de ce qui pourrait être un fichier de configuration de type "MotClé=Valeur". Ce format spécifie donc qu'on s'attend à trouver le mot clé "Config", en ignorant éventuellement les blancs initiaux, puis le caractère '=', entouré d'un nombre quelconque de blancs, éventuellement aucun. À la suite de cela, on doit avoir un guillemet ('"'), puis au plus 127 caractères autres que que les guillemets, qui seront stockés dans la zone mémoire codice_133 (qui sera terminée par 0, d'où l'allocation d'un caractère supplémentaire). Le guillemet final est là pour s'assurer, d'une part, que la longueur de la chaîne est bien inférieure à 127 caractère et, d'autre part, que le guillemet n'a pas été oublié dans le fichier.
En cas d'erreur, on peut par exemple ignorer tous les caractères jusqu'à la ligne suivante.
Ajuster le type des arguments.
On peut aussi ajuster le type des arguments en fonction des attributs de taille :
Ainsi pour lire la valeur d'un entier sur l'entrée standard, on utilisera un code tel que celui ci :
int main(void)
 int i;
 printf("Entrez un entier : ");
 scanf("%d", &i);
 printf("la variable i vaut maintenant %d\n", i);
 return 0;
Les appels à codice_30 ne sont pas indispensables à l'exécution du codice_110, mais permettent à l'utilisateur de comprendre ce qu'attend le programme (et ce qu'il fait aussi).
Conversions muettes.
La fonction codice_110 reconnaît encore un autre attribut qui permet d'effectuer la conversion, mais sans retourner la valeur dans une variable. Il s'agit du caractère étoile '*', qui remplace l'éventuel attribut de taille.
En théorie, la valeur de retour ne devrait pas tenir compte des conversions muettes.
Exemple:
int i, j;
sscanf("1 2.434e-308 2", "%d %*f %d", &i, &j); /* i vaut 1 et j vaut 2 */
Quelques remarques pour finir.
La fonction codice_116 n'est pas particulièrement adaptée pour offrir une saisie conviviale à l'utilisateur, même en peaufinant à l'extrême les spécificateurs de format. En général, il faut s'attendre à une gestion très rudimentaire du clavier, avec très peu d'espoir d'avoir ne serait-ce que les touches directionnelles pour insérer du texte à un endroit arbitraire.
Qui plus est, lors de saisie de texte, les terminaux fonctionnent en mode bloc : pour que les données soient transmises à la fonction de lecture, il faut que l'utilisateur confirme sa saisie par entrée. Même les cas les plus simple peuvent poser problèmes. Par exemple, il arrive souvent qu'on ne veuille saisir qu'un caractère pour répondre à une question du genre codice_138, avant d'écraser un fichier. Utiliser une des fonctions de saisie nécessite de saisir d'abord un caractère, ensuite de valider avec la touche "entrée". Ce qui peut non seulement être très pénible s'il y a beaucoup de questions, mais aussi "risqué" si on ne lit les caractères qu'un à un. En effet, dans ce dernier cas, si l'utilisateur entre une chaîne de plusieurs caractères, puis valide sa saisie, les caractères non lus seront disponibles pour des lectures ultérieures, répondant de ce fait automatiquement aux questions du même type.
Il s'agit en fait de deux opérations en apparence simples, mais impossible à réaliser avec la bibliothèque C standard :
Ces fonctionnalités sont hélas le domaine de la gestion des terminaux POSIX et spécifiées dans la norme du même nom.
On l'aura compris, cette famille de fonction est plus à l'aise pour traiter des fichiers, ou tout objet nécessitant le moins d'interaction possible avec l'utilisateur. Néanmoins dans les cas les plus simples, ce sera toujours un pis-aller.
À noter, que contrairement à la famille de fonction codice_81, codice_116 n'est pas sensible à la localisation pour la saisie de nombres réels.
Entrées non formatées.
Pour saisir des chaînes de caractères indépendamment de leur contenu, on peut utiliser les fonctions suivantes :
char * fgets(char * restrict chaine, int taille_max, FILE * restrict flux);
int fgetc( FILE * restrict flux);
int ungetc( int octet, FILE * flux );
La fonction codice_141 permet de saisir une ligne complète dans la zone mémoire spécifiée, en évitant tout débordement. Si la ligne peut être contenue dans le bloc, elle contiendra le caractère de saut de ligne (codice_11), en plus du caractère nul. Dans le cas contraire, la ligne sera tronquée, et la suite de la ligne sera obtenue à l'appel suivant. Si la fonction a pu lire au moins un caractère, elle retournera la chaîne transmise en premier argument, ou codice_29 s'il n'y a plus rien à lire.
Un exemple de lecture de ligne arbitrairement longue est fournie dans le livre Exercices en langage C (énoncé et solution).
La fonction codice_144 permet de ne saisir qu'un caractère depuis le flux spécifié. À noter que la fonction renvoie bien un entier de type codice_24 et non de type codice_75, car en cas d'erreur (y compris la fin de fichier), cette fonction renvoie codice_13 (défini à -1 en général).
À noter que cette fonction est incapable de traiter des fichiers mixtes (binaire et texte) depuis un descripteur en mode caractère (accès séquentiel). D'une part la fonction ne renvoyant pas le nombre d'octets lus (ce qui aurait facilement réglé le problème) et d'autre part, ftell() ne fonctionnant pas sur de tels descripteurs, il faudra reprogrammer codice_148 pour gérer ce cas de figure.
Entrées/sorties brutes.
Les fonctions suivantes permettent d'écrire ou de lire des quantités arbitraires de données depuis un flux. Il faut faire attention à la portabilité de ces opérations, notamment lorsque le flux est un fichier. Dans la mesure où lire et écrire des structures binaires depuis un fichier nécessite de gérer l'alignement, le bourrage, l'ordre des octets pour les entiers ("big endian", "little endian") et le format pour les réels, il est souvent infiniment plus simple de passer par un format texte.
Sortie.
size_t fwrite(const void * buffer, size_t taille, size_t nombre, FILE * flux);
Entrée.
size_t fread(void * buffer, size_t taille, size_t nombre, FILE * flux);
Lit "nombre" éléments, chacun de taille "taille", à partir du "flux" et stocke le résultat dans le "buffer". Renvoie le nombre d'éléments correctement lus.
Gestion des erreurs.
Qui dit entrées/sorties dit forcément une pléthore de cas d'erreurs à gérer. C'est souvent à ce niveau que se distinguent les « bonnes » applications des autres : fournir un comportement cohérent face à ces situations exceptionnelles. Dans la description des fonctions précédentes, il est fait mention que, en cas d'erreur, un code spécial est retourné par la fonction. De plus, on dispose de la fonction codice_149, qui permet de savoir si une erreur a été déclenchée sur un fichier lors d'un appel antérieur à une fonction de la bibliothèque standard.
Si ces informations permettent de savoir s'il y a eu une erreur, elles ne suffisent pas à connaître la cause de l'erreur. Pour cela, la bibliothèque codice_84 repose sur la variable globale "errno", dont l'utilisation est décrite dans le chapitre sur la gestion d'erreur.