NOM
printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf,
vsnprintf - Formatage des sorties
SYNOPSIS
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
Exigences de macros de test de fonctionnalités pour la glibc (voir
feature_test_macros(7)) :
snprintf(), vsnprintf() : _BSD_SOURCE || _XOPEN_SOURCE >= 500 ||
_ISOC99_SOURCE ; ou cc -std=c99
Les fonctions de la famille printf() produisent des sorties en accord
avec le format décrit plus bas. Les fonctions printf() et vprintf()
écrivent leur sortie sur stdout, le flux de sortie standard. fprintf()
et vfprintf() écrivent sur le flux stream indiqué. sprintf(),
snprintf(), vsprintf() et vsnprintf() écrivent leurs sorties dans la
chaîne de caractères str.
Les fonctions snprintf() et vsnprintf() écrivent au plus size octets
(caractère nul (« \0 ») final compris) dans str.
Les fonctions vprintf(), vfprintf(), vsprintf(), vsnprintf() sont
équivalentes aux fonctions printf(), fprintf(), sprintf(), snprintf()
respectivement, mais elles emploient un tableau va_list à la place d’un
nombre variable d’arguments. Ces fonctions n’appellent pas la macro
va_end. Du fait qu’elles appèlent la macro va_arg, la valeur de ap
n’est pas définie après l’appel. Consultez stdarg(3).
Ces huit fonctions créent leurs sorties sous le contrôle d’une chaîne
de format qui indique les conversions à apporter aux arguments suivants
(ou accessibles à travers les arguments de taille variable de
stdarg(3)).
C99 et POSIX.1-2001 spécifient que les résultats ne sont pas définis si
un appel à sprintf(), snprintf(), vsprintf() ou vsnprintf() causait la
copie entre des objets qui se chevauchent (par exemple, si le tableau
de la chaîne cible et un des paramètres d’entrée se trouvent dans le
même tampon). Consultez la section NOTES.
VALEUR RENVOYÉE
En cas de succès, ces fonctions renvoient le nombre de caractères
affichés (sans compter le caractère nul de fin utilisé pour terminer
les sorties dans les chaînes).
Ces fonctions renvoient le nombre de caractères imprimés, sans compter
le caractère nul « \0 » final dans les chaînes. Les fonctions
snprintf() et vsnprintf() n’écrivent pas plus de size octets (y compris
le «\0 » final). Si la sortie a été tronquée à cause de la limite, la
valeur de retour est le nombre de caractères (sans le « \0 » final) qui
auraient été écrits dans la chaîne s’il y avait eu suffisamment de
place. Ainsi, une valeur de retour size ou plus signifie que la sortie
a été tronquée (voir aussi la section NOTES plus bas).
Si une erreur de sortie s’est produite, une valeur négative est
renvoyée.
CHAÎNE DE FORMAT
Le format de conversion est indiqué par une chaîne de caractères,
commençant et se terminant dans son état de décalage initial. La chaîne
de format est composée d’indicateurs : les caractères ordinaires
(différents de %), qui sont copiés sans modification sur la sortie, et
les spécifications de conversion, qui sont mises en correspondance avec
les arguments suivants. Les spécifications de conversion sont
introduites par le caractère %, et se terminent par un indicateur de
conversion. Entre eux peuvent se trouver (dans l’ordre), zéro ou
plusieurs attributs, une valeur optionnelle de largeur minimal de
champ, une valeur optionnelle de prcision, et un éventuel modificateur
de longueur.
Les arguments doivent correspondre correctement (après les promotions
de types) avec les indicateurs de conversion. Par défaut les arguments
sont pris dans l’ordre indiqué, où chaque « * » et chaque indicateur de
conversion réclament un nouvel argument (et où l’insuffisance en
arguments est une erreur). On peut aussi préciser explicitement quel
argument prendre, en écrivant, à chaque conversion, « %m$ » au lieu de
« % », et « *m$ » au lieu de « * ». L’entier décimal m indique la
position dans la liste d’arguments, l’indexation commençant à 1. Ainsi,
printf("%*d", width, num);
et
printf("%2$*1$d", width, num);
sont équivalents. La seconde notation permet de répéter plusieurs fois
le même argument. Le standard C99 n’autorise pas le style utilisant
« $ », qui provient des Spécifications Single Unix. Si le style avec
« $ » est utilisé, il faut l’employer pour toutes conversions prenant
un argument, et pour tous les arguments de largeur et de précision,
mais on peut le mélanger avec des formats « %% » qui ne consomment pas
d’arguments. Il ne doit pas y avoir de sauts dans les numéros des
arguments spécifiés avec « $ ». Par exemple, si les arguments 1 et 3
sont spécifiés, l’argument 2 doit aussi être mentionné quelque part
dans la chaîne de format.
Pour certaines conversions numériques, un caractère de séparation
décimale (le point par défaut) est utilisé, ainsi qu’un caractère de
regroupement par milliers. Les véritables caractères dépendent de la
localisation LC_NUMERIC. La localisation POSIX utilise « . » comme
séparateur décimal, et n’a pas de caractère de regroupement. Ainsi,
printf("%'.2f", 1234567.89);
s’affichera comme « 1234567.89 » dans la localisation POSIX,
« 1 234567,89 » en localisation fr_FR, et « 1.234.567,89 » en
localisation da_DK.
CARACTÈRE D’ATTRIBUT
Le caractère % peut être éventuellement suivi par un ou plusieurs
attributs suivants :
# indique que la valeur doit être convertie en une autre forme.
Pour la conversion o le premier caractère de la chaîne de sortie
vaudra zéro (en ajoutant un préfixe 0 si ce n’est pas déjà un
zéro). Pour les conversions x et X une valeur non nulle reçoit
le préfixe « 0x » (ou « 0X » pour l’indicateur X). Pour les
conversions a, A, e, E, f, F, g, et G le résultat contiendra
toujours un point décimal même si aucun chiffre ne le suit
(normalement, un point décimal n’est présent avec ces
conversions que si des décimales le suivent). Pour les
conversions g et G les zéros en tête ne sont pas éliminés,
contrairement au comportement habituel. Pour les autres
conversions, cet attribut n’a pas d’effet.
0 indique le remplissage avec des zéros. Pour les conversions d,
i, o, u, x, X, a, A, e, E, f, F, g, et G, la valeur est
complétée à gauche avec des zéros plutôt qu’avec des espaces. Si
les attributs 0 et - apparaissent ensemble, l’attribut 0 est
ignoré. Si une précision est fournie avec une conversion
numérique (d, i, o, u, x, et X), l’attribut 0 est ignoré. Pour
les autres conversions, le comportement est indéfini.
- indique que la valeur doit être justifiée sur la limite gauche
du champ (par défaut elle l’est à droite). Sauf pour la
conversion n, les valeurs sont complétées à droite par des
espaces, plutôt qu’à gauche par des zéros ou des blancs. Un
attribut - surcharge un attribut 0 si les deux sont fournis.
' ' (un espace) indique qu’un espace doit être laissé avant un
nombre positif (ou une chaîne vide) produit par une conversion
signée
+ Un signe (+ ou -) doit toujours être imprimé avant un nombre
produit par une conversion signée. Par défaut, un signe n’est
utilisé que pour des valeurs négatives. Un attribut + surcharge
un attribut « espace » si les deux sont fournis.
Les cinq caractères d’attributs ci-dessus sont définis dans le standard
C, les spécifications SUSv2 en ajoute un :
' Pour les conversions décimales (i, d, u, f, F, g, G) indique que
les chiffres d’un argument numérique doivent être groupés par
milliers en fonction de la localisation. Remarquez que de
nombreuses versions de gcc(1) n’acceptent pas cet attribut et
déclencheront un avertissement (warning). SUSv2 n’inclue pas
%'F.
La glibc 2.2 ajoute un caractère d’attribut supplémentaire.
I Pour les conversions décimales (i, d, u) la sortie emploie les
chiffres alternatifs de la localisation s’il y en a. Par
exemple, depuis la glibc 2.2.3, cela donnera des chiffres arabes
pour la localisation perse («fa_IR »).
LARGEUR DE CHAMP
Un nombre optionnel ne commençant pas par un zéro, peut indiquer une
largeur minimale de champ. Si la valeur convertie occupe moins de
caractères que cette largeur, elle sera complétée par des espaces à
gauche (ou à droite si l’attribut d’alignement à gauche a été fourni).
À la place de la chaîne représentant le nombre décimal, on peut écrire
« * » ou « *m$ » (m étant entier) pour indiquer que la largeur du champ
est fournie dans l’argument suivant, ou dans le m-ième argument,
respectivement. L’argument fournissant la largeur doit être de type
int. Une largeur négative est considéré comme l’attribut « - » vu plus
haut suivi d’une largeur positive. En aucun cas une largeur trop petite
ne provoque la troncature du champ. Si le résultat de la conversion est
plus grand que la largeur indiquée, le champ est élargi pour contenir
le résultat.
PRÉCISION
Une précision éventuelle, sous la forme d’un point (« . ») suivi par un
nombre. À la place de la chaîne représentant le nombre décimal, on peut
écrire « * » ou « *m$ » (m étant entier) pour indiquer que la précision
est fournie dans l’argument suivant, ou dans le m-ième argument,
respectivement. L’argument fournissant la précision doit être de type
int. Si la précision ne contient que le caractère « . », ou une valeur
négative, elle est considérée comme nulle. Cette précision indique un
nombre minimum de chiffres à faire apparaître lors des conversions d,
i, o, u, x, et X, le nombre de décimales à faire apparaître pour les
conversions a, A, e, E, f et F, le nombre maximum de chiffres
significatifs pour g et G, et le nombre maximum de caractères à
imprimer depuis une chaîne pour les conversions s et S.
MODIFICATEUR DE LONGUEUR
Ici, une conversion entière correspond à d, i, o, u, x ou X.
hh La conversion entière suivante correspond à un signed char ou
unsigned char, ou la conversion n suivante correspond à un
argument pointeur sur un signed char.
h La conversion entière suivante correspond à un short int ou
unsigned short int, ou la conversion n suivante correspond à un
argument pointeur sur un short int.
l (elle) La conversion entière suivante correspond à un long int
ou unsigned long int, ou la conversion n suivante correspond à
un pointeur sur un long int, ou la conversion c suivante
correspond à un argument wint_t, ou encore la conversion s
suivante correspond à un pointeur sur un wchar_t.
ll (elle-elle) La conversion entière suivante correspond à un long
long int, ou unsigned long long int, ou la conversion n suivante
correspond à un pointeur sur un long long int.
L La conversion a, A, e, E, f, F, g, ou G suivante correspond à un
argument long double (C99 autorise %LF mais pas SUSv2).
q (« quad » BSD 4.4 et Linux sous libc5 seulement, ne pas
utiliser) Il s’agit d’un synonyme pour ll.
j La conversion entière suivante correspond à un argument intmax_t
ou uintmax_t.
z La conversion entière suivante correspond à un argument size_t
ou ssize_t (la bibliothèque libc5 de Linux proposait l’argument
Z pour cela, ne pas utiliser).
t La conversion entière suivante correspond à un argument
ptrdiff_t.
Les spécifications SUSv2 ne mentionnent que les modificateurs de
longueur h (dans hd, hi, ho, hx, hX, hn), l (dans ld, li, lo, lx, lX,
ln, lc, ls) et L (dans Le, LE, Lf, Lg, LG).
INDICATEUR DE CONVERSION
Un caractère indique le type de conversion à apporter. Les indicateurs
de conversion, et leurs significations sont :
d, i L’argument int est converti en un chiffre décimal signé. La
précision, si elle est mentionnée, correspond au nombre minimal
de chiffres qui doivent apparaître. Si la conversion fournit
moins de chiffres, le résultat est rempli à gauche avec des
zéros. Par défaut la précision vaut 1. Lorsque 0 est converti
avec une précision valant 0, la sortie est vide.
o, u, x, X
L’argument unsigned int est converti en un chiffre octal non
signé (o), un chiffre décimal non signé (u), un chiffre
hexadécimal non signé (x et X). Les lettres abcdef sont
utilisées pour les conversions avec x, les lettres ABCDEF sont
utilisées pour les conversions avec X. La précision, si elle est
indiquée, donne un nombre minimal de chiffres à faire
apparaître. Si la valeur convertie nécessite moins de chiffres,
elle est complétée à gauche avec des zéros. La précision par
défaut vaut 1. Lorsque 0 est converti avec une précision valant
0, la sortie est vide.
e, E L’argument réel, de type double, est arrondi et présenté avec la
notation scientifique [-]c.ccce±cc dans lequel se trouve un
chiffre avant le point, puis un nombre de décimales égal à la
précision demandée. Si la précision n’est pas indiquée,
l’affichage contiendra 6 décimales. Si la précision vaut zéro,
il n’y a pas de point décimal. Une conversion E utilise la
lettre E (plutôt que e) pour introduire l’exposant. Celui-ci
contient toujours au moins deux chiffres. Si la valeur affichée
est nulle, son exposant est 00.
f, F L’argument réel, de type double, est arrondi, et présenté avec
la notation classique [-]ccc.ccc, où le nombre de décimales est
égal à la précision réclamée. Si la précision n’est pas
indiquée, l’affichage se fera avec 6 décimales. Si la précision
vaut zéro, aucun point n’est affiché. Lorsque le point est
affiché, il y a toujours au moins un chiffre devant.
SUSv2 ne mentionne pas F et dit qu’il existe une chaîne de
caractères représentant l’infini ou NaN. Le standard C99 précise
« [-]inf » ou «[-]infinity » pour les infinis, et une chaîne
commençant par « nan » pour NaN dans le cas d’une conversion f,
et les chaînes « [-]INF » «[-]INFINITY » « NAN* » pour une
conversion F.
g, G L’argument réel, de type double, est converti en style f ou e
(ou F ou E pour la conversion G) La précision indique le nombre
de décimales significatives. Si la précision est absente, une
valeur par défaut de 6 est utilisée. Si la précision vaut 0,
elle est considérée comme valant 1. La notation scientifique e
est utilisée si l’exposant est inférieur à -4 ou supérieur ou
égal à la précision demandée. Les zéros en fin de partie
décimale sont supprimés. Un point décimal n’est affiché que s’il
est suivi d’au moins un chiffre.
a, A (C99 mais pas SUSv2). Pour la conversion a, l’argument de type
double est transformé en notation hexadécimale (avec les lettres
abcdef) dans le style [-]0xh.hhhhp±d; Pour la conversion A, le
préfixe 0X, les lettres ABCDEF et le séparateur d’exposant P
sont utilisés. Il y a un chiffre hexadécimal avant la virgule,
et le nombre de chiffres ensuite est égal à la précision. La
précision par défaut suffit pour une représentation exacte de la
valeur, si une représentation exacte est possible en base 2.
Sinon, elle est suffisamment grande pour distinguer les valeurs
de type double. Le chiffre avant le point décimal n’est pas
spécifié pour les nombres non normalisés, et il est non nul pour
les nombres normalisés.
c S’il n’y a pas de modificateur l, l’argument entier, de type
int, est converti en un unsigned char, et le caractère
correspondant est affiché. Si un modificateur l est présent,
l’argument de type wint_t (caractère large) est converti en
séquence multioctet par un appel à wcrtomb(3), avec un état de
conversion débutant dans l’état initial. La chaîne multioctet
résultante est écrite.
s S’il n’y a pas de modificateur l, l’argument de type const char
* est supposé être un pointeur sur un tableau de caractères
(pointeur sur une chaîne). Les caractères du tableau sont écrits
jusqu’au caractère nul ’\0’ final, non compris. Si une précision
est indiquée, seul ce nombre de caractères sont écrits. Si une
précision est fournie, il n’y a pas besoin de caractère nul. Si
la précision n’est pas donnée, ou si elle est supérieure à la
longueur de la chaîne, le caractère nul final est nécessaire.
Si un modificateur l est présent, l’argument de type const
wchar_t * est supposé être un pointeur sur un tableau de
caractères larges. Les caractères larges du tableau sont
convertis en une séquence de caractères multioctet (chacun par
un appel de wcrtomb(3), avec un état de conversion dans l’état
initial avant le premier caractère large), ceci jusqu’au
caractère large nul final compris. Les caractères multioctet
résultants sont écris jusqu’à l’octet nul final (non compris).
Si une précision est fournie, il n’y a pas plus d’octets écrits
que la précision indiquée, mais aucun caractère multioctet n’est
écrit partiellement. Remarquez que la précision concerne le
nombre d’octets écrits, et non pas le nombre de caractres
larges ou de positions dcrans. La chaîne doit contenir un
caractère large nul final, sauf si une précision est indiquée,
suffisamment petite pour que le nombre d’octets écrits la
remplisse avant la fin de la chaîne.
C (dans SUSv2 mais pas dans C99) Synonyme de lc. Ne pas utiliser.
S (dans SUSv2 mais pas dans C99) Synonyme de ls. Ne pas utiliser.
p L’argument pointeur, du type void * est affiché en hexadécimal,
comme avec %#x ou %#lx.
n Le nombre de caractères déjà écrits est stocké dans l’entier
indiqué par l’argument pointeur de type int *. Aucun argument
n’est converti.
m (extension glibc) Affiche la sortie strerror(errno). Aucun
argument n’est requis.
% Un caractère « % » est écrit. Il n’y a pas de conversion.
L’indicateur complet est « %% ».
CONFORMITÉ
Les fonctions fprintf(), printf(), sprintf(), vprintf(), vfprintf() et
vsprintf() sont conformes à C89 et C99. Les fonctions snprintf() et
vsnprintf() sont conformes à C99.
En ce qui concerne la valeur de retour de snprintf(), SUSv2 et C99 sont
en contradiction : lorsque snprintf() est appelée avec un argument
size=0 SUSv2 précise une valeur de retour indéterminée, inférieure à 1,
alors que C99 autorise str à être NULL dans ce cas, et réclame en
valeur de retour (comme toujours) le nombre de caractères qui auraient
été écrits si la chaîne de sortie avait été assez grande.
La bibliothèque libc4 de Linux connaissait les 5 attributs standards du
C. Elle connaissait les modificateurs de longueur h, l, L et les
conversions c, d, e, E, f, F, g, G, i, n, o, p, s, u, x et X, où F
était synonyme de f. De plus, elle acceptait D, O et U comme synonymes
de ld, lo et lu (ce qui causa de sérieux bogues par la suite lorsque le
support de %D disparut). Il n’y avait pas de séparateur décimal
dépendant de la localisation, pas de séparateur des milliers, pas de
NaN ou d’infinis, et pas de « %m$ » ni « *m$ ».
La bibliothèque libc5 de Linux connaissait les 5 attributs standards C,
l’attribut « ' », la localisation, « %m$ » et « *m$ ». Elle connaissait
les modificateurs de longueur h, l, L, Z et q, mais acceptait L et q
pour les long double et les long long int (ce qui est un bogue). Elle
ne reconnaissait plus F, D, O et U, mais ajoutait le caractère de
conversion m, qui affiche strerror(errno).
La bibliothèque glibc 2.0 ajouta les caractères de conversion C et S.
La bibliothèque glibc 2.1 ajouta les modificateurs de longueur hh, t et
z, et les caractères de conversion a et A.
La bibliothèque glibc 2.2. ajouta le caractère de conversion F avec la
sémantique C99, et le caractère d’attribut I.
NOTES
Certains programmes reposent imprudemment sur du code comme :
sprintf(buf, "%s some further text", buf);
pour ajouter du texte à buf. Cependant, les normes indiquent
explicitement que le résultat n’est pas défini si les tampons de source
et de destination se recouvrent lors d’un appel à sprintf(),
snprintf(), vsprintf() et vsnprintf(). En fonction de la version de
gcc(1) utilisée et des options de compilation, ces appels ne produiront
pas le résultat attendu.
L’implémentation des fonctions snprintf() et vsnprintf() de la glibc se
conforme au standard C99, et se comporte comme décrit plus haut depuis
la glibc 2.1. Jusqu’à la glibc 2.0.6, elles renvoyaient -1 si la sortie
avait été tronquée.
BOGUES
Comme sprintf() et vsprintf() ne font pas de suppositions sur la
longueur des chaînes, le programme appelant doit s’assurer de ne pas
déborder l’espace d’adressage. C’est souvent difficile. Notez que la
longueur des chaînes peut varier avec la localisation et être
difficilement prévisible. Il faut alors utiliser snprintf() ou
vsnprintf() à la place (ou encore asprintf(3) et vasprintf(3)).
La libc4.[45] de Linux n’avait pas snprintf(), mais proposait une
bibliothèque libbsd qui contenait un snprintf() équivalent à sprintf(),
c’est-à-dire qui ignorait l’argument size. Ainsi, l’utilisation de
snprintf() avec les anciennes libc4 pouvait conduire à de sérieux
problèmes de sécurité.
Un code tel que printf(foo); indique souvent un bogue, car foo peut
contenir un caractère « % ». Si foo vient d’une saisie non sécurisée,
il peut contenir %n, ce qui autorise printf() à écrire dans la mémoire,
et crée une faille de sécurité.
EXEMPLE
Pour afficher pi avec cinq décimales :
#include <math.h>
#include <stdio.h>
fprintf (stdout, "pi = %.5f\n", 4 * atan (1.0));
Pour afficher une date et une heure sous la forme « Sunday, July 3,
23:15», ou jour_semaine et mois sont des pointeurs sur des chaînes :
#include <stdio.h>
fprintf(stdout, "%s, %s %d, %.2d:%.2d\n",
jour_semaine, mois, jour, heure, minute);
De nombreux pays utilisent un format de date différent, comme
jour-mois-année. Une version internationale doit donc être capable
d’afficher les arguments dans l’ordre indiqué par le format :
#include <stdio.h>
fprintf(stdout, format,
jour_semaine, mois, jour, heure, min);
où le format dépend de la localisation et peut permuter les arguments.
Avec la valeur :
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
On peut obtenir « Dimanche, 3 Juillet, 23:15 ».
Pour allouer une chaîne de taille suffisante et écrire dedans (code
correct aussi bien pour glibc 2.0 que glibc 2.1) :
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
char *
make_message(const char *fmt, ...)
{
/* Supposons que nous n’avons pas besoin de plus de 100 octets. */
int n, size = 100;
char *p, *np;
va_list ap;
if ((p = malloc(size)) == NULL)
return NULL;
while (1) {
/* Essayons avec l’espace alloué. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* Si ça marche, renvoyer la chaîne. */
if (n > -1 && n < size)
return p;
/* Sinon réessayer avec plus de place. */
if (n > -1) /* glibc 2.1 */
size = n+1; /* ce qu’il fallait */
else /* glibc 2.0 */
size *= 2; /* deux fois plus */
if ((np = realloc(p, size)) == NULL) {
free(p);
return NULL;
} else {
p = np;
}
}
}
VOIR AUSSI
printf(1), asprintf(3), dprintf(3), scanf(3), setlocale(3), wcrtomb(3),
wprintf(3), locale(5)
COLOPHON
Cette page fait partie de la publication 3.23 du projet man-pages
Linux. Une description du projet et des instructions pour signaler des
anomalies peuvent être trouvées à l’adresse
http://www.kernel.org/doc/man-pages/.
TRADUCTION
Cette page de manuel a été traduite et mise à jour par Christophe
Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis par
Alain Portal <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
disposition sur http://manpagesfr.free.fr/.
Les mises à jour et corrections de la version présente dans Debian sont
directement gérées par Nicolas François
<nicolas.francois@centraliens.net> et l’équipe francophone de
traduction de Debian.
Veuillez signaler toute erreur de traduction en écrivant à
<debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
paquet manpages-fr.
Vous pouvez toujours avoir accès à la version anglaise de ce document
en utilisant la commande « man -L C <section> <page_de_man> ».