PRINTF(3) | Manuel du programmeur Linux | PRINTF(3) |
printf, fprintf, dprintf, sprintf, snprintf, vprintf, vfprintf, vdprintf, vsprintf, vsnprintf - Formatage des sorties
#include <stdio.h>
int printf(const char *format, ...); int fprintf(FILE *flux, const char *format, ...); int dprintf(int fd, const char *format, ...); int sprintf(char *chaîne, const char *format, ...); int snprintf(char *chaîne, size_t taille, const char *format, ...); #include <stdarg.h>
int vprintf(const char *format, va_list ap); int vfprintf(FILE *flux, const char *format, va_list ap); int vdprintf(int fd, const char *format, va_list ap); int vsprintf(char *chaîne, const char *format, va_list ap); int vsnprintf(char *chaîne, size_t taille, const char *format, va_list ap);
snprintf(), vsnprintf() :
dprintf(), vdprintf() :
The functions in the printf() family produce output according to a format as described below. The functions printf() and vprintf() write output to stdout, the standard output stream; fprintf() and vfprintf() write output to the given output stream; sprintf(), snprintf(), vsprintf(), and vsnprintf() write to the character string str.
La fonction dprintf() est équivalente à fprintf() si ce n'est qu'elle écrit dans un descripteur de fichier fd plutôt que dans un flux stdio.
Les fonctions snprintf() et vsnprintf() écrivent au plus taille octets (octet NULL final (« \0 ») compris) dans chaîne.
Les fonctions vprintf(), vfprintf(), vdprintf(), vsprintf() et vsnprintf() sont équivalentes aux fonctions printf(), fprintf(), dprintf(), sprintf() et 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 appellent la macro va_arg, la valeur de ap n'est pas définie après l'appel. Consultez stdarg(3).
Toutes ces fonctions écrivent 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.
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 de zéro ou plus 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 chacune recherche un ou plus d’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 minimale de champ, une valeur optionnelle de précision, 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 « * » (voir Largeur de champ et Précision ci-après) et chaque indicateur de conversion réclame un nouvel argument (et l'insuffisance d’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 UNIX Single. 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 valeur de LC_NUMERIC dans la locale (consultez setlocale(3)). 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 234 567,89 » en localisation fr_FR, et « 1.234.567,89 » en localisation da_DK.
Le caractère % peut être éventuellement suivi par zéro ou plusieurs des attributs suivants :
Les cinq caractères d'attributs ci-dessus sont définis dans la norme C99, les Spécifications UNIX Single en ajoutent un :
La glibc 2.2 ajoute un caractère d'attribut supplémentaire.
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ée 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.
Une précision optionnelle, sous la forme d'un point (« . ») suivi par une chaîne optionnelle de nombres décimaux. À 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, et qui doit être de type int. Si la précision ne contient que le caractère « . », elle est considérée comme zéro. Une précision négative est considérée comme omise. Cette précision indique un nombre minimal 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 maximal de chiffres significatifs pour g et G et le nombre maximal de caractères à imprimer depuis une chaîne pour les conversions s et S.
Ici, une « conversion d’entier » correspond à d, i, o, u, x ou X.
SUSv3 mentionne tous les modificateurs précédents à l'exception des extensions non standard. Les spécifications SUSv2 ne mentionnent que les modificateurs de longueur h (dans hd, hi, ho, hx, hX et hn), l (dans ld, li, lo, lx, lX, ln, lc et ls) et L (dans Le, LE, Lf, Lg et LG).
En tant qu’extension non standard, l'implémentation GNU traite ll et L comme des synonymes de façon à ce qu'il soit possible, par exemple, d'écrire llg (comme synonyme conforme aux standards de Lg) et Ld (comme synonyme conforme aux standards de lld). Une telle utilisation n'est pas portable.
Un caractère indique le type de conversion à apporter. Les indicateurs de conversion, et leurs significations sont :
En cas de succès, ces fonctions renvoient le nombre de caractères affichés (sans compter l'octet NULL final utilisé pour terminer les sorties dans les chaînes).
Les fonctions snprintf() et vsnprintf() n'écrivent pas plus de taille octets (y compris l'octet NULL final). Si la sortie a été tronquée à cause de la limite, la valeur de retour est le nombre de caractères (octet NULL final non compris) qui auraient été écrits dans la chaîne s'il y avait eu suffisamment de place. Ainsi, une valeur de retour taille ou plus signifie que la sortie a été tronquée (consultez aussi la section NOTES plus bas).
Si une erreur de sortie s'est produite, une valeur négative est renvoyée.
Pour une explication des termes utilisés dans cette section, consulter attributes(7).
Interface | Attribut | Valeur |
printf(), fprintf(), sprintf(), snprintf(), vprintf(), vfprintf(), vsprintf(), vsnprintf() | Sécurité des threads | MT-Safe locale |
fprintf(), printf(), sprintf(), vprintf(), vfprintf(), vsprintf() : POSIX.1-2001, POSIX.1-2008, C89, C99.
snprintf(), vsnprintf() : POSIX.1-2001, POSIX.1-2008, C99.
dprintf() et vdprintf() sont originellement des extensions GNU. Elles ont été standardisées dans POSIX.1-2008.
En ce qui concerne la valeur de retour de snprintf(), SUSv2 et C99 sont en contradiction : lorsque snprintf() est appelée avec un argument taille=0, SUSv2 précise une valeur de retour indéterminée, inférieure à 1, alors que C99 autorise chaîne à être NULL dans ce cas, et renvoie (comme toujours) le nombre de caractères qui auraient été écrits si la chaîne de sortie avait été assez grande. Les spécifications de snprintf() dans POSIX.1-2001 et ses versions supérieures sont alignées avec C99.
La bibliothèque glibc 2.1 ajoute les modificateurs de longueur hh, j, t et z, et les caractères de conversion a et A.
La bibliothèque glibc 2.2. ajoute le caractère de conversion F avec la sémantique C99, et le caractère d'attribut I.
Certains programmes reposent imprudemment sur du code comme :
sprintf(buf, "%s texte supplémentaire", 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 à la norme 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.
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)).
Un code tel que printf(toto); indique souvent un bogue, car toto peut contenir un caractère « % ». Si toto 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é.
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"
On peut obtenir « Dimanche, 3 juillet, 23:15 ».
Pour allouer une chaîne de taille suffisante et écrire dedans (code correct aussi bien pour la glibc 2.0 que la glibc 2.1) :
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * make_message(const char *fmt, ...) {
int n = 0;
size_t size = 0;
char *p = NULL;
va_list ap;
/* Déterminer la taille requise */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n < 0)
return NULL;
/* One extra byte for '\0' */
size = (size_t) n + 1;
p = malloc(size);
if (p == NULL)
return NULL;
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n < 0) {
free(p);
return NULL;
}
return p; }
En cas de troncature dans les versions de la glibc avant la 2.0.6, c'est traité comme une erreur au lieu d'être traité de façon élégante.
printf(1), asprintf(3), puts(3), scanf(3), setlocale(3), strfromd(3), wcrtomb(3), wprintf(3), locale(5)
Cette page fait partie de la publication 5.10 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies et la dernière version de cette page peuvent être trouvées à l'adresse https://www.kernel.org/doc/man-pages/.
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Frédéric Hantrais <fhantrais@gmail.com> et Grégoire Scano <gregoire.scano@malloc.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
1 novembre 2020 | GNU |