I'm working on bringing some old code from 1998 up to the 21st century. One of the first steps in the process is converting the printf statements to QString variables. No matter how many times I look back at printf though, I always end up forgetting one thing or the other. So, for fun, let's decode it together, for ole' times sake and in the process create the first little 'printf primer' for Stackoverflow.

In the code, I came across this little gem,

printf("%4u\t%016.1f\t%04X\t%02X\t%1c\t%1c\t%4s", a, b, c, d, e, f, g);

How will the variables a, b, c, d, e, f, g be formatted?


a. decimal, four significant digits

b. Not sure

c. hex, minimum 4 characters

d. Also hex, minimum 2 characters

e. 1 character

f. String of characters, minimum 4

+3  A: 

Danny is mostly right.

a. unsigned decimal, minimum 4 characters, space padded
b. floating point, minimum 16 digits before the decimal (0 padded), 1 digit after the decimal
c. hex, minimum 4 characters, 0 padded, letters are printed in upper case
d. same as above, but minimum 2 characters
e. e is assumed to be an int, converted to an unsigned char and printed
f. same as e
g. This is likely a typo, the 4 has no effect. If it were "%.4s", then a maximum of 4 characters from the string would be printed. It is interesting to note that in this case, the string does not need to be null terminated.

Edit: jj33 points out 2 errors in b and g above here.

Jason Day
For `g`, the 4 has an effect: if the string is shorter than 4 characters it will be space-padded (on the left).
+5  A: 

@Jason Day, I think the 4 in the last %4s is significant if there are fewer than 4 characters. If there are more than 4 you are right, %4s and %s would be the same, but with fewer than 4 chars in g %s would be left justified and %4s would be right-justified in a 4 char field.

b is actually minimum 16 chars for the whole field, including the decimal and the single digit after the decimal I think (16 total chars vs 18 total chars)

+3  A: 

@jj33, you're absolutely right, on both counts.

#include <stdio.h>

int main(int argc, char *argv[]) {
    char *s = "Hello, World";
    char *s2 = "he";

    printf("4s: '%4s'\n", s);
    printf(".4s: '%.4s'\n", s);
    printf("4s2: '%4s'\n", s2);
    printf(".4s2: '%.4s'\n", s2);

    return 0;

$ gcc -o foo foo.c
$ ./foo
4s: 'Hello, World'
.4s: 'Hell'
4s2: '  he'
.4s2: 'he'

Good catch!

Jason Day
+4  A: 

Here's my printf primer: http://www.pixelbeat.org/programming/gcc/format_specs.html

I always compile with -Wall with gcc which will warn about any mismatches between the supplied printf formats and variables.

I randomly came across this primer months ago and immediately bookmarked. I've used it quite a bit since then. Thanks for taking the time to put it together!

What you really need is a tool which takes the format strings in printf() statements and converts them into equivalent QString based function calls.
Does anyone want to spend his Free Software Donation Time on developing such a tool?

Placeholder for URL to a Free Software hosting service holding the source code of such a tool

Omer Zak
Or you could use QString::sprintf which is part of the QString class and "supports most of the conversion specifiers provided by printf() in the standard C++ library."
David Dibben