Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :

next up previous contents index
Next: Récréation Up: Les entrées-sorties Previous: Lecture et écriture par

Sous-sections

E/S formattées sur fichiers

Écriture formattée : fprintf

 

Utilisation

La fonction fprintf admet un nombre variable de paramètres. Son utilisation est la suivante :

fprintf ( flot-de-données , format , param1 , param2 , ... , paramn )

Sémantique des paramètres

-
flot-de-données est de type pointeur vers FILE. Il pointe vers le fichier sur lequel se fait l'écriture.
-
format est une chaîne de caractères qui spécifie ce qui doit être écrit.
-
parami est une expression délivrant une valeur à écrire.

Valeur rendue

La fonction fprintf retourne le nombre de caractères écrits, ou une valeur négative si il y a eu une erreur d'entrée-sortie.

Présentation

La chaîne format contient des caractères ordinaires (c'est à dire différents du caractère %) qui doivent être copiés tels quels, et des séquences d'échappement (introduites par le caractère %), décrivant la manière dont doivent être écrits les paramètres param1, param2, ... paramn.  

Si il y a moins de parami que n'en réclame le format, le comportement n'est pas défini. Si il y a davantage de parami que n'en nécessite le format, les parami en excès sont évalués, mais leur valeur est ignorée.

Les séquences d'échappement

            Une séquence d'échappement se compose des éléments suivants :

1
Un certain nombre (éventuellement zéro) d'indicateurs pouvant être les caractères suivants :

-
parami sera cadré à gauche dans son champ d'impression.

+
si parami est un nombre signé, il sera imprimé précédé du signe + ou -.

blanc
si parami est un nombre signé et si son premier caractère n'est pas un signe, on imprimera un blanc devant parami. Si on a à la fois l'indicateur + et l'indicateur blanc, ce dernier sera ignoré.

#
cet indicateur demande l'impression de parami sous une forme non standard. Pour le format o, cet indicateur force la précision à être augmentée de manière à ce que parami soit imprimé en commençant par un zéro. Pour les formats x et X, cet indicateur a pour but de faire précéder parami respectivement de 0x ou 0X, sauf si parami est nul. Pour les formats e, E, f, g et G, cet indicateur force parami à être imprimé avec un point décimal, même si il n'y a aucun chiffre après. Pour les formats g et G, cet indicateur empêche les zéros de la fin d'être enlevés. Pour les autres formats, le comportement n'est pas défini.

0
pour les formats d, i, o, u, x, X, e, E, f, g, et G cet indicateur a pour effet de compléter l'écriture de parami avec des 0 en tête, de manière à ce qu'il remplisse tout son champ d'impression. Si il y a à la fois les deux indicateurs 0 et -, l'indicateur 0 sera ignoré. Pour les formats d, i, o, u, x et X, si il y a une indication de précision, l'indicateur 0 est ignoré. Pour les autres formats, le comportement n'est pas défini.

2
Un nombre entier décimal (optionnel) indiquant la taille minimum du champ d'impression, exprimée en caractères. Si parami s'écrit sur un nombre de caractères inférieur à cette taille, parami est complété à droite ou à gauche (selon que l'on aura utilisé ou pas l'indicateur -), avec des blancs ou des 0, comme il a été expliqué plus haut.

3
Une indication (optionnelle) de précision, qui donne :

-
le nombre minimum de chiffres pour les formats d, i, o, u, x et X.

-
le nombre de chiffres après le point décimal pour les formats e, E et f.

-
le nombre maximum de chiffres significatifs pour les formats g et G

-
le nombre maximum de caractères pour le format s.

Cette indication de précision prend la forme d'un point (.) suivi d'un nombre décimal optionnel. Si ce nombre est omis, la précision est prise égale à 0.



Remarque
Le nombre entier décimal indiquant la taille maximum du champ d'impression et/ou le nombre entier décimal indiquant la précision, peuvent être remplacées par le caractère *. Si le caractère * a été utilisé une seule fois dans le format, la valeur correspondante (taille du champ ou précision) sera prise égale à parami-1. Si le caractère * a été utilisé deux fois, la taille du champ d'impression sera égale à parami-2, et la précision sera égale à parami-1. Si la taille maximum du champ d'impression a une valeur négative, cela a la sémantique de l'indicateur - suivi de la valeur (positive) de la taille du champ d'impression. Si la précision est négative, cela a la sémantique d'une précision absente.


4
un caractère optionnel, qui peut être :

h
s'appliquant aux formats d, i, o, u, x ou X : parami sera interprété comme un short int ou unsigned short int.

h
s'appliquant au format n : parami sera interprété comme un pointeur vers un short int.

l
5.2. s'appliquant aux formats d, i, o, u, x ou X : parami sera interprété comme un long int ou un unsigned long int.

l
5.3 s'appliquant au format n : parami sera interprété comme un pointeur vers un long int.

L
s'appliquant aux formats e, E, f, g ou G : parami sera interprété comme un long double.



Si un h, l ou L s'applique à un autre format que ceux indiqués ci-dessus, le comportement est indéterminé.


5
un caractère qui peut prendre les valeurs suivantes :

d, i
parami sera interprété comme un int, et écrit sous forme décimale signée.

u
parami sera interprété comme un unsigned int, et écrit sous forme décimale non signée.

o
parami sera interprété comme un int, et écrit sous forme octale non signée.

x, X
parami sera interprété comme un int, et écrit sous forme hexadécimale non signée. La notation hexadécimale utilisera les lettres abcdef dans le cas du format x, et les lettres ABCDEF dans le cas du format X.

Dans les cas qui précèdent, la précision indique le nombre minimum de chiffres avec lesquels écrire parami. Si parami s'écrit avec moins de chiffres, il sera complété avec des zéros. La précision par défaut est 1. Une valeur nulle demandée avec une précision nulle, ne sera pas imprimée.

c
parami sera interprété comme un unsigned char.

s
parami sera interprété comme l'adresse d'un tableau de caractères (terminé ou non par un null). Les caractères du tableau seront imprimés jusqu'au premier des deux évènements possibles :
-
impression de précision caractères de parami.
-
rencontre de null dans parami.
Dans le cas où parami n'est pas terminé par un null, le format d'impression doit comporter une indication de précision.

p
parami sera interprété comme un pointeur vers void. Le pointeur sera imprimé sous une forme dépendante de l'implémentation.

n
parami sera interprété comme un pointeur vers un int auquel sera affecté le nombre de caractères écrits jusqu'alors par cette invocation de fprintf.

e,E
parami sera interprété comme un double et écrit sous la forme :
-option pe . pf e signe exposant
dans laquelle pe et pf sont respectivement partie entière et partie fractionnaire de la mantisse. La partie entière est exprimée avec un seul chiffre, la partie fractionnaire est exprimée avec un nombre de chiffres égal à la précision. La précision est prise égale à 6 par défaut. Si la précision est 0, le point décimal n'apparaît pas. L'exposant contient toujours au moins deux chiffres. Si parami est nul, l'exposant sera nul. Dans le cas du format E, la lettre E est imprimée à la place de e.

f
parami sera interprété comme un double et écrit sous la forme :
-option pe . pf
dans laquelle pe et pf sont respectivement partie entière et partie fractionnaire de la mantisse. La partie fractionnaire est exprimée avec un nombre de chiffres égal à la précision. La précision est prise égale à 6 par défaut. Si la précision est 0, le point décimal n'apparaît pas.

g,G
parami sera interprété comme un double et écrit sous le format f, ou le format e, selon sa valeur. Si parami a un exposant inférieur à -4 ou plus grand ou égal à la précision, il sera imprimé sous le format e, sinon il sera imprimé sous le format f. D'éventuels zéros à la fin de la partie fractionnaire sont enlevés. Le point décimal n'apparaît que si il est suivi d'au moins un chiffre. Dans ce qui précède, l'utilisation du format G implique l'utilisation du format E à la place du format e.

%
Un caractère % est écrit.

Écriture formattée : printf

  Nous avons déjà vu printf, mais nous allons la définir ici formellement.

Utilisation

La fonction printf admet un nombre variable de paramètres. Son utilisation est la suivante :

printf ( format , param1 , param2 , ... , paramn )

Description

Un appel printf(fmt, ...) est rigoureusement identique à fprintf(stdout,fmt,...).

Écriture formattée dans une chaîne : sprintf

 

Utilisation

La fonction sprintf admet un nombre variable de paramètres. Son utilisation est la suivante :

sprintf ( chaîne , format , param1 , param2 , ... , paramn )

Description

La fonction sprintf réalise le même traitement que la fonction fprintf, avec la différence que les caractères émis par sprintf ne sont pas écrits dans un fichier, mais dans le tableau de caractères chaîne. Un null est écrit dans chaîne en fin de traitement.

Exemples d'utilisation des formats

              source C                       resultat

printf("|%d|\n",1234);                       	|1234|
printf("|%d|\n",-1234);                      	|-1234|
printf("|%+d|\n",1234);                      	|+1234|
printf("|%+d|\n",-1234);                     	|-1234|
printf("|% d|\n",1234);                      	| 1234|
printf("|% d|\n",-1234);                     	|-1234|
printf("|%x|\n",0x56ab);                     	|56ab|
printf("|%X|\n",0x56ab);                     	|56AB|
printf("|%#x|\n",0x56ab);                    	|0x56ab|
printf("|%#X|\n",0x56ab);                    	|0X56AB|
printf("|%o|\n",1234);                       	|2322|
printf("|%#o|\n",1234);                      	|02322|
                                             	
printf("|%10d|\n",1234);                     	|      1234|
printf("|%10.6d|\n",1234);                   	|    001234|
printf("|%.6d|\n",1234);                     	|001234|
printf("|%*.6d|\n",10,1234);                 	|    001234|
printf("|%*.*d|\n",10,6,1234);               	|    001234|
                                             	
printf("|%f|\n",1.234567890123456789e5);     	|123456.789012|
printf("|%.4f|\n",1.234567890123456789e5);   	|123456.7890|
printf("|%.20f|\n",1.234567890123456789e5);  	|123456.78901234567456413060|
printf("|%20.4f|\n",1.234567890123456789e5); 	|         123456.7890|
                                             	
printf("|%e|\n",1.234567890123456789e5);     	|1.234568e+05|
printf("|%.4e|\n",1.234567890123456789e5);   	|1.2346e+05|
printf("|%.20e|\n",1.234567890123456789e5);  	|1.23456789012345674564e+05|
printf("|%20.4e|\n",1.234567890123456789e5); 	|          1.2346e+05|
                                             	
printf("|%.4g|\n",1.234567890123456789e-5);  	|1.235e-05|
printf("|%.4g|\n",1.234567890123456789e5);   	|1.235e+05|
printf("|%.4g|\n",1.234567890123456789e-3);  	|0.001235|
printf("|%.8g|\n",1.234567890123456789e5);   	|123456.79|

Entrées formattées : fscanf

 

Utilisation

La fonction fscanf admet un nombre variable de paramètres. Son utilisation est la suivante :

fscanf ( flot-de-données , format , param1 , param2 , ... , paramn )

Sémantique des paramètres

-
flot-de-données est de type pointeur vers FILE. Il pointe vers le fichier à partir duquel se fait la lecture.
-
format est une chaîne de caractères qui spécifie la forme de l'entrée admissible dans flot-de-données.
-
les parami sont des pointeurs. Ils pointent des variables dans lesquelles fscanf dépose les valeurs lues dans flot-de-données, après les avoir converties en binaire.

   
Valeur rendue

Si au moins un parami s'est vu affecter une valeur, fscanf retourne le nombre de parami affectés. Si il y a eu rencontre de fin de fichier ou erreur d'entrée-sortie avant toute affectation à un parami, fscanf retourne EOF.  

Description

fscanf lit une suite de caractères du fichier défini par flot-de-données en vérifiant que cette suite est conforme à la description qui en est faite dans format. Cette vérification s'accompagne d'un effet de bord qui consiste à affecter des valeurs aux variables pointées par les différents parami.  

Quelques définitions

flot d'entrée
il s'agit de la suite de caractères lus du fichier défini par flot-de-données.

caractères blancs
il s'agit des six caractères suivants : espace, tab, line feed, new line, vertical tab et form feed.

modèle
un modèle est la description d'un ensemble de chaînes de caractères. Exemple : %d est le modèle des chaînes formées de chiffres décimaux, éventuellement signées.

conforme
on dira qu'une chaîne est conforme à un modèle quand elle appartient à l'ensemble des chaînes décrites par le modèle. Exemple : 123 est conforme au modèle %d.

directive
une directive peut être :

-
une suite de caractères blancs qui est un modèle d'un nombre quelconque de caractères blancs. Exemple : un espace est un modèle pour un nombre quelconque d'espaces, ou d'un nombre quelconque d'espace et de tab mélangés, ou d'un nombre quelconque d'espaces, de tab et de line-feed mélangés etc.

-
une suite de caractères ordinaires (c'est à dire qui ne sont ni des caractères blancs, ni le caractère %) qui est un modèle pour elle-même. Exemple : la chaîne hello est un modèle de la seule chaîne hello.

-
des séquences d'échappement introduites par le caractère %. Ces séquences jouent un double rôle : elle sont à la fois un modèle des chaînes acceptables dans le flot d'entrée, et elles sont également des ordres de conversion de la chaîne lue et d'affectation du résultat à une variable pointée par le parami correspondant. Exemple : la directive %d est un modèle des nombres décimaux et un ordre de conversion de la chaîne lue en valeur binaire et d'affectation à l'entier pointé par le parami correspondant.

Les séquences d'échappement

                Les séquences d'échappement se composent des éléments suivants :

1
le caractère * (optionnel) qui indique que la directive doit être considérée comme un pur modèle : pas de conversion de la chaîne lue, et pas d'affectation à un parami.

2
un nombre (optionnel) qui indique la longueur maximum de la chaîne acceptable du flot d'entrée.

3
un caractère optionnel, qui est un modificateur de type, pouvant prendre l'une des valeurs suivantes :

h
s'appliquant aux formats d, i, n : parami sera interprété comme un pointeur vers un short int.

h
s'appliquant aux formats o, u, x : parami sera interprété comme un pointeur vers un unsigned short int.

l
s'appliquant aux formats d, i, n : parami sera interprété comme un pointeur vers un long int.

l
s'appliquant aux formats o, u, x : parami sera interprété comme un pointeur vers un unsigned long int.

l
s'appliquant aux formats e, f, g : parami sera interprété comme un pointeur vers un double.

L
s'appliquant aux formats e, f, g : parami sera interprété comme un pointeur vers un long double.

4
un caractère de conversion qui peut prendre l'une des valeurs suivantes :

d
modèle pour un nombre décimal éventuellement précédé d'un signe. Le parami correspondant est interprété comme un pointeur vers un int, sauf si la directive contient un modificateur de type.

i
modèle pour un nombre éventuellement précédé d'un signe, et ayant l'une des trois formes suivantes :

-
un nombre décimal.
-
un nombre débutant par 0 qui sera pris comme nombre octal.
-
un nombre débutant par 0x ou 0X, qui sera pris comme nombre hexadécimal.

Le parami correspondant est interprété comme un pointeur vers un int, sauf si la directive contient un modificateur de type.

o
modèle pour un nombre octal éventuellement précédé d'un signe. Le parami correspondant est interprété comme un pointeur vers un unsigned int, sauf si la directive contient un modificateur de type.

u
modèle pour un nombre décimal éventuellement précédé d'un signe.5.4 Le parami correspondant est interprété comme un pointeur vers un unsigned int, sauf si la directive contient un modificateur de type.

x
modèle pour un nombre hexadécimal éventuellement précédé d'un signe. Le parami correspondant est interprété comme un pointeur vers un unsigned int, sauf si la directive contient un modificateur de type.



Remarque
En ce qui concerne les formats o, u, et x, le lecteur a sans doute été surpris de voir que le parami correspondant est interprété comme un pointeur vers un unsigned int alors que la chaîne dans le flot d'entrée qui correspond à ces formats est un nombre éventuellement précédé d'un signe. Il n'y a pas d'erreur, c'est bien ce que dit la norme.


c
modèle pour une suite de caractères dont le nombre est donné par le nombre (optionnel) qui indique la longueur maximum de la chaîne acceptable du flot d'entrée (Cf plus haut). Si ce nombre optionnel ne figure pas dans la directive, il est pris égal à 1. Le parami correspondant est interprété comme étant un pointeur vers un tableau de caractères suffisamment grand pour contenir la chaîne lue. Il n'y a pas de null rajouté à la fin de la chaîne lue dans le flot d'entrée.

s
modèle pour une suite de caractères non blancs. Le parami correspondant est interprété comme un pointeur vers un tableau de caractères suffisamment grand pour contenir la chaîne lue plus un null terminal.

e,f,g
modèle pour un flottant écrit selon la syntaxe d'une constante flottante du langage C. Le parami correspondant est interprété comme un pointeur vers un float , sauf si la directive contient un modificateur de type.

[
Dans la chaîne format, ce caractère introduit une séquence particulière destinée à définir un scanset. La séquence est formée du caractère [, suivi d'une suite de caractères quelconques, suivi du caractère ]. Si le premier caractère après le crochet ouvrant n'est pas le caractère ^, le scanset est l'ensemble des caractères entre crochets. Si le caractère après le crochet ouvrant est le caractère ^, le scanset est l'ensemble des caractères ne se trouvant pas dans la chaîne entre crochets. Le scanset peut comprendre le caractère ] à condition de le mettre en début soit [] ...] ou [^]...] selon que l'on utilise la forme sans ou avec ^. Le scanset peut contenir ^ à condition de ne pas le mettre en tête : [...^...].

Une directive [ est un modèle pour une suite de caractères appartenant au scanset. Le parami correspondant est interprété comme un pointeur vers un tableau de caractères suffisamment grand pour contenir la chaîne lue plus un null terminal.

p
modèle pour un pointeur écrit d'une manière dépendant de l'implémentation, mais identique à l'impression par printf d'un pointeur selon le format %p. Le parami correspondant est interprété comme un pointeur vers un pointeur vers void.

n
cette directive n'est pas un modèle. Elle ne sert qu'à mettre une valeur dans l'objet pointé par le parami correspondant. Le parami correspondant est interprété comme un pointeur vers un int dans lequel fscanf écrit le nombre de caractères lus jusqu'à ce moment, dans le flot de données, par cette invocation de fscanf. L'exécution d'une directive %n n'augmente pas le nombre des parami affectés qui sera retourné par fscanf (Cf 5.5.5).

%
est un modèle pour le caractère %. La directive complète est %%.

Algorithme de fscanf

La chaîne format doit se composer d'un ensemble de directives. Il doit y avoir autant de parami que de directives demandant l'affectation d'une valeur. Si il n'y a pas suffisamment de parami pour le format, le comportement n'est pas défini. Si il y a davantage de parami que demandé par le format, les parami en excès sont évalués mais ils sont inutilisés.

La fonction fscanf exécute dans l'ordre chaque directive du format. Si une directive échoue, la fonction fscanf retourne à l'appelant.

-
L'exécution d'une directive formée de caractères blancs, consiste à consommer dans le flot d'entrée la plus longue séquence possible de caractères blancs. Même si cette séquence est de taille nulle, la directive a réussi.

-
L'exécution d'une directive formée de caractères ordinaires, consiste à consommer dans le flot d'entrée une séquence identique à la directive. Au premier caractère différent, la directive a échoué et ce caractère reste non lu.

-
L'exécution d'une directive formée d'une séquence d'échappement, consiste à :

1.
consommer dans le flot d'entrée la plus longue séquence possible de caractères blancs. Cette séquence peut être de taille nulle. Cette action ne s'applique pas aux formats c, n, ni [.

2.
consommer dans le flot d'entrée la plus longue séquence possible de caractères qui soit conforme au modèle. Si cette séquence est de taille nulle, la directive a échoué.

3.
si la directive ne contient pas le caractère *, convertir la chaîne lue et l'affecter à l'objet pointé par le parami correspondant. Si cet objet n'est pas de la taille ou du type convenable pour la recevoir, le comportement n'est pas défini.

Remarques sur la gestion des espaces blancs

La gestion des espaces blancs est assez pénible. Il y a deux méthodes de consommation des espaces blancs du flot de données :
1.
le format contient une directive formée de caractères blancs. Si une telle directive ne peut consommer aucun caractère blanc, c'est un cas d'échec de la directive.

2.
le format contient une séquence d'échappement (autre que c, n, ou [) dont l'exécution commence par consommer d'éventuels caractères blancs dans le flot de données. Si il n'y a pas de caractères blancs à consommer, ce n'est pas une condition d'échec de la directive.

Voyons quelques conséquences.

Si le flot de données contient 23 45 on pourra les lire indifféremment soit :

-
par le format "%d %d" : la première directive %d consomme 23, la directive blanc (entre les deux %d) consomme les blancs entre 2 et 45, et la seconde directive %d essaye de consommer des blancs, échoue (mais ce n'est pas une erreur), puis consomme 45.

-
par le format "%d%d" : la première directive %d consomme 23, la seconde directive %d essaye de consommer des blancs, réussit, puis consomme 45.

Dans les deux cas, les valeurs affectées seront bien les mêmes : 23 et 45.

Un tel phénomène ne se manifeste pas avec les séquences d'échappement dont l'exécution ne commence pas par consommer les espaces blancs. Par exemple, si le flot de données contient 23 jean dupond, on n'obtiendra pas le même résultat selon que l'on utilise le format
"%d %[ abcdefghijklmnopqrstuvwxyz]" ou le format
"%d%[ abcdefghijklmnopqrstuvwxyz]" (sans blanc après %d). Le fscanf réussira dans les deux cas, mais dans le premier cas, la chaîne affectée au parami sera "jean dupond" et dans le second cas, ce sera " jean dupond".

Entrées formattées : scanf

  Nous avons déjà vu scanf, nous allons la définir ici formellement.

Utilisation

La fonction scanf admet un nombre variable de paramètres. Son utilisation est la suivante :

scanf ( format , param1 , param2 , ... , paramn )

Description

Un appel scanf(fmt,...) est rigoureusement identique à fscanf(stdin,fmt,...).

Entrées formattées depuis une chaîne : sscanf

 

Utilisation

La fonction sscanf admet un nombre variable de paramètres. Son utilisation est la suivante :

sscanf ( chaîne , format , param1 , param2 , ... , paramn )

Description

La fonction sscanf réalise le même traitement que la fonction fscanf, avec la différence que les caractères lus par sscanf ne sont pas lus depuis un fichier, mais du tableau de caractères chaîne. La rencontre du null terminal de chaîne pour sscanf est équivalent à la rencontre de fin de fichier pour fscanf.


next up previous contents index
Next: Récréation Up: Les entrées-sorties Previous: Lecture et écriture par
Bernard Cassagne
1998-12-09
Contacter le responsable de la rubrique C