01 · THE IDEAREAD → TRY → LEARN
Why format strings exist
Concatenating values with . works, but it gets awkward when you need zero-padded numbers, fixed decimals or aligned columns. sprintf() solves this with a template. The template is ordinary text mixed with conversion specifications, and each specification consumes one argument and turns it into text. The function returns the finished string and does not print anything.
sprintf(string $format, mixed ...$values): string
Anatomy of a specification
Every specification begins with % and follows this shape:
%[argnum$][flags][width][.precision]specifier
Only the % and the specifier are required. Here is what each part does:
- specifier: the type of conversion.
dis a signed integer,sa string,fa float,xlowercase hex,bbinary.%%prints a literal percent sign and takes no argument. - width: the minimum number of characters in the result. Shorter values are padded; longer values are never cut.
- flags:
-left-justifies,+forces a sign on positive numbers,0pads numbers with zeros, and'followed by a character pads with that character. Spaces are the default padding. - precision: a period and a number. For
fit is the count of digits after the decimal point (6 by default). Forsit is a maximum length, so the string is truncated. - argnum$: a position such as
2$that picks which argument to use. It must come right after the%.
Worked example: padded numbers and positions
The first example builds an ISO-style date from integers. %02d means a minimum width of 2, padded with zeros.
$year = 2005;
$month = 5;
$day = 6;
echo sprintf('%04d-%02d-%02d', $year, $month, $day), PHP_EOL;2005-05-06
Argument numbering lets the template decide the order. That is useful when a translated sentence needs its pieces in a different sequence, and a numbered placeholder may be reused without passing the value again.
$num = 5;
$location = 'tree';
$format = 'The %2$s contains %1$04d monkeys';
echo sprintf($format, $num, $location), PHP_EOL;The tree contains 0005 monkeys
A tour of useful directives
The next example puts many directives side by side. The results go into an array and are encoded as JSON so the padding stays visible inside quotes.
$parts = [
sprintf('%.2f', 3.14159),
sprintf('%8.3f', 2.5),
sprintf('%-8.1f', 7.5),
sprintf('%+d', 5),
sprintf('%.3s', 'abcdef'),
sprintf("%'*8s", 'php'),
sprintf('%x', 255),
sprintf('%b', 5),
sprintf('%5.1f%%', 45.5),
];
echo json_encode($parts, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;["3.14"," 2.500","7.5 ","+5","abc","*****php","ff","101"," 45.5%"]
Read the results carefully. %8.3f makes eight characters with three decimals, right-aligned. %-8.1f is left-aligned, so its padding appears on the right. %.3s cuts a string to three characters, and %'*8s pads with asterisks.
Things to watch
- Too few arguments throw
ArgumentCountErrorin PHP 8. A negative width or precision throwsValueError. - Width counts bytes, not visible characters. For multibyte text, padding with
scan look wrong. Stick to ASCII here. fis locale aware,Fis not. UseFwhen a decimal point must be a period no matter what locale is set.- Width is a minimum.
%02dapplied to100gives100, not10. - Rounding of floats follows binary representation, so choose test values that are exactly representable, such as
4.5, when you need predictable output. - Type coercion:
%dconverts its argument to an integer, so a float like9.99would lose its fraction. Use%ffor decimals.
Exercise contract
Write formatReceiptLine(string $name, int $quantity, float $price): string. It must return one fixed-width line made of four parts:
- The name, left-justified in exactly 8 characters, truncated if longer.
- One space, then
xand the quantity padded with zeros to at least 2 digits. - One space, then the price with exactly two decimals, right-aligned in a width of 7.
For example, Tea, 2 and 4.5 produce Tea x02 4.50. A quantity of 100 keeps all its digits, and a name like Chocolate is cut to Chocolat. Only one sprintf() format string is needed. Build it from the pieces described above.
Recap
A format string is a template of literal text plus % specifications. Width sets a minimum size, flags choose alignment and padding, precision controls decimals or string length, and argnum$ selects arguments by position. Test your formats with values that are exactly representable so the output is predictable.
Functions · Arrays · Types
- Build deterministic padded and decimal-formatted strings
- Implement and test a deterministic PHP 8.4 function