Input and Output with Streams
C++ reads and writes through streams: std::cout for output, std::cin for input and std::cerr for errors. Streams are type-safe — the compiler picks the right conversion for each value — and manipulators control how numbers are formatted.
Reading with std::cin
The extraction operator >> reads a value into a variable, skipping any spaces and newlines first:
#include <iostream> int main() { int age{}; std::cout << "How old are you? "; std::cin >> age; std::cout << "\nNext year you'll be " << age + 1 << ".\n"; }
29
How old are you? Next year you'll be 30.
The input is shown separately; when you type at a terminal, it appears on the same line as the prompt.
#include <iostream> #include <string> int main() { std::string item; int quantity{}; double price{}; std::cin >> item >> quantity >> price; std::cout << quantity << " x " << item << " = " << quantity * price << '\n'; }
apples 6 0.45
6 x apples = 2.7
>> into a std::string reads one word — it stops at whitespace.
Reading whole lines
std::getline reads everything up to the end of the line:
#include <iostream> #include <string> int main() { std::string name; std::cout << "Full name: "; std::getline(std::cin, name); std::cout << "\nHello, " << name << "! (" << name.size() << " characters)\n"; }
Ada Lovelace
Full name: Hello, Ada Lovelace! (12 characters)
A classic trap: after std::cin >> n, the newline is still waiting in the input, so a following getline returns an empty line. Either skip it with std::cin >> std::ws before getline, or read everything with getline and convert (lesson 9).
Checking for bad input
If the input can't be converted — letters where a number was expected — the stream enters a fail state, the variable gets 0, and further reads do nothing until you clear it. Test the stream like a boolean:
#include <iostream> #include <limits> int main() { int guests{}; while (true) { std::cout << "How many guests? "; if (std::cin >> guests && guests > 0) break; if (std::cin.eof()) return 1; // input ended std::cout << "\nPlease enter a positive whole number.\n"; std::cin.clear(); // reset the fail state std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // discard the bad line } std::cout << "\nSetting " << guests << " places.\n"; }
lots -3 6
How many guests? Please enter a positive whole number. How many guests? Please enter a positive whole number. How many guests? Setting 6 places.
Reading until input ends
Because a stream converts to false once input runs out, a read can be a loop condition. This processes every number until the end of input (or a file redirected with ./main < data.txt):
#include <iostream> int main() { double value{}, total{}; int count{}; while (std::cin >> value) { total += value; ++count; } std::cout << count << " values, average " << total / count << '\n'; }
12.5 7.25 30 18
4 values, average 16.9375
Formatting output
Manipulators from <iomanip> change how the next values are printed:
#include <iomanip> #include <iostream> int main() { double pi = 3.14159265; std::cout << pi << '\n'; // default: 6 significant digits std::cout << std::fixed << std::setprecision(2) << pi << '\n'; // 2 decimal places std::cout << std::setw(8) << 42 << "|\n"; // width 8, right-aligned std::cout << std::left << std::setw(8) << 42 << "|\n"; // left-aligned std::cout << std::setfill('0') << std::right << std::setw(5) << 42 << '\n'; std::cout << std::hex << 255 << ' ' << std::dec << 255 << '\n'; std::cout << std::boolalpha << true << '\n'; }
3.14159
3.14
42|
42 |
00042
ff 255
trueMost manipulators are sticky — they stay in effect until changed — except setw, which applies only to the next value. That stickiness is one reason many programmers prefer std::format (lesson 45) for anything non-trivial.
A formatted table
#include <iomanip> #include <iostream> #include <string> int main() { std::cout << std::left << std::setw(10) << "Item" << std::right << std::setw(5) << "Qty" << std::setw(9) << "Price" << '\n'; std::cout << std::fixed << std::setprecision(2); std::cout << std::left << std::setw(10) << "Notebook" << std::right << std::setw(5) << 4 << std::setw(9) << 3.5 << '\n'; std::cout << std::left << std::setw(10) << "Pen" << std::right << std::setw(5) << 10 << std::setw(9) << 1.2 << '\n'; }
Item Qty Price Notebook 4 3.50 Pen 10 1.20
Errors go to std::cerr
std::cerr writes to standard error, which stays visible when normal output is redirected to a file, and is unbuffered so messages appear immediately:
std::cerr << "Error: could not open " << filename << '\n';
Try it yourself
Read a list of temperatures until input ends and print the lowest, highest and average with one decimal place.
14.5 17 12.25 19.75 16
min 12.2, max 19.8, mean 15.9