0Pricing
C Academy · Lección

Escritura de funciones similares a printf

Argumentos variables

Escritura de funciones similares a printf es una lección gratuita de C Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C Academy incluye 4 lecciones en total.

Funciones que aceptan una cadena de formato

El uso más potente de los argumentos variádicos es crear funciones de estilo printf que interpretan una cadena de formato.

El formato indica a la función cuántos argumentos siguen y qué tipo tiene cada uno.

#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;
}

Recorrer la cadena de formato

Analice el formato carácter por carácter. Cuando vea un %, el carácter siguiente será un especificador de conversión que le indicará qué tipo debe leer.

Todo lo demás se imprime literalmente.

#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;
}

Leer el tipo correspondiente

Cuando el especificador sea %d, lea un int. Para %s, lea un char *. El formato debe coincidir exactamente con los argumentos reales.

#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;
}

Gestionar varios especificadores

Amplíe el analizador para gestionar varias conversiones. Añada casos para %d, %s y %c, leyendo el tipo correcto cada vez.

#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;
}

Escapar el signo de porcentaje

Las funciones de formato reales tratan %% como un signo de porcentaje literal. Añada un caso para que los usuarios puedan imprimir un % real.

#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;
}

Reenviar a vprintf

A menudo no querrá volver a implementar el formato. La biblioteca estándar ofrece vprintf, que acepta directamente una va_list.

Su envoltorio solo reenvía los argumentos.

#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;
}

Añadir un prefijo

El enfoque con vprintf facilita añadir comportamiento alrededor del formato estándar, como imprimir una etiqueta antes de cada mensaje.

#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;
}

Escribir en un búfer con vsnprintf

Para dar formato a una cadena en lugar de imprimirla, use vsnprintf(buf, size, fmt, args).

Está limitado por size, lo que evita desbordamientos, y siempre termina la cadena con un carácter nulo.

#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;
}

Devolver una longitud

vsnprintf devuelve el número de caracteres que se habrían escrito. Puede usarlo para detectar truncamientos o calcular el tamaño de un búfer.

#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;
}

Elegir el enfoque

Hay dos estrategias: analizar el formato usted mismo para tener un control total, o reenviarlo a vprintf/vsnprintf para obtener corrección con menos código.

En la mayoría del código real, reenviar los argumentos es la opción más segura y sencilla.

#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;
}

Las discrepancias provocan comportamiento indefinido

Si la cadena de formato indica un tipo que no coincide con el argumento real, el comportamiento es indefinido.

printf("%d", "text") puede provocar un fallo. Mantenga siempre sincronizados el formato y los argumentos.

#include <stdio.h>

int main(void) {
    int n = 5;
    printf("%d\n", n);
    return 0;
}

Comprobación rápida

Compruebe su comprensión de los envoltorios de estilo printf.

Resumen

Ha aprendido a crear funciones similares a printf:

  • Acepte una cadena de formato como parámetro con nombre y, después, ....
  • Analice usted mismo los especificadores % y lea los tipos correspondientes, o
  • reenvíe la va_list a vprintf / vsnprintf para obtener un formato seguro y correcto.
  • Mantenga sincronizados el formato y los tipos de los argumentos para evitar un comportamiento indefinido.

Preguntas frecuentes

¿La lección «Escritura de funciones similares a printf» es gratis?

Sí — el texto completo de «Escritura de funciones similares a printf» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C Academy, actualiza a CoddyKit PRO. El curso de C Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Escritura de funciones similares a printf»?

Argumentos variables Practicas C Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar C Academy?

No se requiere experiencia previa. C Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Escritura de funciones similares a printf»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de C Academy?

Sí. Cada lección de C Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Macros de stdarg
  2. Escritura de funciones similares a printf
  3. Consideraciones sobre la seguridad de tipos
  4. Ejemplos prácticos
← Volver a C Academy