Écrire des fonctions semblables à printf
Arguments variables
Écrire des fonctions semblables à printf est une leçon C Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C Academy comprend 4 leçons au total.
Fonctions qui acceptent une chaîne de format
L’utilisation la plus puissante des fonctions variadiques consiste à créer des fonctions de style printf qui interprètent une chaîne de format.
Le format indique à la fonction combien d’arguments suivent et quel est le type de chacun.
#include <stdio.h>
#include <stdarg.h>
void myprint(const char *fmt, ...) {
printf("format was: %s\n", fmt);
}
int main(void) {
myprint("%d items\n", 5);
return 0;
}Parcourir la chaîne de format
Parcourez le format caractère par caractère. Lorsque vous voyez un %, le caractère suivant est un spécificateur de conversion qui vous indique quel type lire.
Tout le reste est affiché littéralement.
#include <stdio.h>
#include <stdarg.h>
void scan(const char *fmt) {
for (const char *p = fmt; *p; p++) {
if (*p == '%') printf("[spec:%c]", *(p+1));
else putchar(*p);
}
putchar('\n');
}
int main(void) {
scan("x=%d y=%s");
return 0;
}Lire le type correspondant
Lorsque le spécificateur est %d, lisez un int. Pour %s, lisez un char *. Le format doit correspondre exactement aux arguments réels.
#include <stdio.h>
#include <stdarg.h>
void mini(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%' && *(p+1) == 'd') {
printf("%d", va_arg(args, int));
p++;
} else putchar(*p);
}
va_end(args);
}
int main(void) {
mini("count=%d\n", 42);
return 0;
}Gérer plusieurs spécificateurs
Étendez l’analyseur pour gérer plusieurs conversions. Ajoutez des cas pour %d, %s et %c, en lisant à chaque fois le type approprié.
#include <stdio.h>
#include <stdarg.h>
void fmt_print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p != '%') { putchar(*p); continue; }
p++;
if (*p == 'd') printf("%d", va_arg(args, int));
else if (*p == 's') printf("%s", va_arg(args, char *));
else if (*p == 'c') putchar(va_arg(args, int));
}
va_end(args);
}
int main(void) {
fmt_print("%s is %d\n", "age", 30);
return 0;
}Échapper le signe pour cent
Les véritables fonctions de format traitent %% comme un signe pour cent littéral. Ajoutez un cas afin que les utilisateurs puissent afficher un véritable %.
#include <stdio.h>
#include <stdarg.h>
void fp(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
for (const char *p = fmt; *p; p++) {
if (*p == '%') {
p++;
if (*p == '%') putchar('%');
else if (*p == 'd') printf("%d", va_arg(args, int));
} else putchar(*p);
}
va_end(args);
}
int main(void) {
fp("%d%% done\n", 75);
return 0;
}Transmettre à vprintf
Souvent, vous ne souhaitez pas réimplémenter le formatage. La bibliothèque standard propose vprintf, qui accepte directement une va_list.
Votre fonction enveloppe se contente de transmettre ses arguments.
#include <stdio.h>
#include <stdarg.h>
void logline(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
logline("value = %d, name = %s\n", 7, "box");
return 0;
}Ajouter un préfixe
L’approche fondée sur vprintf permet facilement d’ajouter un comportement autour du formatage standard, comme l’affichage d’une étiquette avant chaque message.
#include <stdio.h>
#include <stdarg.h>
void info(const char *fmt, ...) {
printf("[INFO] ");
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
int main(void) {
info("server started on port %d\n", 8080);
return 0;
}Écrire dans un tampon avec vsnprintf
Pour formater une chaîne au lieu de l’afficher, utilisez vsnprintf(buf, size, fmt, args).
La taille est limitée par size, ce qui empêche les dépassements, et la chaîne se termine toujours par un caractère nul.
#include <stdio.h>
#include <stdarg.h>
void format_into(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vsnprintf(buf, n, fmt, args);
va_end(args);
}
int main(void) {
char out[64];
format_into(out, sizeof(out), "id-%d", 123);
printf("%s\n", out);
return 0;
}Renvoyer une longueur
vsnprintf renvoie le nombre de caractères qui auraient été écrits. Vous pouvez l’utiliser pour détecter une troncature ou déterminer la taille d’un tampon.
#include <stdio.h>
#include <stdarg.h>
int build(char *buf, size_t n, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int len = vsnprintf(buf, n, fmt, args);
va_end(args);
return len;
}
int main(void) {
char b[10];
int needed = build(b, sizeof(b), "%d-%d", 11, 22);
printf("%s (needed %d)\n", b, needed);
return 0;
}Choisir votre approche
Deux stratégies sont possibles : analyser vous-même le format pour un contrôle total, ou transmettre les arguments à vprintf/vsnprintf pour obtenir un résultat correct avec moins de code.
Pour la plupart des programmes réels, la transmission est le choix le plus sûr et le plus simple.
#include <stdio.h>
#include <stdarg.h>
void say(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
int main(void) {
say("%s = %.1f\n", "pi", 3.14);
return 0;
}Une incompatibilité entraîne un comportement indéfini
Si la chaîne de format annonce un type qui ne correspond pas à l’argument réel, le comportement est indéfini.
printf("%d", "text") peut provoquer un plantage. Faites toujours correspondre le format et les arguments.
#include <stdio.h>
int main(void) {
int n = 5;
printf("%d\n", n);
return 0;
}Vérification rapide
Vérifiez votre compréhension des fonctions enveloppes de style printf.
Récapitulatif
Vous avez appris à créer des fonctions semblables à printf :
- Prenez une chaîne de format comme paramètre nommé, puis
.... - Analysez vous-même les spécificateurs
%et lisez les types correspondants, ou - transmettez la
va_listà vprintf / vsnprintf pour un formatage sûr et correct. - Faites correspondre le format et les types des arguments afin d’éviter tout comportement indéfini.
Questions Fréquemment Posées
La leçon « Écrire des fonctions semblables à printf » est-elle gratuite ?
Oui — le texte complet de « Écrire des fonctions semblables à printf » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C Academy, passe à CoddyKit PRO. Le cours C Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Écrire des fonctions semblables à printf » ?
Arguments variables Tu pratiques C Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C Academy ?
Aucune expérience préalable n'est requise. C Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Écrire des fonctions semblables à printf » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C Academy ?
Oui. Chaque leçon C Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Macros stdarg
- Écrire des fonctions semblables à printf
- Problèmes de sûreté des types
- Exemples pratiques