Section: Manual del Programador de Linux (3)
Updated: 25 noviembre 1999
Index Return to Main
Contents
printf, fprintf, sprintf, vprintf, vfprintf, vsprintf - conversión de salida formateada
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);
Las funciones de la familia printf producen una salida de acuerdo a format como se describe abajo. Printf y vprintf escriben su salida a stdout, el flujo de salida estándar. fprintf y vfprintf escriben su salida al stream de salida dado. sprintf, snprintf, vsprintf y vsnprintf escriben a una cadena de caracteres str.
Las funciones vprintf, vfprintf, vsprintf y vsnprintf son equivalentes a las funciones printf, fprintf, sprintf y snprintf, respectivamente, salvo en que se las llama con un va_list en lugar de con un número variable de argumentos. Estas funciones no llaman a la macro va_end. En consecuencia, el valor de ap queda indefinido después de la llamada. La propia aplicación debería llamar a va_end(ap) después.
Estas ocho funciones escriben la salida bajo el control de una cadena format que especifica cómo los argumentos posteriores (o los argumentos accedidos mediante las facilidades de argumentos de longitud variables proporionadss por stdarg(3)) son convertidos para su salida.
Estas funciones devuelven el número de caracteres impresos (no incluyendo el carácter `\0' usado para terminar la salida de cadenas). snprintf y vsnprintf no escriben más de size bytes (incluyendo el carácter terminador '\0'), y devuelven -1 si la salida se ha truncado debido a esta limitación. (Así es hasta la versión 2.0.6 de glibc. Desde la versión 2.1 estas funciones siguen el estándar C99 y devuelven el número de caracteres (excluyendo el carácter terminador '\0') que se habrían escrito en la cadena final si hubiera habido suficiente espacio.)
La cadena de formato es una cadena de caracteres que comienza y termina en su estado de cambios inicial, si lo hay. La cadena format está compuesta de cero o más directivas: caracteres ordinarios (no %) que se copian sin cambios al flujo de salida, e indicaciones de conversión, cada uno de las cuales produce la búsqueda de cero o más argumentos posteriores. Cada especificación de conversión se introduce mediante el carácter % y termina con un indicador de conversión. En medio puede haber (en este orden) cero o más opciones, una anchura de campo opcional mínima, una precisión opcional y un modificador de longitud opcional.
Los argumentos se deben corresponder adecuadamente (después de la promoción de tipos) con el indiciador de conversión. Por defecto, los argumentos se usan en el orden dado, donde cada `*' y cada indicador de conversión pregunta por el siguiente argumento (y es un error si se dan de forma insuficiente muchos argumentos). También se puede especificar explícitamente qué argumento se toma, en cada lugar donde se necesite un argumento, escribiendo `%m$' en lugar de `%' y `*m$' en lugar de `*', donde el entero decimal m denota la posición en la lista de argumentos del argumento deseado, empezando por 1. Por tanto,
printf("%*d", width, num);
y
printf("%2$*1$d", width, num);
son equivalentes. El segundo estilo permite referencias repetidas al mismo argumento. El estándar C99 no permite mezclar ambos estilos.
Para alguna conversión numérica se usa un carácter radical (`punto decimal') o carácter separador de miles. El carácter real usado depende de la parte LC_NUMERIC de la localización. La localizacíon POSIX usa `.' como carácter radical y no posee un carácter separador de miles. Por tanto,
printf("%'.2f", 1234567.89);
produce `1234567.89' en la localización POSIX, `1234567,89' en la localización nl_NL, y `1.234.567,89' en la localización da_DK.
El carácter % va seguido por cero o más de las siguientes opciones:
Los cinco carácteres de opción anteriores se definen en el estándar C. SUSv2 especifica un carácter de opción adicional.
Una cadena de dígitos decimales opcional (con un primer dígito distinto de cero) que especifica una anchura de campo mínimo. Si el valor convertido tiene menos caracteres que la anchura del campo, se rellenará con espacios a la izquierda (o a la derecha, si se da la opción de justificación a la izquierda). En lugar de una cadena de dígitos decimales se puede escribir `*' o `*m$' (para algún entero decimal m) para especificar que la anchura del campo se proporciona en el siguiente argumento o en el m-ésimo argumento, respectivamente, que debe ser de tipo int. Una anchura de campo negativa se toma como una opción `-' seguida por una anchura de campo positiva. En ningún caso, una anchura de campo inexistente o pequeña hace que el campo se trunque. Si el resultado de la conversión es más ancho que la anchura del campo, el campo se expande para contener el resultado de la conversión.
Una precisión opcional, indicada por un punto (`.') seguido por una cadena de dígitos también opcional. En lugar de una cadena de dígitos decimales se puede escribir `*' o `*m$' (para algún entero decimal m) para especificar que la precisión se da en el siguiente argumento o en el m-ésimo argumento, respectivamente, que debe ser de tipo int. Si la precisión se da como un simple `.', o si la precisión es negativa, la precisión se toma como cero. Esto da el número mínimo de dígitos que deben aparecer en las conversiones d, i, o, u, x, y X, el número de dígitos que deben aparacer tras el carácter radical en las conversiones a, A, e, E, f y F, el máximo número de dígitos significativos para las conversiones g y G, o el máximo número de caracteres a imprimir de una cadena en las conversiones s y S.
Aquí, `conversión entera' significa una conversión d, i, o, u, x, o X.
SUSv2 sólo conoce los indicadores de longitud h (en hd, hi, ho, hx, hX, hn), l (en ld, li, lo, lx, lX, ln, lc, ls) y L (en Le, LE, Lf, Lg, LG).
Un carácter que especifica el tipo de conversión a ser aplicado. Los indicadores de conversión y sus significados son:
(SUSv2 no conoce F y dice que deben estar disponibles reprentaciones como cadenas de caracteres para infinito y NaN (Not a Number, no es un número). El estándar C00 especifica `[-]inf' o `[-]infinity' para el infinito y una cadena que comienza por `Nan' para NaN, en el caso de una conversión f, y `[-]INF' o `[-]INFINITY' o `NAN*' en el caso de una conversión F.)
Para imprimir con cinco cifras decimales:
#include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
Para imprimir una fecha y una hora de la forma `Sunday, July 3, 10:02', donde weekday y month son punteros a cadenas:
#include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
Muchos países usan el orden día-mes-año. Por tanto, una versión internacionalizada debe ser capaz de mostrar los argumentos en el orden indicado por el formato:
#include <stdio.h> fprintf(stdout, formato, diasemana, mes, día, hora, min);
donde formato depende de la localización y puede permutar los argumentos. Con el valor
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
se podría obtener `sonntag, 3. Juli, 10:02'.
Para reservar una cadena de 128 bytes e imprimir dentro de ella: Para reservar una cadena suficientemente grande e imprimir dentro de ella: (código correcto tanto para glibc 2.0 como glibc 2.1):
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char * construye_mensaje(const char *fmt, ...) { /* Suponemos que no necesitamos más de 100 bytes. */ int n, size = 100; char *p; va_list ap; if ((p = malloc (size)) == NULL) return NULL; while (1) { /* Intenta imprimir en el espacio reservado. */ va_start(ap, fmt); n = vsnprintf (p, size, fmt, ap); va_end(ap); /* Si ha funcionado, devuelve la cadena. */ if (n > -1 && n < size) return p; /* Si no, inténtalo de nuevo con más espacio. */ if (n > -1) /* glibc 2.1 */ size = n+1; /* exactamente lo que se necesita */ else /* glibc 2.0 */ size *= 2; /* el doble del tamaño anterior*/ if ((p = realloc (p, size)) == NULL) return NULL; } }
(1), wcrtomb(3), wprintf(3), scanf(3), locale(5)
Las funciones fprintf, printf, sprintf, vprintf, vfprintf, y vsprintf están conforme a ANSI C3.159-1989 (``ANSI C'') e ISO/IEC 9899:1999 (``ISO C99''). Las funciones snprintf y vsnprintf están conforme a ISO/IEC 9899:1999.
Teniendo en cuenta el valor devuelto pr snprintf, SUSv2 y el estándar C99 se contradicen: cuando snprintf se llama con size=0, SUSv2 estipula un valor devuelto sin especificar menor que 1, mientras que C99 permite que str sea NULL en este caso y da el valor devuelto (como siempre) como el número de caracteres que habrían sido escritos en el caso de que la cadena de salida hubiera sido lo suficientemente grande.
La libc4 de Linux reconoce las cinco opciones estándares de C. Reconoce los modificadores de longitud h, l y L, y las conversiones cdeEfFgGinopsuxX, donde F es un sinónimo de f. Adicionalmente, acepta D, O y U, como sinónimos de ld, lo y lu. (Esto es malo y provocó serios fallos más tarde, cuando desapareció el soporte para %D). No reconoce un carácter radical dependiente de la localización, ni un separador de miles, ni NaN ni infinito, ni %m$ ni *m$.
La libc5 de Linux reconoce las seis opciones, la localización, %m$ y *m$. Reconoce los modificadores de longitud h, l, L, Z y q, pero acepta L y q, ambos para valores long double y long long integer (esto es un fallo). Ya no reconoce más FDOU, pero añade un nuevo carácter de conversión m, que produce strerror(errno).
glibc2.0 añade los caracteres de conversión C y S.
glibc2.1 añade los modificadores de longitud hh, j, t y z, y los caracteres de conversión a y A.
Unix V7 define las tres rutinas printf, fprintf, sprintf, y posee la opción -, la anchura o precisión *, el modificador de longitud l, las conversiones doxfegcsu, y también D, O, U y X como sinónimos de ld, lo, lu y lx. Esto todavía es cierto para BSD 2.9.1, pero BSD 2.10 tiene las opciones #, + y <space> y ya no menciona D, O, U y X. BSD 2.11 tiene vprintf, vfprintf, vsprintf, y advierte de no usar D, O, U y X. BSD 4.3 Reno tiene la opción 0, los modificadores de longitud h y L, las conversiones n, p, E, G, X (con el significado actual) y hace obsoletas D, O y U. BSD 4.4 introduce las funciones snprintf y vsnprintf, y el modificador de longitud q. FreeBSD también posee las funciones asprintf y vasprintf, que reservan un buffer los suficientemente largo para sprintf.
Ya que sprintf y vsprintf asumen una cadena de longitud arbitraria, los invocadores deben tener cuidado de no sobrepasar el espacio actual. A menudo, esto es imposible de garantizar. Advierta que las longitudes de las cadenas producidas dependen de la localización y que son difíciles de predecir. Use snprintf y vsnprintf en su lugar.
La libc4.[45] de Linux no posee la función snprintf, pero proporciona una libbsd que contiene una función snprintf equivalente a sprintf, es decir, una que ignora el argumento size. Por tanto, el uso de snprintf con las primeras libc4 conduce a serios problemas de seguridad.
Algunas conversiones de punto flotante en las primeras libc4 producían pérdidas de memoria.
This document was created by man2html, using
the manual pages.
Time: 06:16:22 GMT, January 22, 2005