[ Team LiB ] Previous Section Next Section

Formatting Strings

Until now, we have simply printed any strings we want to display directly to the browser. PHP provides two functions that allow you first to apply formatting, whether to round doubles to a given number of decimal places, define alignment within a field, or display data according to different number systems. In this section, you learn a few of the formatting options provided by printf() and sprintf().

Working with printf()

If you have any experience with C, you will be familiar with the printf() function. The PHP version is similar but not identical. printf() requires a string argument, known as a format control string. It also accepts additional arguments of different types. The format control string contains instructions as to how to display these additional arguments. The following fragment, for example, uses printf() to output an integer as a decimal:


printf ("This is my number: %d", 55);
// prints "This is my number: 55"

Within the format control string (the first argument), we have included a special code, known as a conversion specification.

A conversion specification begins with a percent (%) symbol and defines how to treat the corresponding argument to printf(). You can include as many conversion specifications as you want within the format control string, as long as you send an equivalent number of arguments to printf().

The following fragment outputs two numbers using printf():


printf ("First number: %d<br/>\nSecond number: %d<br/>\n", 55, 66);
// Output:
// First number: 55
// Second number: 66

The first conversion specification corresponds to the first of the additional arguments to printf(), which is 55. The second conversion specification corresponds to 66. The d following the percent symbol requires that the data be treated as a decimal integer. This part of a conversion specification is called a type specifier.

printf() and Type Specifiers

You have already come across one type specifier, d, which displays data in decimal format. Table 8.1 lists the other available type specifiers.

Table 8.1. Type Specifiers

Specifier

Description

d

Displays an argument as a decimal number

b

Displays an integer as a binary number

c

Displays an integer as its ASCII equivalent

f

Displays an integer as a floating-point number (double)

o

Displays an integer as an octal number (base 8)

s

Displays an argument as a string

x

Display an integer as a lowercase hexadecimal number (base 16)

X

Displays an integer as an uppercase hexadecimal number (base 16)

Listing 8.1 uses printf() to display a single number according to some of the type specifiers listed in Table 8.1.

Notice that we do not only add conversion specifications to the format control string. Any additional text we include will be printed.

Listing 8.1 Demonstrating Some Type Specifiers
 1: <!DOCTYPE html PUBLIC
 2:   "-//W3C//DTD XHTML 1.0 Strict//EN"
 3:  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 8.1 Demonstrating Some Type Specifiers</title>
 7: </head>
 8: <body>
 9: <div>
10: <?php
11: $number = 543;
12: printf("Decimal: %d<br/>", $number );
13: printf("Binary: %b<br/>", $number );
14: printf("Double: %f<br/>", $number );
15: printf("Octal: %o<br/>", $number );
16: printf("String: %s<br/>", $number);
17: printf("Hex (lower): %x<br/>", $number );
18: printf("Hex (upper): %X<br/>", $number );
19: ?>
20: </div>
21: </body>
22: </html>

Figure 8.1 shows the output for Listing 8.1. As you can see, printf() is a quick way of converting data from one number system to another and outputting the result.

Figure 8.1. Demonstrating conversion specifiers.

graphics/08fig01.gif

When you specify a color in HTML, you combine three hexadecimal numbers between 00 and FF, representing the values for red, green, and blue. You can use printf() to convert three decimal numbers between 0 and 255 to their hexadecimal equivalents, like so:


$red = 204;
$green = 204;
$blue = 204;
printf( "#%x%x%x", $red, $green, $blue);
// prints "#CCCCCC"

Although you can use the type specifier to convert from decimal to hexadecimal numbers, you can't use it to determine how many characters the output for each argument should occupy. Within an HTML color code, each hexadecimal number should be padded to two characters, which would become a problem if we changed our $red, $green, and $blue variables in the previous fragment to contain 1, for example. We would end up with the output "#111". You can force the output of leading zeroes by using a padding specifier.

Padding Output with the Padding Specifier

You can require that output be padded by leading characters. The padding specifier should directly follow the percent sign that begins a conversion specification. To pad output with leading zeroes, the padding specifier should consist of a zero followed by the number of characters you want the output to take up. If the output occupies fewer characters than this total, the difference is filled with zeroes:


printf("%04d", 36);
// prints "0036"

To pad output with leading spaces, the padding specifier should consist of a space character followed by the number of characters the output should occupy:


printf ("% 4d", 36);
// prints " 36"

graphics/bytheway_icon.gif

A browser does not display multiple spaces in an HTML document. However, you can force the display of spaces and newlines by placing <pre> tags around your output:


<pre>
<?php
print "The spaces will be visible";
?>
</pre>

If you want to format an entire document as text, you can use the header() function to change the Content-Type header, as shown here:


header("Content-Type: Text/Plain");

Remember that your script must not have sent any output to the browser for the header() function to work as desired.


You can specify any character other than a space or zero in your padding specifier with a single quotation mark followed by the character you want to use:


printf ( "%'x4d", 36 );
// prints "xx36"

We now have the tools we need to complete our HTML code example. Until now, we could convert three numbers, but we could not pad them with leading zeroes:


$red = 1;
$green = 1;
$blue = 1;
printf( "#%02x%02x%02x", $red, $green, $blue);
// prints "#010101"

Each variable is output as a hexadecimal number. If the output occupies fewer than two spaces, leading zeroes are added.

Specifying a Field Width

You can specify the number of spaces within which your output should sit. The field width specifier is an integer that should be placed after the percent sign that begins a conversion specification (assuming no padding specifier is defined). The following fragment outputs a list of four items, all of which sit within a field of 20 spaces. To make the spaces visible on the browser, we place all our output within a PRE element:


print "<pre>";
printf ("%20s\n", "Books");
printf ("%20s\n", "CDs");
printf ("%20s\n", "Games");
printf ("%20s\n", "Magazines");
print "</pre>";

