Scrivere funzioni simili a printf
Argomenti variabili
Scrivere funzioni simili a printf è una lezione C Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C Academy include 4 lezioni in totale.
Funzioni che accettano una stringa di formato
L'uso più potente delle funzioni variadiche consiste nel creare funzioni nello stile di printf che interpretano una stringa di formato.
Il formato indica alla funzione quanti argomenti seguono e qual è il tipo di ciascuno.
#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;
}Scorrere la stringa di formato
Analizzi il formato carattere per carattere. Quando trova un %, il carattere successivo è uno specificatore di conversione che indica quale tipo leggere.
Tutto il resto viene stampato letteralmente.
#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;
}Leggere il tipo corrispondente
Quando lo specificatore è %d, legga un int. Per %s legga un char *. Il formato deve corrispondere esattamente agli argomenti effettivi.
#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;
}Gestire più specificatori
Estenda l'analizzatore in modo da gestire diverse conversioni. Aggiunga casi per %d, %s e %c, leggendo ogni volta il tipo corretto.
#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;
}Eseguire l'escape del simbolo di percentuale
Le vere funzioni di formato trattano %% come un simbolo di percentuale letterale. Aggiunga un caso per consentire agli utenti di stampare un vero %.
#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;
}Delegare a vprintf
Spesso non è necessario reimplementare la formattazione. La libreria standard offre vprintf, che accetta direttamente una va_list.
Il wrapper si limita a passargli gli argomenti.
#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;
}Aggiungere un prefisso
L'approccio con vprintf semplifica l'aggiunta di comportamenti attorno alla formattazione standard, ad esempio la stampa di un tag prima di ogni messaggio.
#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;
}Scrivere in un buffer con vsnprintf
Per formattare una stringa invece di stamparla, usi vsnprintf(buf, size, fmt, args).
La funzione è limitata da size, impedendo l'overflow, e termina sempre la stringa con il carattere nullo.
#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;
}Restituire una lunghezza
vsnprintf restituisce il numero di caratteri che sarebbero stati scritti. Può usare questo valore per rilevare il troncamento o dimensionare un buffer.
#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;
}Scegliere l'approccio
Esistono due strategie: analizzare personalmente il formato per avere il pieno controllo oppure delegare a vprintf/vsnprintf per ottenere correttezza e scrivere meno codice.
Nella maggior parte del codice reale, delegare è la scelta più sicura e semplice.
#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;
}La mancata corrispondenza è indefinita
Se la stringa di formato indica un tipo che non corrisponde all'argomento effettivo, il comportamento è indefinito.
printf("%d", "text") potrebbe causare un arresto anomalo. Mantenga sempre sincronizzati formato e argomenti.
#include <stdio.h>
int main(void) {
int n = 5;
printf("%d\n", n);
return 0;
}Verifica rapida
Verifichi la Sua comprensione dei wrapper nello stile di printf.
Riepilogo
Ha imparato a creare funzioni simili a printf:
- Accettino una stringa di formato come parametro denominato, seguita da
.... - Può analizzare personalmente gli specificatori
%e leggere i tipi corrispondenti, oppure - delegare la
va_lista vprintf / vsnprintf per una formattazione sicura e corretta. - Mantenga sincronizzati il formato e i tipi degli argomenti per evitare un comportamento indefinito.
Domande Frequenti
La lezione «Scrivere funzioni simili a printf» è gratuita?
Sì — il testo completo di «Scrivere funzioni simili a printf» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C Academy, passa a CoddyKit PRO. Il corso C Academy include 4 lezioni in totale.
Cosa imparerò in «Scrivere funzioni simili a printf»?
Argomenti variabili Eserciti C Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare C Academy?
Non è richiesta alcuna esperienza precedente. C Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Scrivere funzioni simili a printf»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione C Academy?
Sì. Ogni lezione C Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Macro stdarg
- Scrivere funzioni simili a printf
- Problemi di sicurezza dei tipi
- Esempi pratici