Reading and Writing Integers in C
We have seen in previous lessons how to declare and initialize integer variables in C language by specifying both their size and whether they are signed or unsigned.
Now it is essential to understand how to print these values to the screen and how to read them from the keyboard. In this article we will see how to do this using the printf and scanf functions by applying the appropriate format specifiers.
printf and integer types
We have seen how to declare and initialize integer variables in C language. Now let's see how we can read and write these variables using the printf function.
Until now, when we have used the printf function to print integers to the screen, we have always used the format specifier %d within the format string. The letter d stands, precisely, for decimal, as the integer number is printed in base 10.
For example, to print the value of an integer variable number, we have used the following statement:
int number = 42;
printf("The value of number is %d\n", number);
However, we have seen in previous lessons that there are different types of integer variables in C language, such as short int, long int and long long int.
In such cases, the format specifier %d is not suitable to correctly represent the value of these variables. In fact, %d is only suitable for variables of type int.
For this reason, the printf function provides different specifiers depending on the specific type of integer we want to print. In particular, a letter must be placed before the character d to specify the type of integer we want to print:
%hdfor variables of typeshort int;%ldfor variables of typelong int;%lldfor variables of typelong long int.
The following example shows how to use these format specifiers:
short int short_number = 42;
long int long_number = 2147483647;
long long int long_long_number = 9223372036854775807;
printf("The value of short_number is %hd\n", short_number);
printf("The value of long_number is %ld\n", long_number);
printf("The value of long_long_number is %lld\n", long_long_number);
If we try to compile and execute the code above we get an output like the following:
The value of short_number is 42
The value of long_number is 2147483647
The value of long_long_number is 9223372036854775807
Care must be taken when printing integers. In fact, using an incorrect specifier, especially when using a format specifier for a smaller size type, can lead to incorrect results.
For example, if we try to print a variable of type long int using the specifier %hd, we get an incorrect result:
long int long_number = 2147483647;
printf("The value of long_number is %hd\n", long_number);
In this case, the result printed to the screen will be:
The value of long_number is -1
This is because the value of long_number is too large to be represented by a short int, and therefore the result is incorrect.
Format Specifiers for Integers in printf
To correctly print integer variables of a type other than int in C language, it is necessary to use the following format specifiers:
%hdfor variables of typeshort int;%ldfor variables of typelong int;%lldfor variables of typelong long int.
The printf function also provides a format specifier to indicate that the integer to be printed is unsigned, unsigned.
In this case, instead of the letter d, the letter u must be used:
unsigned int unsigned_number = 42;
printf("The value of unsigned_number is %u\n", unsigned_number);
As above, the specifier u can be combined with the letters h, l and ll to specify the type of unsigned integer:
%hufor variables of typeunsigned short int;%lufor variables of typeunsigned long int;%llufor variables of typeunsigned long long int.
Summarizing:
Syntax of Format Specifiers for Integers of the printf function
The syntax of format specifiers for integers of the printf function is as follows:
%<size><format>
Where <size> can be one of the following letters:
hforshort int;lforlong int;llforlong long int;- if omitted,
intis assumed.
While <format> can be one of the following letters:
dfor signed integers;ufor unsigned integers.
In any case integers will be printed in base 10.
Printing integers in other bases
The printf function is flexible enough to allow printing integers in bases other than decimal.
In particular, we can use, instead of d and u, the following format specifiers:
%oto print the integer in octal base;%xto print the integer in hexadecimal base;%Xto print the integer in hexadecimal base, with uppercase letters;%bto print the integer in binary base.
In the following example, we read an int number from the keyboard and print it in octal, hexadecimal (both uppercase and lowercase) and binary base:
#include <stdio.h>
int main() {
int number;
printf("Enter an integer number: ");
scanf("%d", &number);
printf("The number in octal base is %o\n", number);
printf("The number in hexadecimal base is %x\n", number);
printf("The number in hexadecimal base (uppercase) is %X\n", number);
printf("The number in binary base is %b\n", number);
return 0;
}
If we run the program and enter the number 42, we get the following output:
Enter an integer number: 42
The number in octal base is 52
The number in hexadecimal base is 2a
The number in hexadecimal base (uppercase) is 2A
The number in binary base is 101010
However, care must be taken with one detail: when we use one of the four specifiers above, the number will always be considered as unsigned (unsigned).
In fact, consider the following example:
#include <stdio.h>
int main() {
int number = -42;
printf("The number in octal base is %o\n", number);
printf("The number in hexadecimal base is %x\n", number);
printf("The number in hexadecimal base (uppercase) is %X\n", number);
printf("The number in binary base is %b\n", number);
return 0;
}
If we run the program, we get the following output:
The number in octal base is 37777777726
The number in hexadecimal base is fffffff6
The number in hexadecimal base (uppercase) is FFFFFFF6
The number in binary base is 11111111111111111111111111110110
As can be observed, the number -42 was interpreted as an unsigned number, and therefore the result is different from what we expected.
Format Specifiers for Integers in Different Bases in printf
To print an int value with the printf function in a base other than 10, we can use the following format specifiers:
%oto print the integer in octal base;%xto print the integer in hexadecimal base;%Xto print the integer in hexadecimal base, with uppercase letters;%bto print the integer in binary base.
In any case, the number will be considered as unsigned (unsigned).
The format specifiers introduced above can be combined with the prefixes h, l and ll to specify the size of the integer to be printed.
For example, we can print a short int number in octal base using the following format specifier:
short int short_number = 42;
printf("The number in octal base is %ho\n", short_number);
Or, we can print a long long int number in binary base using the following format specifier:
long long int long_long_number = 9223372036854775807;
printf("The number in binary base is %llb\n", long_long_number);
Summarizing:
Syntax of Format Specifiers for Integers in Different Bases of the printf function
The syntax of format specifiers for integers in different bases of the printf function is as follows:
%<size><format>
Where <size> can be one of the following letters:
hforshort int;lforlong int;llforlong long int;- if omitted,
intis assumed.
While <format> can be one of the following letters:
ofor octal base;xfor hexadecimal base;Xfor hexadecimal base (uppercase);bfor binary base.
In any case the number will be considered as unsigned (unsigned).
Reading integers from the keyboard
The discussion made above for the printf function applies in the same way to the scanf function.
Through it we can read integer values from the keyboard. But we must apply the appropriate format specifiers to correctly read the integer values.
The specifiers to be used are exactly the same as seen above.
For example, the following program reads three numbers from the keyboard, with sign, using different formats:
#include <stdio.h>
int main() {
short int short_number;
long int long_number;
long long int long_long_number;
printf("Enter a short int number: ");
scanf("%hd", &short_number);
printf("Enter a long int number: ");
scanf("%ld", &long_number);
printf("Enter a long long int number: ");
scanf("%lld", &long_long_number);
printf("You entered the following numbers:\n");
printf("short int: %hd\n", short_number);
printf("long int: %ld\n", long_number);
printf("long long int: %lld\n", long_long_number);
return 0;
}
If we run the program and enter the numbers 42, 2147483647 and 9223372036854775807, we get the following output:
Enter a short int number: 42
Enter a long int number: 2147483647
Enter a long long int number: 9223372036854775807
You entered the following numbers:
short int: 42
long int: 2147483647
long long int: 9223372036854775807
As can be observed, the entered values were correctly read and stored in the variables short_number, long_number and long_long_number.
In the same way we can read unsigned values from the keyboard. In this case, we must use the format specifiers %hu, %lu and %llu for unsigned short int, unsigned long int and unsigned long long int, respectively.
The flexibility of scanf also lies in the fact that we can read integer values in different bases. To do this, we must use the same format specifiers seen above for the printf function.
For example, the following program reads an integer number in octal, hexadecimal and binary base:
#include <stdio.h>
int main() {
int octal_number, hexadecimal_number, binary_number;
printf("Enter a number in octal base: ");
scanf("%o", &octal_number);
printf("Enter a number in hexadecimal base: ");
scanf("%x", &hexadecimal_number);
printf("Enter a number in binary base: ");
scanf("%b", &binary_number);
printf("You entered the following numbers:\n");
printf("Octal: %d\n", octal_number);
printf("Hexadecimal: %d\n", hexadecimal_number);
printf("Binary: %d\n", binary_number);
return 0;
}
If we run the program and enter the numbers 23, ABAC, 101010, we get the following output:
Enter a number in octal base: 23
Enter a number in hexadecimal base: ABAC
Enter a number in binary base: 101010
You entered the following numbers:
Octal: 19
Hexadecimal: 43948
Binary: 42
An important detail concerns entering numbers in hexadecimal base. In fact, the scanf function does not distinguish between %x and %X. Both formats correctly read hexadecimal numbers, regardless of whether the letters are uppercase or lowercase.
Reading Integers from the Keyboard with scanf
The syntax of format specifiers for reading integers with the scanf function is as follows:
%<size><format>
Where <size> can be one of the following letters:
hforshort int;lforlong int;llforlong long int;- if omitted,
intis assumed.
While <format> can be one of the following letters:
dfor signed integers;ufor unsigned integers;ofor octal base;xorXfor hexadecimal base and no distinction is made between uppercase and lowercase;bfor binary base.
In Summary
In this lesson we have seen how to read and write integer variables in C language using the printf function.
We have seen that, to correctly print integer variables of a type other than int, it is necessary to use different format specifiers, such as %hd, %ld, %lld and %u.
Furthermore, we have seen that the printf function allows printing integers in bases other than decimal, using format specifiers such as %o, %x, %X and %b.
Finally, we have seen how to read integer values from the keyboard using the scanf function, and how to apply the same format specifiers seen above for the printf function.