Scripting

Printf() Formatting Specifiers in C Language

The printf() function has several interesting properties, both in terms of its use and its design and operation. First, it is a variadic function which means that it can accept as many input arguments as the programmer wishes to send, thus solving a task with a single call that would otherwise require multiple functions and calls. Another important feature of printf() is that it can display the variables in any format that is used in C and insert them into the text without converting them into strings or using the concatenation functions for it.

In this LinuxWays article, you’ll learn how to specify the format in which you want to show the variables when using the printf() function. We’ll look at a theoretical section that shows the syntax and the method for setting the output formats. We’ll also look at the formats available in this function and learn how to nest the text and variables so you can output them to the screen with a single call.

How Does the Printf() Function Work?

To see how printf() handles the formats, we first need to understand some aspects of the function and how its input arguments are processed. Let’s see the prototype of printf():

int printf ( const char *restrict format, ... );

As we see in the prototype, the first input argument is the format pointer to a string, while the second argument is an ellipsis (…).

The string that is pointed to by the format performs the following three functions:

  1. Contains the text that is used to concatenate the values of the variables converted to strings.
  2. Includes the format specifiers for the conversion of variables.
  3. Specifies in which part and in which order the conversion results are to be concatenated.

In variadic functions, ellipses stand for an indefinite number of input arguments. In the case of printf(), the programmer can insert as many variables as he wants to be converted and printed, with the only rule that each of them must be separated by commas and has its own format specifier in the format string.

When called, the printf() function parses the format string and replaces the format specifiers with the resulting string of converted variables. As we can see in the format string, we specify not only the information about the conversion formats, but also the order and location where the variable should be concatenated in the text to print the final string.

The format identifiers that we will see in this article are compatible with all functions of this family.

Format Specifiers in the Printf() Function

Format specifiers are strings or fragments of strings that are contained in the format string of the printf() function. These strings or fragments of them determine the type of conversion and how a variable will be displayed in the output text.

The format identifiers can be contained in explicit or implicit strings and must always begin with the symbol “%” and end with the letter that specifies the conversion type. Below we see the syntax of a format specifier:

% [order][flags][width][.precision][length]type

The arguments enclosed in square brackets are optional and, as we will see later, specify the precision, field size, etc.

The most common way to establish a conversion format is to specify the type letter preceded by the “%” symbol. Let’s see a table with the letter of type, the syntax used, and a short description for each:

Type Syntax Description
c %c Print ASCII character
s %s Print character strings
i, d %i, %d Signed integers conversion
u %u Unsigned integers conversion
f, F %f, %F Floating point conversion (standard notation)
e, E %e, %E Floating point conversion (scientific notation)
g, G %g, %G Reduced floating point conversion
x, X %x, %X Hexadecimal conversion
o %o Octal conversion
p %p Pointer conversion

How to Specify the Conversion Format in the Printf() Function

Now, let’s look at an example where we declare a variable for each conversion type, assign it with a value, and then print it to the command console using the printf() function, specifying the appropriate format for each type:

#include <stdio.h>

void main (){

char a ='Z';
char * Ptr ="Hello World";
int  b =-2023;
unsigned int c =12345;
float d =1.123456789;
double sc =1.123457e+00;
int o =100;
int x = 0x2EFF02;

printf ("char: %c\n", a);
printf ("string: %s\n", Ptr);
printf ("Pointer address: %p\n", Ptr);
printf ("int: %i\n", b);
printf ("unsigned int: %u\n", c);
printf ("float: %f\n", d);
printf ("scientific float: %e\n", d);
printf ("octal: %o\n", o);
printf ("hexadecimal: 0x%x\n", x);
}

Let’s see the compilation and execution of this code:

As we can see in the picture, the identifiers have been replaced by the value of the corresponding variable. To make the example more readable, we use a call to the printf() function for each variable to be displayed, but the correct way is to resolve everything in a single call as shown in the following:

printf ("char: %c\nstring: %s\nPointer address: %p\nint: %i\nunsigned int: %u\nfloat: %f\nscientific float: %e\noctal: %o\nhexadecimal: 0x%x\n", a, Ptr, Ptr, b, c, d, sc, o, x);

How to Set the Order of Variables in the Printf() Function

As we have already seen, the variables, by default, are displayed in the final text in the same order in which they appear in the input arguments. However, we can change this order using the format specifier. Let’s see a table with the syntax that we can use to specify the order of the variables:

Syntax Description
“%n$[type]” n stands for the order of occurrence of the variables

Next, let’s look at an example where we call the printf() function twice to display the “Hello” and “World” strings in the console.

The first call is done by default, while we change the order in the second call using the “%2s%1s” specifications. Let’s see the code for this example:

#include <stdio.h>

void main (){
char * str_1 ="Hello ";
char * str_2 ="World ";
printf ("%s%s\n", str_1, str_2);
printf ("%2$s%1$s\n", str_1, str_2);
}

As seen in the following figure, the “$” specifications change the order of appearance of the variables:

Flags in the Format Specifiers of the Printf() Function

The flag field of a format specifier adds the following functions to the conversion:

  1. Prepends the base notation of a variable
  2. Prepends the sign of a variable
  3. Prepends a blank space before a variable

Let’s see a table of the most commonly used flags in the print() function:

Flag Syntax Description
# “%#[type]” Prepends the base notation of the variable
+ “%+[type]” Shows the sign of the variable
‘ ‘ “%‘ ‘[type]” Prepends a blank space

How to Prefix the Base Notation of a Variable with the Printf() Function in the C Language

In this example, we convert the variable “a” from an integer to a hexadecimal number, and then call the printf() function twice to display it on the screen. In the first call, we omit the # indicator, while we insert it in the second call so that the base notation is displayed before the variable’s value.

#include <stdio.h>

void main (){
int a = 2222;
printf ("Without: %x\n", a);
printf ("With: %#x\n", a);

}

Let’s see the following image that shows the execution of this code:

How to Print the Sign of a Variable with the Printf() Function in the C Language

In this example, we will see how to print the sign of an integer variable. In C, the signed variables with negative values always output their sign by default, so the “+” specifier only affects the positive values.

In the following code, we declare the integer “a” and assign it the value of 12345. Then, we call the printf() function twice to print this variable. The first call does not include the “+” specifier, but the second call does.

#include <stdio.h>

void main (){
int a = 12345;
printf ("Without +: %i\n", a);
printf ("With +: %+i\n", a);

}

The following image shows the execution of this code:

Decimal Precision and Width Fields in the Printf() Function

The precision and width fields in the format specifiers determine the precision and width of the field in which the variables are displayed. This specifier has the following two usage modes:

  1. Sets the precision of the decimal part in floating point values
  2. Sets the size of the field where the integer, double, long, and string variables will be displayed

For each of these specifiers that we insert into the string, an input argument “n” is added in the order of their occurrence of the variables, specifying the number of fields or precision digits to be displayed.

Let’s see a table with the syntax of these specifiers and a description of them:

Specifier Description
“%.*[type]”,n Specifies the precision in the decimal part of a floating-point value.
“%* [type]”,n Specifies the number of fields to display.


How to Set a Decimal Precision on a Floating Point Value with the Printf() Function

In this example, we use the “%.*” formatter that we just saw to specify the decimal precision to display a floating point number. To do this, we declare the variable “a” of type float and give it the value of 1.22222222. Then, we use the “%.*” specifier to set the decimal precision of “a” to two digits, then to 3 and 4. Let’s see the code for this example:

#include <stdio.h>

void main (){
float a = 1.22222222;
printf ("%.*f\n", 2, a);
printf ("%.*f\n", 3, a);
printf ("%.*f\n", 4, a);

}

As we can see, the printf() function now has three input arguments – the second is the precision indicator and the third is the variable to display. Let’s see the compilation and execution of this code:

How to Adjust the Number of Fields to be Displayed in a Variable or String in the Printf() Function

In this example, we will use the “%*” formatter to adjust the number of fields that we want to display from a variable or string. The operation of this formatter is identical to the previous one, except that its syntax does not include a period and it works with integers, double numbers, and strings.

In the following code, we will use the “str_1” pointer with the “Hello world! Hello Linux Ways!” string and we use the incremental variable “i” as an index of the number of fields in a “for” loop, creating an animation in which the text is written letter by letter every 50 ms.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

void main (){
while (1){
char * str_2 ="Hello world! Hello Linux Ways!!";
for (int i =0; i!=strlen(str_2);i++){
system ("clear");
printf ("%.*s\n", i, str_2);
usleep(50000);
}
sleep(1);
}}

Let’s see an image with the execution of this code:

The Length Field in the Format Specifier of the Printf() Function

Format specifiers also provide the option to convert certain types of data to integers. Let’s see a table of them, their syntax, and a description of each:

Syntax Description
“%hhi” Converts a char to int and prints it
“%hi” Converts a short int to int and prints it
“%li” Converts a long to int and prints it
“%lli” Converts a long long to int and prints it
“%Li” Converts a long double to int and prints it
“%zi” Converts a size_t to int and prints it
“%ji! Converts a intmax_t or uintmax_t to int and prints it

How to Convert a Data Type to Integer with the Format Specifier in the Printf() Function

In this example, we will show you how to convert a character and a long value to an integer and display it to the command console using the width field of the printf() format specifier. For this, we declare the character “c” and the long l and assign them with a random value. Then, we call printf() on each of these variables, passing the “%hhi” specifier for the character and “%li” for the long. Let’s see the code for this example:

#include <stdio.h>

void main (){

  char c = 'C';
  long l = 1234899876;
  printf ("%hhi\n", c);
  printf ("%li\n", l);

}

The following image shows the execution of this code, with the values of “c” and l converted to integers:

Conclusion

In this Linux Ways article, we taught you all about the format specifications of the printf() family of functions so that you can harness their potential and save the lines of code by avoiding multiple calls to other functions. We explained how these functions handle their input arguments and we showed you what the syntax of a format specifier is. Then, in several sections, we explained the individual fields and showed how we can use them to specify the format and order of appearance of the variables that we want to print.

Similar Posts