Formatted Output and The Printf Function
Formatted Output and The Printf Function
C has a family of library functions that provide this capability. All of these functions reside in the stdio library.
Although the library contains several functions for printing formatted output, it is likely that you will only use
two of them with any frequency. One, the printf (short for "print formatted") function, writes output to the
computer monitor. The other, fprintf, writes output to a computer file. They work in almost exactly the same
way, so learning how printf works will give you (almost) all the information you need to use fprintf.
When you actually use the printf function, that is, when you want your program to print something on the
screen, you will place a call to the function in your source code. When we want a function to perform its task we
say we "call" it, and a function call is a type of program statement. All function calls have the same basic format.
The first part of the call is always the name of the function (in this case, printf). Following the function name is
an argument list or parameter list. The terms "argument" and "parameter" are synonymous in computer
programming. An argument list provides information for the function. In the same way that a mathematical
function takes some input value, performs a transformation, and produces a result (output), functions in C
typically require some input as well. For the printf function, the argument list will provide the information that
the function should print to the screen. We generally say that we pass arguments to a function.
An argument list has a particular form as well. First, a pair of parentheses always encloses the list of arguments.
Inside the parentheses, we separate multiple arguments from each other with a comma. Since a function call is a
kind of statement, you will also need to follow the call with a semicolon, just after the closing parenthesis of the
argument list. We can formalize a function call then as follows:
function_name (argument1, argument2, ...);
The "..." signifies that there may be more arguments. In fact, there may also be fewer arguments.
Different functions require different kinds of input. Some functions need only one parameter, others may need
many, and some do not need any parameters at all. In this last case, the argument list would simply be a pair of
parentheses with nothing inside. In most cases, any given function needs a particular number of parameters. That
is, we might have a function that requires three pieces of information to perform its task. Every time we call that
function, we will need to provide exactly three parameters in its argument list. The printf function is unusual,
because the number of parameters it needs is variable. It always requires at least one argument, called the format
string. Depending on what this argument contains, we may need to pass other parameters to printf as well.
In C, a "string" is a sequence of one or more characters that the programmer intends to use as a unit (such as a
word or sentence). The first program you saw printed a sentence, "Hello world," to the screen. The series of
characters that forms this sentence is a string. To ensure that the compiler processes a string as a string, rather
than as identifiers, we use a pair of double quotes around a string constant to show that it is a string. This is quite
similar to using single quotes to indicate a character constant. It is important to remember that the single and
https://eecs.wsu.edu/~cs150/reading/printf.htm 1/11
11/19/2020 Formatted Output and the printf function
double quotes are not interchangeable. Later, you will learn the difference between a one-character string, such
as "a" and a single character, such as 'a'. For now, you must simply try to remember that they are different. The
following mnemonic may help you remember when to use double quotes and when to use single quotes. A
character is always just one character, while a string usually contains several characters. Thus, a character is
usually "shorter" than a string. The single quote is also "shorter" than the double quote, so you use the "short"
with the "short."
In its simplest form, a format string is just a series of characters that you want to print to the screen. It will print
exactly as it appears in the argument list, except that the double quotes will not appear. This is generally how
you would use printf to print a prompt to request that the user of a program enter some data. For example, if you
wanted to ask a user to type a number, you might call printf as follows:
printf ("Please type an integer then press Enter: ");
When the computer executes this statement, the message will appear on the screen:
You will often use this simplest kind of format string when you want to display some sort of status message or
explanation on the screen. For instance, if you wrote a program that you knew would take some time to perform
a task, you would probably want to let the user know that the program was working and had not crashed. You
might use printf to tell the user what the program is doing:
printf ("Searching, please wait...");
On the screen, you would see:
In both of the examples above, once the message has appeared, the cursor will remain at the end of the printed
output. If you called printf again, the next message would appear immediately after the first one. Usually, this
will not be what you want. Instead, you will want to print the next message on the next line of the screen, but
you will need to tell printf to do this; it will not happen automatically. You know that if you are typing that you
press the Enter key to get from one line to the next, but, as a programmer, if you press the Enter key inside the
double quotes of the format string, the cursor will go to the next line of your source code file. If you then type
the double quote, closing parenthesis, and semicolon and then try to compile the program, the compiler will give
you a syntax error. Usually, the error message will tell you that you have an "unterminated string constant." This
is because the compiler expects to find the closing double quote on the same line as the opening double quote.
https://eecs.wsu.edu/~cs150/reading/printf.htm 2/11
11/19/2020 Formatted Output and the printf function
Here are a few more examples of printf statements that make use of escape sequences:
printf ("\nName\tAddress\n");
produces:
Name Address
|
Joe's Dine|
As you can see, escape sequences give us some ability to format output even when we use the simplest form or
the printf function, but printf is actually much more powerful than we have seen. First, assume for a moment
that you have declared a variable in your program as follows:
int number = 10;
Now suppose that you want to prove to yourself that the variable number really does hold the value 10. You
want to display the string "The value of number is 10" on the screen. You might try calling printf as follows:
https://eecs.wsu.edu/~cs150/reading/printf.htm 3/11
11/19/2020 Formatted Output and the printf function
The problem is that within the program's source code, we have only one way to refer to the variable number and
that is by its name. The names of identifiers are made up of characters, so if we place a variable's name in a
format string, printf will simply print that name. Just as C solves the problem of displaying special characters
within a format string through the use of escape sequences, it solves this problem using another special notation
within the format string. Besides escape sequences, the format string argument can also contain format
specifiers. A format specifier is a placeholder that performs two functions. First, it shows where in the output to
place an item not otherwise represented in the format string and it indicates how printf should represent the
item. The "item" is most often a variable, but it can also be a constant. In particular, format specifiers allow us
to print the values of variables as well as printing their names.
All format specifiers begin with a percent sign, just as all escape sequences begin with a backslash. What
follows the percent sign tells at least what data type printf should expect to print. It can also indicate exactly
how the programmer wants printf to display it. Schematically, we can represent the syntax for a format specifier
as follows:
%[flags][width][.precision]type_character
As usual, italics indicate placeholders for which a programmer must substitute a specific value. The square
brackets that appear in this syntax template mean that the placeholders within are optional. They can appear or
not, as the needs of the programmer dictate. The brackets themselves do not appear in the source program. Most
of the time, format specifiers will not include any of the optional items. The options give the programmer
precise control over the spacing of the output and even over how much of the output printf will display. Thus,
most often a format specifier will simply be a percent sign followed by a "type character." The type character is
what tells printf what data type to print. The following table shows the most common type characters (several
others exist):
For example, the format string "%d" indicates to printf that it should write an integer in base 10 format, whereas
the format string "%s" tells printf to print a string. Notice that the format specifiers tell what kind of thing the
programmer wants to display, but they do not tell what value to print. That means that printf will need some
additional information in the form of an additional argument. A format string can contain more than one format
specifier and the format specifier(s) can appear in conjunction with other text, including escape sequences. Each
format specifier that appears in the format string requires an additional argument in the argument list. The
additional argument specifies what value printf should substitute for the format specifier. For instance, the
following call to printf will display the value of our variable number:
printf ("The value of number is %d\n", number);
https://eecs.wsu.edu/~cs150/reading/printf.htm 4/11
11/19/2020 Formatted Output and the printf function
The two arguments to this call to printf combine to tell the function exactly what to write on the screen. What
happens is that the printf function actually takes apart the format string and checks each character before
displaying it. Whenever it encounters the percent sign, it checks the next character. If the next character is a type
character, printf retrieves the next argument in the argument list and prints its value. If the next character is not a
type character, printf simply displays the percent sign. For example,
printf ("The value of number is %q\n", number);
will print:
Although it is unlikely that you will ever really want to do so, you may be asking, "so what if I want to print
something like '%d' on the screen." If printf finds the sequence %d in a format string, it will substitute a value
for it. To print one of the format specifiers to the screen, then, you have to "trick" printf. The following call:
printf ("The % \bd format specifier prints a base 10 number.\n");
will display:
In the format string, a blank space follows the percent sign, not a type character, so printf will simply display
the percent sign. It then displays the blank space (the next character in the format string), and then it displays the
backspace character (specified with the escape sequence \b). This effectively erases the blank space. The next
character in the format string is the letter 'd', which printf writes in the place where it originally wrote the blank.
We mentioned above that we can have more than one format specifier in a format string. If we do this, we will
need one additional argument for each of the format specifiers. Furthermore, the arguments must appear in the
same order as the format specifiers. Examine the following examples:
printf ("The value of number, %d, multipled by 2, is %d.\n", number,
number*2);
prints:
As you can see from the previous example, the argument can be an expression such as number * 2 as well as a
variable.
printf ("The value of number, %d, multipled by 2, is %d.\n", number*2,
number);
displays:
https://eecs.wsu.edu/~cs150/reading/printf.htm 5/11
11/19/2020 Formatted Output and the printf function
In the preceding example, the order of the additional parameters is wrong, so the output is plainly nonsensical.
You must remember that printf does not understand English, so it cannot determine which argument belongs
with which format specifier. Only the order of the parameters matters. The printf function substitutes the first of
the additional arguments for the first format specifier, the second of the additional arguments for the second
format specifier, and so on. Thus,
printf ("%d + %d = %d\n", number, number*2, number + number*2);
writes:
10 + 20 = 30
|
Because printf uses the additional parameters to give it the values to substitute for the format specifiers, it is
essential that, as a programmer, you supply enough parameters. For instance, if we rewrite the preceding
example as follows so that we have three format specifiers in the format string, but only two additional
parameters:
printf ("%d + %d = %d\n", number, number*2);
printf will print something bizarre on the screen. Since it has no value for the third format specifier, it will print
a garbage value. We have no way to predict exactly what value it will display (it may even coincidentally be the
right value!), but it would not be surprising to see output such as:
10 + 20 = -4797
|
The moral of the story is that if you see strange output when you are using format specifiers, one of the first
things you should check is the order and number of the additional arguments.
You might also see unexpected output for one other reason. The type character in the format specifier determines
completely how printf will display a value. If you include a format specifier with a particular type character in
your format string and then give an argument of a different data type, printf will display the value of the
argument using the syntax for values corresponding to the type character, not the syntax corresponding to the
data type of the argument. For example,
printf ("%d", 'a');
will print:
97|
5.000000|
In each example, printf makes an implicit type conversion of its argument to force it to agree with the data type
that the type character specifies. In some special cases, you can use this automatic conversion to your advantage,
but most of the time, you will want to ensure that the data type of the argument matches the type character.
Although the first option is flags, it is actually the least common, so we will leave its discussion for last. The
width option is the option you will use most frequently. This option is often called a field width. We usually use
field widths to line up columns of data to form tables on the screen. Printing things in tables makes output more
readable. We can also use field widths for other reasons as well. Since they allow us to control exactly where a
value will appear on a line of the screen, we can also use field widths when we want to "draw" with characters.
The value that the format specifier indicates is sometimes called a "field" so the field width controls how many
columns the field will occupy on the screen. The value that we substitute for the italicized width in an actual
format specifier can be one of two things. Most often, it will be an integer. For example, assume that your
program contains a declaration for a character variable as follows:
char digit = '2';
If the body of the code contains the following statement:
printf ("%3c\n", digit);
what printf will display is:
2
|
Notice that two blank spaces precede the digit '2'; this means the entire field (two blanks and one non-blank
character) occupies three columns. In addition, notice that the blanks come before the digit. We call this right
justification. Right justification implies that items on a single row of the screen will line up along the right
margin. Thusm if we immediately make another call to printf as follows:
printf ("%3c\n", digit+1);
the screen will look like this:
2
3
|
https://eecs.wsu.edu/~cs150/reading/printf.htm 7/11
11/19/2020 Formatted Output and the printf function
The field width you specify is the minimum number of columns that output will occupy. If a complete
representation of a value requires more columns, printf will print the whole value, overriding the field width.
For example, consider the following call to printf:
printf ("%3f\n", 14.5);
The field width specifier in this call is 3, but the value, 14.5 actually requires four columns (the decimal point
requires a column as well as the digits. In this case, the display will be:
14.5
|
14.5
3.2
|
Notice that because the field width was too small, the right justification fails; the two numbers do not line up
along the right hand margin. A field width that requires fewer columns than the actual data value requires will
always result in this failure.
You may be wondering at this point how justification allows us to print tables. So far, we have only put one
value on each line, but if we print several values before each newline, we can use field widths to force them to
line up. Consider the following series of printf statements:
printf ("%10s%10s\n", "month", "day");
printf ("%10d%10d\n", 1, 10);
printf ("%10d%10d\n", 12, 2);
What appears on the screen when these statements executes is a table:
month day
1 10
12 2
|
Notice in particular that the field widths always start from the last column printed. At the beginning, the cursor is
in the extreme upper left corner of the screen. The format string in the first printf statement specifies that the
function should print the string "month" using 10 columns. Since "month" only requires 5 columns, printf
precedes the string with five blanks. At this point, the cursor will be in the eleventh column. The next format
specifier requires printf to write the string "day", also using 10 columns. The string "day" takes up three
columns, so printf must precede it with seven blanks, starting from the current cursor position. In other words,
the column count begins just after the last letter of the string "month".
In a situation like this, where we are printing only constants, we could simply embed the blanks in the format
string and not bother with format specifiers or additional arguments. The sequence of statements:
would produce exactly the same output. In most situations, however, the additional arguments will be variables.
As such, we cannot necessarily determine what values they will hold when the program executes. In particular,
when we have numeric variables, we will not be able to predict whether the value of the variable will be a one-
digit number or a 4-digit number. Only by using field widths can we guarantee that the columns will line up
correctly.
Occasionally, when we write a program, we cannot even predict how large a field width we will need when a
program executes. This implies that the field width itself needs to be a variable, for which the program will
compute a value. Although it is rare for this situation to arise, it is worth mentioning how you can accomplish
this. Just as was the case when we wanted to print the value of a variable, if we try to use a variable's name as a
field width specifier, printf will simply print the name to the screen. For example, assume that you have
declared an integer variable named width and have somehow computed a value for it. The call:
printf ("%widthd\n", 10);
will print:
%widthd
|
To solve this problem, C uses an asterisk in the position of the field width specifier to indicate to printf that it
will find the variable that contains the value of the field width as an additional parameter. For instance, assume
that the current value of width is 5. The statement:
printf ("%*d%*d\n", width, 10, width, 12);
will print:
10 12
|
Notice that the order of the additional parameters is exactly the same as the order of the specifiers in the format
string, and that even though we use the same value (width) twice as a field width, it must appear twice in the
parameter list.
Precision specifiers
Precision specifiers are most common with floating point numbers. We use them, as you might expect from the
name, to indicate how many digits of precision we want to print. Compilers have a default precision for floating
point numbers. The help facility or user's manual for your compiler will tell you what this default is, although
you can also determine its value by simply printing a floating point number with a %f format specifier and
counting how many digits there are after the decimal point. Quite often, we want to control this precision. A
common example would be printing floating point numbers that represent monetary amounts. In this case, we
will typically want just two digits after the decimal point. You can see from the syntax template that a period
must precede the precision specifier. The period really is a syntactic device to help the compiler recognize a
precision specifier when no field width exists, but the choice of a period serves to help remind the programmer
that it represents the number of places after a decimal point in a floating point number. Just as for the field width
specifier, the programmer may use a number or an asterisk as a precision specifier. The asterisk again indicates
that the actual value of the precision specifier will be one of the additional parameters to the printf call. For
example,
printf ("%.2f\n", 3.675);
will print:
https://eecs.wsu.edu/~cs150/reading/printf.htm 9/11
11/19/2020 Formatted Output and the printf function
3.68
|
Notice that printf rounds the number when a precision specifier requires that some digits must not appear.
printf ("%.*f\n", width, 10.4);
assuming that the current value of width is 3, will print:
10.400
|
Precision specifiers have no effect when used with the %c format specifier. They do have an effect when
printing integers or strings, however. When you use a precision specifier with integer data, one of two things
may happen. If the precision specifier is smaller than the number of digits in the value, printf ignores the
precision specifier. Thus,
printf ("%.1d\n", 20);
will print the entire number, "20". Here, the precision specifier is less than the number of digits in the value. On
the other hand, if the precision specifier is larger than the number of digits in the value, printf will "pad" the
number with leading zeros:
printf ("%.4d\n", 20);
will print "0020".
With string data, the precision specifier actually dictates the maximum field width. In other words, a programmer
can use a precision specifier to force a string to occupy at most a given number of columns. For instance,
printf ("%.5s\n", "hello world");
will print only "hello" (the first five characters). It is fairly rare to use precision specifiers in this fashion, but one
situation in which it can be useful is when you need to print a table where one column is a string that may
exceed the field width. In this case, you may wish to truncate the long string, rather than allow it to destroy the
justification of the columns. Generally, when this happens, you will use both a field width specifier and a
precision specifier, thus defining both the maximum and minimum number of columns that the string must
occupy. Thus, if name is a variable that contains a string,
printf ("%10.10s\n", name);
will force printf to use exactly 10 columns to display the value of name. If the value is less than ten characters
long, printf will pad with leading blanks; if the value has more than ten characters, printf will print only the
first ten.
Flags
Flags are fairly uncommon in format specifiers and although several flag options exist, you are most likely to
use only two of them. The first is a minus sign, which you will use in conjunction with a field width specifier.
By default, whenever printf must pad output with blanks to make up a field width, the blanks precede the
representation of the data. This results in right justification, as previously mentioned. In a few situations, you
may wish to left justify data. That is, you may want values to line up along the left side, rather than the right
side. In most cases, it will be best to right justify numbers and left justify strings. For instance, if you wanted to
print a table of student names followed by their test scores, you would probably want the table to appear as
follows:
Mary Jones 89
Sam Smith 100
John Cook 78
https://eecs.wsu.edu/~cs150/reading/printf.htm 10/11
11/19/2020 Formatted Output and the printf function
The names are lined up along the left, while the scores are lined up along the right. To print a single line of this
table, your format string might look as follows:
"%-15.15s%4d"
The minus sign indicates left justification for the name, which must occupy exactly 15 columns. The %4d format
specifier tells printf to right justify the score and to have it occupy four columns. Since we can assume that no
score will actually be larger than a three digit number, specifying a field width of four ensures that we will have
a blank space between the name and the score.
The other flag that you may want to use is a plus sign. This flag is only meaningful with numeric data. By
default, when printf displays a number, it prints a minus sign for negative numbers, but it does not print a plus
sign for positive numbers. If you want the plus sign to appear, this flag will cause printf to display it. Thus,
printf ("%+.3f", 2.5);
will print "+2.500".
https://eecs.wsu.edu/~cs150/reading/printf.htm 11/11