Variable Width Values in Conversion Characters

The topic of conversion characters, or printf() percent placeholders, is vast and confusing. Most programmers know the basics, but the details are so complex that some handy shortcuts are overlooked. One of those shortcuts is the * wildcard that sets width values.

The tables and examples of conversion characters found in the K&R book are dry and lack examples. In my books, I try to spice them up, but I must be choosy because too much detail makes the reader’s eyes glaze over. With so many options, variations, and choices, it would consume too many pages to document everything. Without a zippy plot, no one would read it.

Here on the C Blog, I’ve reviewed various placeholder options in my Conversion Character series. My approach is by variable type as opposed to the placeholder letters. So I didn’t even mention the * option. In the K&R book, the paragraph after the conversion character table goes:

A width or precision may be specified as *, in which case the value is computed by converting the next argument (which must be an int).

An example is provided, but — seriously — at that point in your C education, you’re so overwhelmed that the text merrily slips into the ether. Yet, the * width specifier is useful and kind of fun.

As an example, the %f placeholder converts float values and variables. To set precision, you use a width format such as %.2f, which outputs only two digits after the decimal. If you instead use %.*f, you can add an int argument to the printf() function to set the precision at runtime:

#include <stdio.h>
#include <math.h>

int main()
{
    int x;

    for(x=1;x<=10;x++)
        printf("%.*f\n",x,M_PI);

    return(0);
}

In the above code, the value of π (defined as M_PI in the math.h header file) is displayed in degrees of precision from 1 to 10. The placeholder is %.*f. Variable x in the printf() statement sets the width. Here’s the output:

3.1
3.14
3.142
3.1416
3.14159
3.141593
3.1415927
3.14159265
3.141592654
3.1415926536

For other placeholders that specify width, you sandwich the * between the % and the conversion character:

#include <stdio.h>

int main()
{
    int x;

    for(x=6;x<=16;x++)
        printf("%*s\n",x,"Hello!");

    return(0);
}

The above code uses the %*s placeholder to set a variable width for string output. Strings are right-aligned by default, so the effect is that the string moves to the right within a variable-width space, as the output shows:

Hello!
 Hello!
  Hello!
   Hello!
    Hello!
     Hello!
      Hello!
       Hello!
        Hello!
         Hello!
          Hello!

Upon reviewing my own code, I see that I’ve used the sprintf() function instead of the * character; sprintf() created a formatting string for printf(), one that used variable width. Using the * instead would have been better. I shall remember to do so in the future!

Leave a Reply