Step 1 of 5 · Reading · ~3 min
Learn
Strings
Output Formatting
By the end of this lesson you can print numbers with an exact number of decimal places and line values up in fixed-width columns, using the manipulators from <iomanip>. A manipulator is something you insert into std::cout with << that prints nothing itself but changes how the following values are printed.
Decimal places: std::fixed plus std::setprecision
By default std::cout prints a double with 6 significant digits and drops trailing zeros:
std::cout << 2.0 / 7.0 << "\n"; // 0.285714
std::cout << 5.0 << "\n"; // 5
std::cout << 4200000.0 << "\n"; // 4.2e+06
std::setprecision(n) on its own still counts significant digits, so it can surprise you. Put std::fixed in front and n becomes digits after the decimal point, rounded, with trailing zeros kept:
| value | setprecision(1) alone | fixed << setprecision(1) |
|---|---|---|
2.0 / 7.0 | 0.3 | 0.3 |
5.0 | 5 | 5.0 |
4200000.0 | 4e+06 | 4200000.0 |
0.96 | 1 | 1.0 |
Both are sticky: once inserted they stay in force for every later double on that stream, until you change them. Integers are never affected by precision; an int 7 prints as 7 either way.
Column width: std::setw
std::setw(n) pads the next value with spaces to at least n characters. By default the padding goes on the left, so the value sits at the right edge (right-aligned). std::left moves the padding to the other side; std::right moves it back. Here [ and ] are printed only so you can see the spaces:
std::cout << "[" << std::setw(6) << 42 << "]\n"; // [ 42]
std::cout << "[" << std::left << std::setw(6) << 42 << "]\n"; // [42 ]
std::cout << "[" << std::setw(6) << "ok" << "]\n"; // [ok ] left is still on
std::cout << "[" << std::setw(3) << "overflow" << "]\n"; // [overflow]
Three rules come out of that block. setw is not sticky: it applies to one value and then resets to 0. std::left and std::right are sticky, so the third line is still left-aligned. And setw never cuts anything: a value longer than the width is printed whole.
Composing a row
Here is a weather line: a temperature right-aligned in 6 columns with one decimal, a space, a city left-aligned in 8 columns, then a marker:
#include <iostream>
#include <iomanip>
#include <string>
int main() {
std::string city = "Oslo";
double temp = 43.0 / 2.0; // 21.5
std::cout << std::fixed << std::setprecision(1);
std::cout << std::setw(6) << temp << " "
<< std::left << std::setw(8) << city << "*\n";
return 0;
}
Trace it character by character: 21.5 is 4 characters, so setw(6) adds 2 spaces before it; then the literal space; then Oslo plus 4 spaces to fill 8; then *:
21.5 Oslo *
Each column gets its own setw right before its value. Alignment only needs to be inserted when it changes, but because it is sticky, a second row printed by this program would start with std::left still in force, and its temperature would come out as 21.5 .
Common mistakes
setprecisionwithoutfixed.12.0prints as12instead of12.00, and987640.0withsetprecision(2)prints9.9e+05.- Forgetting to switch back with
std::right. Afterstd::leftfor a text column, a number meant to be right-aligned prints as3instead of3. - One
setwfor the whole line.setwpads only the value right after it; the other columns come out unpadded, like|3|3.75. - Expecting
setwto shorten long text. A 17-character name in a 10-wide column prints all 17 characters and pushes the rest of the row right. That is correct behaviour; do not try to trim it.
Your exercise
Print one receipt row: item name, quantity and line total, each in its own fixed-width column separated by |. The starter already reads the input, computes the total and prints the three values with the separators, but with no formatting. Add the manipulators. The most likely mistake is leaving std::left in force for the quantity column.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…