cadena printf, elemento de longitud variable

3 minutos de lectura
#define SIZE 9
int number=5;
char letters[SIZE]; /* this wont be null-terminated */
... 

char fmt_string[20];
sprintf(fmt_string, "%%d %%%ds", SIZE);
/* fmt_string = "%d %9d"... or it should be */

printf(fmt_string, number, letters);

¿Hay una mejor manera de hacer esto?

  • Parece que estás construyendo una cadena de formato. Pero deberías estar asignando la cadena devuelta por sprintf para fmt_string y fmt_string no debería estar en la lista de parámetros.

    – pabellón

    9 de mayo de 2011 a las 3:41


  • ¿Hay alguna razón en particular por la que dices eso? letters no será nulo-terminado?

    –Andrew Keeton

    9 de mayo de 2011 a las 3:53

  • @AndrewKeeton esto fue por un problema de búsqueda con un gran conjunto de datos en el que no podía permitirme el espacio para contener caracteres nulos.

    – William Entriken

    11/10/2014 a las 19:46

  • NOTA: esto es una duplicidad de stackoverflow.com/questions/2239519/…

    – pevik

    2 de septiembre de 2016 a las 8:31

avatar de usuario
Trento

No hay necesidad de construir una cadena de formato especial. printf le permite especificar la precisión usando un parámetro (que precede al valor) si usa un .* como la precisión en la etiqueta de formato.

Por ejemplo:

printf ("%d %.*s", number, SIZE, letters);

Nota: hay una distinción entre ancho (que es un ancho de campo mínimo) y precisión (que da el número máximo de caracteres que se imprimirán).
%*s especifica el ancho, %.s especifica la precisión. (y también puedes usar %*.* pero luego necesita dos parámetros, uno para el ancho y uno para la precisión)

Consulte también la página de manual de printf (man 3 printf bajo Linux) y especialmente las secciones sobre ancho de campo y precisión:

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.

  • Los había confundido… scanf es el que no tiene esa opción.

    – William Entriken

    16 de mayo de 2011 a las 3:56

  • También funciona con 2 longitudes como "%*.*s", minlength, maxlength, letters.

    – ott–

    11 de septiembre de 2013 a las 12:39

  • Nota: "*m$" no es estándar C.

    – chux – Reincorporar a Monica

    13/03/2016 a las 23:58

  • ¿Hay alguna forma de aceptar el formato “%.*s”? size_t en lugar de int?

    – Jimmay

    13 de junio de 2016 a las 18:47

avatar de usuario
Nadie en particular

Una función algo desconocida es asprintf. El primer parámetro es un **char. Esta función malloc espacio para la cadena para que no tenga que llevar la contabilidad. Recuerda free la cadena cuando haya terminado.

char *fmt_string;

asprintf(&fmt_string, "%%d %%%ds", SIZE);
printf(fmt_string, number, letters);
free(fmt_string);

es un ejemplo de uso.

  • Aunque asprintf es una función interesante, es importante tener en cuenta que es una extensión gnu. Además, no estoy seguro de cómo esto aborda la pregunta.

    – Trento

    9 de mayo de 2011 a las 4:20

  • @Trent, es cierto que comenzó como una extensión de GNU, pero mientras tanto OpenBSD, FreeBSD y NetBSD haberlo implementado. Incluso Mac OS X lo tiene ahora.

    – Cristian Ciupitu

    14 de octubre de 2014 a las 1:09

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad