In this section, we will print numbers with wildly varying format settings, in order to get familiar with I/O manipulators:
- First, we include all the necessary headers and declare that we use the std namespace by default:
#include <iostream>
#include <iomanip>
#include <locale>
using namespace std;
- Next, we define a helper function that prints a single integer value with different styles. It accepts a padding width and a filling character for padding, which is set to space ' ' by default:
void print_aligned_demo(int val,
size_t width,
char fill_char = ' ')
{
- With setw, we can set the minimum number of characters output for printing a number. If we print 123 with a width of 6, for example, we get " 123", or "123 ". We can control on which side the padding occurs with std::left, std::right, and std::internal. When printing numbers in the decimal form, internal looks identical to right. But if we print the value 0x1, for example, with a width of 6 and with internal, we get "0x 6". The setfill manipulator defines the character that will be used for padding. We will try different styles:
cout << "================n";
cout << setfill(fill_char);
cout << left << setw(width) << val << 'n';
cout << right << setw(width) << val << 'n';
cout << internal << setw(width) << val << 'n';
}
- In the main function, we start using the function we just implemented. At first, we print the value 12345, with a width of 15. We do this twice, but the second time, we use the '_' character for padding:
int main()
{
print_aligned_demo(123456, 15);
print_aligned_demo(123456, 15, '_');
- Afterward, we print the value 0x123abc with the same width as before. However, before doing this, we apply std::hex and std::showbase to tell the output stream object cout that it should print numbers in the hexadecimal format and that it should prepend "0x" to them so that it is obvious that they are to be interpreted as hex:
cout << hex << showbase;
print_aligned_demo(0x123abc, 15);
- We can do the same with oct, which tells cout to use the octal system for printing numbers. The showbase is still active, so 0 will be prepended to every printed number:
cout << oct;
print_aligned_demo(0123456, 15);
- With hex and uppercase, we get the 'x' in "0x" printed upper case. The 'abc' in '0x123abc' is also upper cased:
cout << "A hex number with upper case letters: "
<< hex << uppercase << 0x123abc << 'n';
- If we want to print 100 in the decimal format again, we have to remember that we switched the stream to hex before. By using dec, we can put it back to normal:
cout << "A number: " << 100 << 'n';
cout << dec;
cout << "Oops. now in decimal again: " << 100 << 'n';
- We can also configure how Boolean values are printed. By default, true is printed as 1 and false as 0. With boolalpha, we can set it to a text representation:
cout << "true/false values: "
<< true << ", " << false << 'n';
cout << boolalpha
<< "true/false values: "
<< true << ", " << false << 'n';
- Let's have a look at floating-point variables of the float and double types. If we print a number such as 12.3, it is printed as 12.3, of course. If we have a number such as 12.0, the output stream will just drop the decimal point, which we can change with showpoint. Using this, the decimal point is always displayed:
cout << "doubles: "
<< 12.3 << ", "
<< 12.0 << ", "
<< showpoint << 12.0 << 'n';
- The representation of a floating-point number can be scientific or fixed. scientific means that the number is normalized to such a form that the first digit is the only digit before the decimal point, and then the exponent is printed, which is needed to multiply the number back to its actual size. For example, the value 300.0 would be printed as "3.0E2", because 300 equals 3.0 * 10^2. fixed reverts back to the normal decimal point notation:
cout << "scientific double: " << scientific
<< 123000000000.123 << 'n';
cout << "fixed double: " << fixed
<< 123000000000.123 << 'n';
- Apart from the notation, we can also decide with what precision a floating-point number is printed. Let's create a very small value and print it with 10 digits after the decimal point, and once with just one digit after the decimal point:
cout << "Very precise double: "
<< setprecision(10) << 0.0000000001 << 'n';
cout << "Less precise double: "
<< setprecision(1) << 0.0000000001 << 'n';
}
- Compiling and running the program yields us the following lengthy output. Those four first blocks of output are from the print helper function that tampered around with the setw and left/right/internal modifiers. Afterward, we played with the casing of base representations, Boolean representation, and floating-point formatting. It is a good idea to play with each of these to get familiar with them:
$ ./formatting
================
123456
123456
123456
================
123456_________
_________123456
_________123456
================
0x123abc
0x123abc
0x 123abc
================
0123456
0123456
0123456
A hex number with upper case letters: 0X123ABC
A number: 0X64
Oops. now in decimal again: 100
true/false values: 1, 0
true/false values: true, false
doubles: 12.3, 12, 12.0000
scientific double: 1.230000E+11
fixed double: 123000000000.123001
Very precise double: 0.0000000001
Less precise double: 0.0