printf string, variable length item

88,308

Solution 1

There is no need to construct a special format string. printf allows you to specify the precision using a parameter (that precedes the value) if you use a .* as the precision in the format tag.

For example:

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

Note: there is a distinction between width (which is a minimum field width) and precision (which gives the maximum number of characters to be printed). %*s specifies the width, %.s specifies the precision. (and you can also use %*.* but then you need two parameters, one for the width one for the precision)

See also the printf man page (man 3 printf under Linux) and especially the sections on field width and precision:

Instead of a decimal digit string one may write "*" or "*m$" (for some decimal integer m) to specify that the precision is given in the next argument, or in the m-th argument, respectively, which must be of type int.

Solution 2

A somewhat unknown function is asprintf. The first parameter is a **char. This function will malloc space for the string so you don't have to do the bookkeeping. Remember to free the string when done.

char *fmt_string;

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

is an example of use.

Share:
88,308
William Entriken
Author by

William Entriken

Lead author of ERC-721. Personal website and contact information: https://phor.net Promoting two open source projects: https://github.com/fulldecent/web-puc - A script to validate you are using the latest JQuery, Bootstrap, Font Awesome versions in your favorite PHP or other web front-end (compatible with Travis CI) https://fulldecent.github.io/cameralife/ - Mature LAMP project for displaying large photo collections on the web (i.e. your life work)

Updated on July 09, 2022

Comments

  • William Entriken
    William Entriken almost 2 years
    #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);
    

    Is there a better way to do this?

  • Trent
    Trent about 13 years
    Although asprintf is indeed an interesting function, it is important to note that it is a gnu extention. Also, I'm not sure how this addresses the question.
  • William Entriken
    William Entriken almost 13 years
    Had them mixed up... scanf is the one that doesn't have that option.
  • ott--
    ott-- over 10 years
    It also works with 2 lengths like "%*.*s", minlength, maxlength, letters.
  • Cristian Ciupitu
    Cristian Ciupitu over 9 years
    @Trent, it's true that it started as a GNU extension, but in the mean time OpenBSD, FreeBSD and NetBSD have implemented it. Even Mac OS X has it now.
  • chux - Reinstate Monica
    chux - Reinstate Monica about 8 years
    Note: "*m$" is not standard C.
  • Jimmay
    Jimmay almost 8 years
    Is there a way to get the "%.*s" format to accept size_t instead of int?