formatted output and printf
TRANSCRIPT
-
8/12/2019 Formatted Output and Printf
1/12
Formatted Output and the printf function
One of the most important and common tasks in virtually every program is the printing of output. Programs use
output to request input from a user, to display status messages, and to inform the user of the results of
computations that the program performs. For obvious reasons, the manner in which the program displays its
output can have a profound effect on the usefulness and usability of a program. When a program prints its output
in a neatly formatted fashion, the output is always easier to read and understand. As a result, being able to write
programs easily that produce attractive output is an essential feature of most programming languages.
C has a family of library functions that provide this capability. All of these functions reside in the stdiolibrary.
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 printfworks will give you (almost) all the information you need to use fprintf.
Using printf to print messages
To use the printffunction, you must first insure that you have included the stdio library in your program. You do
this by placing the C preprocessor directive
#include
at the beginning of your program. If you are also including other libraries, you will have other #include
directives; the order of these does not matter.
When you actually use the printf function, that is, when you want your program to print something on the screen,
you will place a callto 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 anargument listorparameter 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 printffunction, the argument list will provide the information that the
function should print to the screen. We generally say that wepassarguments 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 printffunction is unusual,
-
8/12/2019 Formatted Output and Printf
2/12
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 printfas
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
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 youwould use printfto 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:
Please type an integer then press Enter: |
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 printfto tell the user what the program is doing:
printf ("Searching, please wait...");
On the screen, you would see:
Searching, please wait...|
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 printfagain, the next message would appear immediately after the first one. Usually, this wil
not be what you want. Instead, you will want to print the next message on the next line of the screen, but you wil
need to tell printfto 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
-
8/12/2019 Formatted Output and Printf
3/12
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.
More control using escape sequences
Obviously, then, we need another way to tell printfto send the cursor to the next line after printing the rest of the
characters in the format string. C uses escape sequenceswithin a format string to indicate when we want printfto print certain special characters, such as the character that the Enter key produces. The escape character for a
newline(which sends the cursor to the beginning of the next line on the screen) is \n. The backslash is called the
escape characterin this context and it indicates that the programmer wants to insert a special character into the
format string. Without the backslash, printfwould simply print the 'n'. You might guess that the 'n' is an
abbreviation for "newline." C provides several escape sequences, but only a few are common. Others that you
might find useful appear in the following table:
Escape sequenceAction
\n prints a newline
\b prints a backspace (backs up one character)
\t prints a tab character
\\ prints a backslash
\" prints a double quote
If we alter the second example above as follows:
printf ("Searching, please wait...\n");
the screen will appear as before, except that now the cursor will be on the next line. Furthermore, if the program
contains another printf statement later on, the next output will be printed on that same next line.
Searching, please wait...
|
Here are a few more examples of printfstatements that make use of escape sequences:
printf ("\nName\tAddress\n");
produces:
Name Address
|
printf ("Joe's Diner\b");
displays:
Joe's Dine|
-
8/12/2019 Formatted Output and Printf
4/12
printf ("Please type \"Yes\" or \"No\": ");
prints:
Please type "Yes" or "No": |
Using printf to print values with format specifiers
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 printfis actually much more powerful than we have seen. First, assume for a moment tha
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 numberreally does hold the value 10. You
want to display the string "The value of number is 10" on the screen. You might try calling printfas follows:
printf ("The value of number is number\n"); /* This won't work */
Of course, because printfprints the format string exactly as it appears (except for the escape sequences), what
you will see on the screen is:
The value of number is number
|
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, printfwill 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 containformat
specifiers. A format specifier is a placeholder that performs two functions. First, it shows wherein the output to
place an item not otherwise represented in the format string and it indicates howprintfshould 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 printfshould expect to print. It can also indicate exactly how the
programmer wants printfto 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
-
8/12/2019 Formatted Output and Printf
5/12
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 printfwill display. Thus,
most often a format specifier will simply be a percent sign followed by a "type character." The type character is
what tells printfwhat data type to print. The following table shows the most common type characters (several
others exist):
type character print formatd integer number printed in decimal (preceded by a minus sign if the number is negative)
f floating point number (printed in the form dddd.dddddd)
E floating point number (printed in scientific notation: d.dddEddd)
g floating point number (printed either as f or E, depending on value and precision)
x integer number printed in hexadecimal with lower case letters
X integer number printed in hexadecimal with upper case letters
c character
s string
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 printfto print a string. Notice that the format specifiers tell what kind of thing the
programmer wants to display, but they do not tell what valueto 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 printfshould substitute for the format specifier. For instance, the
following call to printfwill display the value of our variable number:
printf ("The value of number is %d\n", number);
The value of number is 10
|
The two arguments to this call to printfcombine to tellthe function exactly what to write on the screen. What
happens is that the printffunction 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, printfretrieves the next argument in the argument list and prints its value. If the next character is notatype character, printf simply displays the percent sign. For example,
printf ("The value of number is %q\n", number);
will print:
The value of number is %q
|
-
8/12/2019 Formatted Output and Printf
6/12
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 printffinds 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:
The %d format specifier prints a base 10 number.
|
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 printfwrites 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 thesame orderas the format specifiers. Examine the following examples:
printf ("The value of number, %d, multipled by 2, is %d.\n",
number, number*2);
prints:
The value of number, 10, multiplied by 2, is 20.
|
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:
The value of number, 20, multiplied by 2, is 10.
|
In the preceding example, the order of the additional parameters is wrong, so the output is plainly nonsensical.
You must remember that printfdoes not understand English, so it cannot determine which argument belongs
with which format specifier. Only the order of the parameters matters. The printffunction 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:
-
8/12/2019 Formatted Output and Printf
7/12
10 + 20 = 30
|
Because printfuses 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 additionalparameters:
printf ("%d + %d = %d\n", number, number*2);
printfwill 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 printfwill 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, printfwill 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|
since the ASCII code for 'a' is 97.
printf ("%f", 5);will display:
5.000000|
In each example, printfmakes an implicit type conversion of its argument to force it to agree with the data type
-
8/12/2019 Formatted Output and Printf
8/12
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.
More control using format specifier options
The syntax template for a format specifier given above provides for several options. These options allow the
programmer to control precisely how output will appear on the screen. The syntax template appears again here
for easy reference:%[flags][width][.precision]type_character
Again, the order of the options is just as important as the order of arguments to the printffunction. In other
words, if you want to use multiple options, they must appear in the same order as they do in the syntax template.
Field width specifiers
Although the first option isflags, it is actually the least common, so we will leave its discussion for last. The
widthoption is the option you will use most frequently. This option is often called afield 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 widthin 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 beforethe 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 printfas follows:printf ("%3c\n", digit+1);
the screen will look like this:
2
3
|
-
8/12/2019 Formatted Output and Printf
9/12
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, printfwill 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
|
If we alter the call:
printf ("%3f\n%3f", 14.5, 3.2);
printf writes:
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 printfstatements:
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 printfstatement 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 printfmust 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".
-
8/12/2019 Formatted Output and Printf
10/12
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:
printf (" month day\n");
printf (" 1 10\n");
printf (" 12 2\n");
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, printfwill simply print the name to the screen. For example, assume that you have declared an
integer variable named widthand 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 printfthat it wilfind the variable that contains the value of the field width as an additional parameter. For instance, assume that
the current value of widthis 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
-
8/12/2019 Formatted Output and Printf
11/12
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, theprogrammer 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 printfcall. For example,
printf ("%.2f\n", 3.675);
will print:
3.68
|
Notice that printfrounds 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 widthis 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 maximumfield width. In other words, a
programmer can use a precision specifier to force a string to occupy at mosta 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
-
8/12/2019 Formatted Output and Printf
12/12
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 printfto use exactly 10 columns to display the value of name. If the value is less than ten characters
long, printfwill 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 printfmust 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 leftjustify 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 89Sam Smith 100
John Cook 78
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 printfto display it. Thus,
printf ("%+.3f", 2.5);
will print "+2.500".