13.4. printf(), fprintf()

Print a formatted string to the console or to a file.

Prototypes

#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);

Description

These functions print formatted strings to a file (that is, a FILE* you likely got from fopen()), or to the console (which is usually itself just a special file, right?)

The printf() function is legendary as being one of the most flexible outputting systems ever devisied. It can also get a bit freaky here or there, most notably in the format string. We'll take it a step at a time here.

The easiest way to look at the format string is that it will print everything in the string as-is, unless a character has a percent sign (%) in front of it. That's when the magic happens: the next argument in the printf() argument list is printed in the way described by the percent code.

Here are the most common percent codes:

%d

Print the next argument as a signed decimal number, like 3490. The argument printed this way should be an int.

%f

Print the next argument as a signed floating point number, like 3.14159. The argument printed this way should be a float.

%c

Print the next argument as a character, like 'B'. The argument printed this way should be a char.

%s

Print the next argument as a string, like "Did you remember your mittens?". The argument printed this way should be a char* or char[].

%%

No arguments are converted, and a plain old run-of-the-mill percent sign is printed. This is how you print a '%' using printf)().

So those are the basics. I'll give you some more of the percent codes in a bit, but let's get some more breadth before then. There's actually a lot more that you can specify in there after the percent sign.

For one thing, you can put a field width in there--this is a number that tells printf() how many spaces to put on one side or the other of the value you're printing. That helps you line things up in nice columns. If the number is negative, the result becomes left-justified instead of right-justified. Example:

printf("%10d", x);  /* prints X on the right side of the 10-space field */
printf("%-10d", x); /* prints X on the left side of the 10-space field */

If you don't know the field width in advance, you can use a little kung-foo to get it from the argument list just before the argument itself. Do this by placing your seat and tray tables in the fully upright position. The seatbelt is fastened by placing the--*cough*. I seem to have been doing way too much flying lately. Ignoring that useless fact completely, you can specify a dynamic field width by putting a * in for the width. If you are not willing or able to perform this task, please notify a flight attendant and we will reseat you.

int width = 12;
int value = 3490;

printf("%*d\n", width, value);

You can also put a "0" in front of the number if you want it to be padded with zeros:

int x = 17;
printf("%05d", x);  /* "00017" */

When it comes to floating point, you can also specify how many decimal places to print by making a field width of the form "x.y" where x is the field width (you can leave this off if you want it to be just wide enough) and y is the number of digits past the decimal point to print:

float f = 3.1415926535;

printf("%.2f", f);  /* "3.14" */
printf("%7.3f", f); /* "  3.141" <-- 7 spaces across */

Ok, those above are definitely the most common uses of printf(), but there are still more modifiers you can put in after the percent and before the field width:

0

This was already mentioned above. It pads the spaces before a number with zeros, e.g. "%05d".

-

This was also already mentioned above. It causes the value to be left-justified in the field, e.g. "%-5d".

' ' (space)

This prints a blank space before a positive number, so that it will line up in a column along with negative numbers (which have a negative sign in front of them). "% d".

+

Always puts a + sign in front of a number that you print so that it will line up in a column along with negative numbers (which have a negative sign in front of them). "%+d".

#

This causes the output to be printed in a different form than normal. The results vary based on the specifier used, but generally, hexidecimal output ("%x") gets a "0x" prepended to the output, and octal output ("%o") gets a "0" prepended to it. These are, if you'll notice, how such numbers are represented in C source. Additionally, floating point numbers, when printed with this # modified, will print a trailing decimal point even if the number has no fractional part. Example: "%#x".

Now, I know earlier I promised the rest of the format specifiers...so ok, here they are:

%i

Just like %d, above.

%o

Prints the integer number out in octal format. Octal is a base-eight number representation scheme invented on the planet Krylon where all the inhabitants have only eight fingers.

%u

Just like %d, but works on unsigned ints, instead of ints.

%x or %X

Prints the unsigned int argument in hexidecimal (base-16) format. This is for people with 16 fingers, or people who are simply addicted hex, like you should be. Just try it! "%x" prints the hex digits in lowercase, while "%X" prints them in uppercase.

%F

Just like "%f", except any string-based results (which can happen for numbers like infinity) are printed in uppercase.

%e or %E

Prints the float argument in exponential (scientific) notation. This is your classic form similar to "three times 10 to the 8th power", except printed in text form: "3e8". (You see, the "e" is read "times 10 to the".) If you use the "%E" specifier, the the exponent "e" is written in uppercase, a la "3E8".

%g or %G

Another way of printing doubles. In this case the precision you specific tells it how many significant figures to print.

%p

Prints a pointer type out in hex representation. In other words, the address that the pointer is pointing to is printed. (Not the value in the address, but the address number itself.)

%n

This specifier is cool and different, and rarely needed. It doesn't actually print anything, but stores the number of characters printed so far in the next pointer argument in the list.

int numChars;
float a = 3.14159;
int b = 3490;

printf("%f %d%n\n", a, b, &numChars);
printf("The above line contains %d characters.\n", numChars);

The above example will print out the values of a and b, and then store the number of characters printed so far into the variable numChars. The next call to printf() prints out that result.

So let's recap what we have here. We have a format string in the form:

"%[modifier][fieldwidth][.precision][lengthmodifier][formatspecifier]"

Modifier is like the "-" for left justification, the field width is how wide a space to print the result in, the precision is, for floats, how many decimal places to print, and the format specifier is like %d.

That wraps it up, except what's this "lengthmodifier" I put up there?! Yes, just when you thought things were under control, I had to add something else on there. Basically, it's to tell printf() in more detail what size the arguments are. For instance, char, short, int, and long are all integer types, but they all use a different number of bytes of memory, so you can't use plain old "%d" for all of them, right? How can printf() tell the difference?

The answer is that you tell it explicitly using another optional letter (the length modifier, this) before the type specifier. If you omit it, then the basic types are assumed (like %d is for int, and %f is for float).

Here are the format specifiers:

h

Integer referred to is a short integer, e.g. "%hd" is a short and "%hu" is an unsigned short.

l ("ell")

Integer referred to is a long integer, e.g. "%ld" is a long and "%lu" is an unsigned long.

hh

Integer referred to is a char integer, e.g. "%hhd" is a char and "%hhu" is an unsigned char.

ll ("ell ell")

Integer referred to is a long long integer, e.g. "%lld" is a long long and "%llu" is an unsigned long long.

I know it's hard to believe, but there might be still more format and length specifiers on your system. Check your manual for more information.

Return Value

Example

    int a = 100;
    float b = 2.717;
    char *c = "beej!";
    char d = 'X';
    int e = 5;

    printf("%d", a); /* "100"      */
    printf("%f", b); /* "2.717000" */
    printf("%s", c); /* "beej!"    */
    printf("%c", d); /* "X"        */
    printf("110%%"); /* "110%"     */

    printf("%10d\n", a);   /* "       100" */
    printf("%-10d\n", a);  /* "100       " */
    printf("%*d\n", e, a); /* "  100"      */
    printf("%.2f\n", b);   /* "2.71"       */

    printf("%hhd\n", c); /* "88" <-- ASCII code for 'X' */
    
    printf("%5d %5.2f %c\n", a, b, d); /* "  100  2.71 X" */

See Also

sprintf(), vprintf(), vfprintf(), vsprintf()