Figure 8.2shows the output of this fragment.

Figure 8.2. Aligning with field width specifiers.

graphics/08fig02.gif

By default, output is right-aligned within the field you specify. You can make it left-aligned by prepending a minus symbol (-) to the field width specifier:


printf ("%-20s\n", "Left aligned");

Note that alignment applies to the decimal portion of any number you output. In other words, only the portion before the decimal point of a double sits flush to the end of the field width when right aligned.

Specifying Precision

If you want to output data in floating-point format, you can specify the precision to which you want to round your data. This is particularly useful when dealing with currency. The precision identifier should be placed directly before the type specifier. It consists of a dot followed by the number of decimal places to which you want to round. This specifier has an effect only on data that is output with the f type specifier:


printf( "%.2f", 5.333333);
// prints "5.33"

graphics/bytheway_icon.gif

In the C language, you can use a precision specifier with printf() to specify padding for decimal output. The precision specifier has no effect on decimal output in PHP. Use the padding specifier to add leading zeroes to integers.


Conversion Specifications: A Recap

Table 8.2 lists the specifiers that can make up a conversion specification in the order in which they would be included. Using both a padding specifier and a field width specifier is difficult—you should choose to use one or the other, but not both.

Table 8.2. Components of Conversion Specification

Name

Description

Example

Padding

Detemines the number of characters the

' 4'

specifier

output should occupy and the characters to add otherwise

 

Field width

Determines the space within which output

'20'

specifier

should be formatted

 

Precision

Determines the number of decimal places

'.4'

specifier

to which a double should be rounded

 

Type specifier

Determines the data type that should be output

'd'

Listing 8.2 uses printf() to output a list of products and prices.

Listing 8.2 Using printf() to Format a List of Product Prices
 1: <!DOCTYPE html PUBLIC
 2: "-//W3C//DTD XHTML 1.0 Strict//EN"
 3: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 4: <html>
 5: <head>
 6: <title>Listing 8.2 Using printf() to Format a List of Product Prices</title>
 7: </head>
 8: <body>
 9: <?php
10: $products = array (
11:       "Green armchair"=>222.4,
12:       "Candlestick"=>4,
13:       "Coffee table"=>80.6
14:       );
15: print "<pre>";
16: printf ("%-20s%23s\n", "Name", "Price");
17: printf ("%'-43s\n", "");
18: foreach ( $products as $Key=>$val ) {
19:   printf ("%-20s%20.2f\n", $Key, $val);
20: }
21: print "</pre>";
22: ?>
23: </body>
24: </html>

We first define an associative array containing product names and prices on line 8. We print a PRE element so the browser will recognize our spaces and newlines. Our first printf() call on line 12 defines the following format control string:


"%-20s%23s\n"

The first conversion specification ("%-20s") uses a field width specifier of 20 characters, with the output left-justified. We use a string type specifier, and the second conversion specification ("%23s") sets up a right-aligned field width. The printf() call then outputs our field headers.

Our second printf() function call on line 13 draws a line of - characters across a field of 43 characters. We achieve this with a padding specifier, which adds padding to an empty string.

The final printf() call on line 15 is part of a foreach statement that loops through our product array. We use two conversion specifications. The first ("%-20s") prints the product name as a string left-justified within a 20-character field. The second conversion specification ("%20.2f") uses a field width specifier to ensure that output will be right-aligned within a 20-character field, and it also uses a precision specifier to ensure that the double we output is rounded to two decimal places.

Figure 8.3 shows the output of Listing 8.2.

Figure 8.3. Products and prices formatted with printf().

graphics/08fig03.gif

Argument Swapping

As of PHP 4.0.6, you can use the format control string to change the order in which the provided arguments are incorporated into output.

Imagine, for example, that we are printing dates to the browser. We have the dates in a multidimensional array and are using printf() to format the output:


<?php
$dates = array(
      array( 'mon'=> 12, 'mday'=>25, 'year'=>2001 ),
      array( 'mon'=> 5, 'mday'=>23, 'year'=>2000 ),
      array( 'mon'=> 10, 'mday'=>29, 'year'=>2001 )
      );
$format = include ("local_format.php");
foreach ($dates as $date) {
  printf( "$format", $date['mon'], $date['mday'], $date['year'] );
}
?>

We are getting our format control string from an include file called local_format.php. Assume that this file contains only the following:


<?php
return "%02d/%02d/%d<br/>";
?>

Our output is therefore in the format mm/dd/yyyy:


12/25/2001
05/23/2000
10/29/2001

Imagine now that we are installing our script for a British site. In the United Kingdom, dates are commonly presented with days before months (dd/mm/yyyy). The core code cannot be changed, but configuration files such as local_format.php can. Luckily, we can now alter the order in which the arguments are presented from within the format control code:


return "%2\$02d/%1\$02d/%3\$d<br/>";

We can insert the argument number we are interested in after the initial percentage character that marks each conversion specification, followed by an escaped dollar character ($). So, in the previous fragment we are demanding that the second argument be presented, followed by the first, followed by the third. The result is a list of dates in British format:


25/12/2001
23/05/2000
29/10/2001



Storing a Formatted String

printf() outputs data to the browser, which means that the results are not available to your scripts. You can, however, use the function sprintf(), which works in exactly the same way as printf() except that it returns a string you can then store in a variable for later use. The following fragment uses sprintf() to round a double to two decimal places, storing the result in $dosh:


$dosh = sprintf("%.2f", 2.334454);
print "You have $dosh dollars to spend";

A particular use of sprintf() is to write a formatted data to a file. You can call sprintf() and assign its return value to a variable that can then be printed to a file with file_put_contents().

    [ Team LiB ] Previous Section Next Section