How to use printf to format output

Get to know printf, a mysterious, flexible, and feature-rich alternative to echo, print, and cout.
53 readers like this.

When I started learning Unix, I was introduced to the echo command pretty early in the process. Likewise, my initial Python lesson involved the print function. Picking up C++ and Java introduced me to cout and systemout. It seemed every language proudly had a convenient one-line method of producing output and advertised it like it was going out of style.

But once I turned the first page of intermediate lessons, I met printf, a cryptic, mysterious, and surprisingly flexible function. In going against the puzzling tradition of hiding printf from beginners, this article aims to introduce to the world the humble printf function and explain how it can be used in nearly any language.

A brief history of printf

The term printf stands for "print formatted" and may have first appeared in the Algol 68 programming language. Since its inclusion in C, printf has been reimplemented in C++, Java, Bash, PHP, and quite probably in whatever your favorite (post-C) language happens to be.

It's clearly popular, and yet many people seem to regard its syntax to be complex, especially compared to alternatives such as echo or print or cout. For example, here's a simple echo statement in Bash:

$ echo hello
hello
$

Here's the same result using printf in Bash:

$ printf "%s\n" hello
hello
$

But you get a lot of features for that added complexity, and that's exactly why printf is well worth learning.

printf output

The main concept behind printf is its ability to format its output based on style information separate from the content. For instance, there is a collection of special sequences that printf recognizes as special characters. Your favorite language may have greater or fewer sequences, but common ones include:

  • \n: New line
  • \r: Carriage return
  • \t: Horizontal tab
  • \NNN: A specific byte with an octal value containing one to three digits

For example:

$ printf "\t\123\105\124\110\n"
     SETH
$

In this Bash example, printf renders a tab character followed by the ASCII characters assigned to a string of four octal values. This is terminated with the control sequence to produce a new line (\n).

Attempting the same thing with echo produces something a little more literal:

$ echo "\t\123\105\124\110\n"
\t\123\105\124\110\n
$

Using Python's print function for the same task reveals there's more to Python's print command than you might expect:

>>> print("\t\123\n")
        S

>>>

Obviously, Python's print incorporates traditional printf features as well as the features of a simple echo or cout.

These examples contain nothing more than literal characters, though, and while they're useful in some situations, they're probably the least significant thing about printf. The true power of printf lies in format specification.

Format output with printf

Format specifiers are characters preceded by a percent sign (%).

Common ones include:

  • %s: String
  • %d: Digit
  • %f: Floating-point number
  • %o: A number in octal

These are placeholders in a printf statement, which you can replace with a value you provide somewhere else in your printf statement. Where these values are provided depends on the language you're using and its syntax, but here's a simple example in Java:

string var="hello\n";
system.out.printf("%s", var);

This, wrapped in appropriate boilerplate code and executed, renders:

$ ./example
hello
$

It gets even more interesting, though, when the content of a variable changes. Suppose you want to update your output based on an ever-increasing number:

#include <stdio.h>

int main() {
  int var=0;
  while ( var < 100) {
    var++;
  printf("Processing is %d%% finished.\n", var);
  }
  return 0;
}

Compiled and run:

Processing is 1% finished.
[...]
Processing is 100% finished.

Notice that the double %% in the code resolves to a single printed % symbol.

Limiting decimal places with printf

Numbers can get complex, and printf offers many formatting options. You can limit how many decimal places are printed using the %f for floating-point numbers. By placing a dot (.) along with a limiter number between the percent sign and the f, you tell printf how many decimals to render. Here's a simple example written in Bash for brevity:

$ printf "%.2f\n" 3.141519
3.14
$

Similar syntax applies to other languages. Here's an example in C:

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

int main() {
  fprintf(stdout, "%.2f\n", 4 * atan(1.0));
  return 0;
}

For three decimal places, use .3f, and so on.

Adding commas to a number with printf

Since big numbers can be difficult to parse, it's common to break them up with a comma. You can have printf add commas as needed by placing an apostrophe (') between the percent sign and the d:

$ printf "%'d\n" 1024
1,024
$ printf "%'d\n" 1024601
1,024,601
$

Add leading zeros with printf

Another common use for printf is to impose a specific format upon numbers in file names. For instance, if you have 10 sequential files on a computer, the computer may sort 10.jpg before 1.jpg, which is probably not your intent. When writing to a file programmatically, you can use printf to form the file name with leading zero characters. Here's an example in Bash for brevity:

$ printf "%03d.jpg\n" {1..10}
001.jpg
002.jpg
[...]
010.jpg

Notice that a maximum of 3 places are used in each number.

Using printf

As you can tell from these printf examples, including control characters, especially \n, can be tedious, and the syntax is relatively complex. This is the reason shortcuts like echo and cout were developed. However, if you use printf every now and again, you'll get used to the syntax, and it will become second nature. I don't see any reason printf should be your first choice for printing statements during everyday activities, but it's a great tool to be comfortable enough with that it won't slow you down when you need it.

Take some time to learn printf in your language of choice, and use it when you need it. It's a powerful tool you won't regret having at your fingertips.

What to read next

Why I use Java

There are probably better languages than Java, depending on work requirements. But I haven't seen anything yet to pull me away.

Seth Kenlon
Seth Kenlon is a UNIX geek, free culture advocate, independent multimedia artist, and D&D nerd. He has worked in the film and computing industry, often at the same time.

2 Comments

Your use of 000%d to left pad filenames is just plain wrong. Your format string should be %03d

You're just plain right. I've corrected it in the article for posterity.

In reply to by Chris Elvidge (not verified)

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.