Input and output formatting
So far every value has been written into the program. std::cin is the input stream: it waits for the user to type something, then puts the value into a variable. Press Run and type a number; the output on the page shows what happens when someone types 25 (what they type isn't shown).
1#include <iostream>2 3int main() {4 int age = 0;5 std::cout << "How old are you?\n";6 std::cin >> age;7 std::cout << "You are " << age << '\n';8 return 0;9}
How old are you? You are 25
In std::cin >> age the arrows point at the variable: the value flows from cin into age. cout uses <<, pointing at cout, so values flow out. >> looks at the variable's type: age is an int, so it reads a whole number.
Reading several values
Like cout, >> can be chained to fill several variables in order. They don't need to have the same type:
1#include <iostream>2 3int main() {4 int count = 0;5 double price = 0;6 std::cout << "How many, and at what price?\n";7 std::cin >> count >> price;8 std::cout << "That's $" << count * price << " in all\n";9 return 0;10}
How many, and at what price? That's $59.7 in all
The user can type 3 19.9 and press Enter, or 3, Enter, 19.9, Enter: >> skips spaces and new lines before it reads the next value.
It stops at a space
>> can read a std::string too. But it reads only one "word": it skips leading spaces and stops at the next space or new line. Say the user types Ana Lee:
1#include <iostream>2#include <string>3 4int main() {5 std::string name;6 std::cout << "What's your name?\n";7 std::cin >> name;8 std::cout << "Hello, " << name << "!\n";9 return 0;10}
What's your name? Hello, Ana!
It only got Ana. The Lee after the space is still waiting in the input for the next read.
getline reads a whole line
To read spaces too, use std::getline(std::cin, s): it puts the rest of the line into s, up to the new line (and leaves the new line out).
1#include <iostream>2#include <string>3 4int main() {5 std::string name;6 std::cout << "What's your name?\n";7 std::getline(std::cin, name);8 std::cout << "Hello, " << name << "!\n";9 return 0;10}
What's your name? Hello, Ana Lee!
getline lives in <string> too. Use it for names, addresses and sentences; use >> for numbers.
getline after cin >>
Reading a number with >> and then a line with getline runs into a well-known problem. The user types 30, Enter, then Ana Lee, Enter:
1#include <iostream>2#include <string>3 4int main() {5 int age = 0;6 std::string name;7 std::cin >> age;8 std::getline(std::cin, name);9 std::cout << "Age: " << age << '\n';10 std::cout << "Name: " << name << '\n';11 return 0;12}
Age: 30 Name:
The name is empty. >> stopped right after 30, so the new line after it is still in the input. getline meets it straight away, decides the line is over, and reads an empty line.
The fix: put std::cin.ignore(); before getline (ignore is something cin itself can do, so it comes after std::cin.). It throws away one character, the leftover new line:
1#include <iostream>2#include <string>3 4int main() {5 int age = 0;6 std::string name;7 std::cin >> age;8 std::cin.ignore();9 std::getline(std::cin, name);10 std::cout << "Age: " << age << '\n';11 std::cout << "Name: " << name << '\n';12 return 0;13}
Age: 30 Name: Ana Lee
Note: ignore() throws away just one character. If the user typed extra spaces after 30, it won't be enough. For now, just remember where this trap is.
Decimal places
You can control how output looks, too; the tools are in <iomanip>. On its own, std::setprecision(n) sets how many digits are shown in all. Only with std::fixed in front does it mean "digits after the decimal point":
1#include <iostream>2#include <iomanip>3 4int main() {5 double average = 86.4567;6 std::cout << average << '\n';7 std::cout << std::setprecision(2) << average << '\n';8 std::cout << std::fixed << average << '\n';9 std::cout << 5.0 << '\n';10 return 0;11}
86.4567 86 86.46 5.00
The second line has just two digits: 86. The third, with std::fixed, has two decimal places, 86.46 (rounded). The last line shows that both settings stay in effect: every double after them gets two decimal places, so even 5.0 shows as 5.00. For prices and averages, write std::fixed << std::setprecision(2) once.
Lining up with setw
std::setw(n) makes the next value take at least n places, padding with spaces on the left, so numbers line up on the right:
1#include <iostream>2#include <iomanip>3 4int main() {5 std::cout << "Tea" << std::setw(6) << 3 << '\n';6 std::cout << "Jam" << std::setw(6) << 12 << '\n';7 std::cout << "Egg" << std::setw(6) << 120 << '\n';8 return 0;9}
Tea 3 Jam 12 Egg 120
Unlike fixed, setw applies only to the one value right after it, so write it before each value you want lined up. It counts bytes: an English letter is one, but characters such as Chinese ones take more, so it won't line those up.
How many spaces are there between [ and 42?
1#include <iostream>2#include <iomanip>3 4int main() {5 std::cout << "[" << std::setw(5) << 42 << "]\n";6 return 0;7}
setw(5) makes 42 take 5 places in all. 42 itself uses 2, so 3 spaces go on the left: [ 42].
Practice
Write the code, then press Check. A hint costs nothing; the answer is there when you need it. Nobody types anything during a check, so the "input" values are already in variables.
A price with two decimals
✓Make the program show Price: 3.50.
Price: 3.50
1#include <iostream>2#include <iomanip>3 4int main() {5 double price = 3.5;6 std::cout << "Price: " << price << '\n';7 return 0;8}
Scores lined up
✓Use std::setw(5) to line the three scores up on the right, as below (each score takes 5 places).
Math 95 Chem 8 Arts 100
1#include <iostream>2#include <iomanip>3 4int main() {5 int math = 95;6 int chem = 8;7 int art = 100;8 9 return 0;10}
Fix it: missing decimals
✓This program should show Total: 12.00, but it shows Total: 12. Fix it.
Total: 12.00
1#include <iostream>2#include <iomanip>3 4int main() {5 double total = 4 * 3.0;6 std::cout << std::setprecision(2);7 std::cout << "Total: " << total << '\n';8 return 0;9}
What you learned
std::cin >> xreads a value intox, the wayx's type says;>>can be chained to read several.>>skips spaces and new lines; for astd::stringit reads one word and stops at a space.std::getline(std::cin, s)reads a whole line, spaces and all.getlineaftercin >>reads the leftover new line; throw it away first withstd::cin.ignore();.<iomanip>:std::fixed << std::setprecision(2)shows two decimal places, and stays in effect.std::setw(n)makes the next value take at leastnplaces, lined up on the right; it covers one value.