# The joys of printf

When I started learning Unix, I got introduced pretty early in the process to the ``echo`` command.
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 was introduced to ``printf``, a cryptic and mysterious, and surprisingly flexible, function kept hidden from beginners.
Going against that puzzling tradition, this article aims to introduce to the world the humble ``printf`` function, and how it can be used in nearly any language you use.

## A brief history of printf

The term ``printf`` stands for "print formatted" and may have first appeared in the [ALGOL 68](https://opensource.com/article/20/6/algol68) programming language.
Since its inclusion in C, ``printf`` has been reimplemented in C++, Java, Bash, PHP, and quite probably in whatever your favourite (post-C) language happens to be.

It's clearly popular, and yet it seems to be regarded as having a complex syntax, 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
$
```

You get a lot of features for that added complexity, though, 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 favourite 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 1 to 3 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:

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

Using Python's ``print`` function for the same task reveals that 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 specificiers are characters preceeded 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, to be replaced by 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 so ``printf`` offers many options when formatting them.
You can limit how many decimal places get 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 3 decimal places, use ``.3f``, and so on.

## Adding commas to a number with printf

Big numbers can be difficult to parse, so we often break them up with a comma.
You can have ``printf`` add commas as needed with 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

A common use for ``printf`` is to impose a specific format upon numbers in file names.
For instance, if you have ten sequential files on a computer, the computer may sort ``10.jpg`` as being before ``1.jpg``, which is probably not your intent.
When writing out 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 "000%d.jpg\n" {1..10}
0001.jpg
0002.jpg
[...]
00010.jpg
```

## Using printf

As you can tell from these ``printf`` examples, the inclusion of control characters, especially ``\n``, can be tedious, and the syntax is relatively complex.
This is the very reason shortcuts like ``echo`` and ``cout`` were developed, of course.
However, if you force yourself to use ``printf`` every now and again, you'll get used to the syntax and it gets to be second nature.
I don't see any reason ``printf`` should be your *first* choice for printing statements during your everyday activities, but it's a great tool to be comfortable enough with that it doesn't slow you down when you have a sudden need for it.
Take some time to learn ``printf`` in whatever your language of choice is, and use it when you need it.
It's a powerful tool you won't regret having at your fingertips.