Streams, Not Print Statements
C++ does not have a print function in the way Python or Java do. It has streams: objects that represent a flow of characters going somewhere. std::cout is the stream connected to standard output, and << is an operator that pushes a value into it. The stream figures out how to turn an int, a double or a std::string into characters, and because each << returns the stream again, you can chain as many as you like in one statement.
Four streams are declared in <iostream> and the distinction between them matters more than it first appears. std::cout and std::cerr both usually end up on your terminal, but they are different channels: your program's output and your program's diagnostics. That separation is what makes ./app > results.txt useful — the results go into the file while error messages still appear on screen, because only cout was redirected.
So the rule is: results and data go to std::cout; warnings, errors and progress messages go to std::cerr. Students who debug with cout everywhere eventually pipe their program into another program and discover their debug lines have corrupted the data.
One more built-in convenience: std::cin is tied to std::cout by default, which means any pending output is flushed before input is read. That is why std::cout << "Enter age: "; std::cin >> age; shows the prompt before waiting, even though the prompt has no newline.
std::cout— standard output; buffered; where your program's real results gostd::cerr— standard error; flushed on every write, so messages survive a crashstd::clog— standard error too, but buffered; for high-volume loggingstd::cin— standard input; tied tocoutso prompts appear before the wait
#include <iostream>
int main() {
int age = 0;
std::cout << "Enter age: "; // prompt flushed automatically by the tie
std::cin >> age;
if (age < 0) {
std::cerr << "Warning: negative age, using 0\n"; // diagnostics channel
age = 0;
}
std::cout << "Age is " << age << '\n'; // results channel
// ./app > results.txt -> only the cout line lands in the file
} endl or backslash-n?
Nearly every C++ tutorial ends its output lines with std::endl, and it is worth knowing exactly what that costs, because it is one of the few beginner habits that shows up as a measurable slowdown.
std::endl does two things: it writes a newline character, and then it flushes the stream. Flushing means "stop buffering, push everything you are holding to the operating system right now". '\n' writes the newline and nothing else, leaving the stream to flush when its buffer fills, which is exactly what buffering is for.
Buffering exists because talking to the operating system is expensive compared with copying bytes into memory. A stream gathers up your output and hands it over in large chunks. Every endl cancels that optimisation for one line. Print a lakh lines with endl and you have asked the operating system to do a lakh separate writes; print them with '\n' and it may be a few dozen. In a competitive-programming problem with heavy output, this alone is the difference between passing and timing out.
When is a flush the right call? When you need the text to appear before something else happens — a prompt you are about to block on, or a progress message before a long computation. But std::cin is already tied to std::cout, which covers the prompt case automatically, and std::cerr flushes on its own, which covers errors. The remaining cases are rare, and when you genuinely want a flush without a newline you can say so directly with std::flush.
The practical guidance: use '\n' by default. Note the single quotes — '\n' is one character while "\n" is a string, and the character version is marginally cheaper. Reach for std::endl only when you have thought about it and decided you want the flush.
#include <iostream>
int main() {
// These two lines produce identical text
std::cout << "Hello" << std::endl; // newline + flush
std::cout << "Hello" << '\n'; // newline only
// In a loop the difference is real
for (int i = 0; i < 100000; ++i) {
std::cout << i << '\n'; // fast: one buffered write per chunk
// std::cout << i << std::endl; // slow: 100000 flushes
}
// When you really do want a flush without a newline
std::cout << "Working... " << std::flush;
// ... long computation ...
std::cout << "done\n";
} - Buffering is also why a crashing program can appear to stop earlier than it did: output already written to
cout's buffer is lost when the process dies. If you are printing to trace a crash, print tostd::cerr, which flushes every time.
Reading Input Without Getting Stuck
An input stream carries a state, and understanding that state turns input handling from guesswork into something predictable. When std::cin >> n succeeds, the stream stays in a good state. When it fails — because the user typed abc where a number was expected — three things happen at once: n is set to zero, the stream enters a failed state, and the offending characters are left sitting in the buffer, untouched.
The consequence is the infinite loop every beginner writes at least once. Once the stream has failed, every subsequent >> fails immediately without reading anything, so a loop that keeps asking never advances and never blocks. It just spins, printing the prompt forever. Recovering takes exactly two calls: std::cin.clear() resets the state flags, and std::cin.ignore(...) throws away the characters that caused the failure. Miss the second and you clear the error only to hit it again on the same input.
Because a stream converts to true when it is in a good state, while (std::cin >> x) reads as "keep reading numbers while that works". It ends either at end of input — Ctrl+D on Linux and macOS, Ctrl+Z then Enter on Windows — or at the first thing that is not a number. This is the standard shape for reading an unknown quantity of values, and it is worth writing until it feels automatic.
Also remember the pairing from the strings lesson: >> reads one whitespace-delimited token and leaves the newline behind; std::getline reads a whole line including spaces. Mixing them without an ignore in between is the most common input bug in beginner C++.
#include <iostream>
#include <limits>
#include <string>
#include <vector>
int main() {
// Read until end of input or a non-number
std::vector<int> marks;
int value = 0;
while (std::cin >> value) {
marks.push_back(value);
}
std::cout << "read " << marks.size() << " values\n";
// Recovering from bad input instead of looping forever
std::cin.clear(); // reset the failure flags
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
int age = 0;
while (!(std::cin >> age)) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "Please enter a number: ";
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string name;
std::getline(std::cin, name);
std::cout << name << " is " << age << '\n';
} std::cin.ignore()with no arguments discards exactly one character, which is not enough if the user typed several. Passingstd::numeric_limits<std::streamsize>::max()means "as many as it takes" and stops at the delimiter — that is why the call looks so verbose. It needs<limits>.
Formatting Output with iomanip
Printing a number as 3.14159265 when you wanted 3.14, or lining up a table that refuses to line up, is fixed with manipulators — small objects you insert into the stream that change how the next values are formatted. Most live in <iomanip>.
std::fixed switches to fixed-point notation and std::setprecision(2) then means "two digits after the decimal point". Without std::fixed, setprecision means total significant digits instead, which is why students see 3.1 when they expected 3.14. Use the two together whenever you are printing money or measurements.
std::setw(n) sets a minimum field width, padding with spaces to align columns. It has a property that catches everyone exactly once: it applies only to the very next item written, then resets. Every column of every row needs its own setw. std::setprecision, std::fixed, std::left and std::setfill, by contrast, are sticky and stay in effect until you change them.
The remaining handful cover most real needs: std::left and std::right control which side the padding goes on (right is the default, which is why text columns look wrong until you say std::left), std::setfill('0') changes the padding character, and std::boolalpha makes a bool print as true/false instead of 1/0.
#include <iomanip>
#include <iostream>
#include <string>
int main() {
double price = 1249.5;
// fixed + setprecision go together for money
std::cout << std::fixed << std::setprecision(2);
std::cout << "Price: Rs " << price << '\n'; // Price: Rs 1249.50
// A table. setw applies to ONE item, so repeat it per column.
std::cout << std::left << std::setw(12) << "Name"
<< std::right << std::setw(8) << "Score" << '\n';
std::cout << std::left << std::setw(12) << "Ananya"
<< std::right << std::setw(8) << 95 << '\n';
std::cout << std::left << std::setw(12) << "Rahul"
<< std::right << std::setw(8) << 88 << '\n';
// Zero padding, e.g. for a timestamp
int hour = 9, minute = 5;
std::cout << std::setfill('0')
<< std::setw(2) << hour << ':'
<< std::setw(2) << minute << '\n'; // 09:05
std::cout << std::setfill(' '); // reset the fill
std::cout << std::boolalpha << (price > 1000) << '\n'; // true
} std::setfillis sticky, so the'0'you set for a timestamp will keep padding every later column with zeroes until you set it back to a space. Forgetting that reset produces some memorably strange-looking tables.
Fast I/O for Competitive Programming
If you are solving problems on an online judge, you will eventually hit a time limit on a problem whose logic is already optimal. Very often the culprit is input and output rather than your algorithm, and two lines fix it.
By default the C++ streams are kept synchronised with C's printf and scanf family, so that mixing the two produces correctly ordered output. Maintaining that synchronisation costs work on every single operation. std::ios::sync_with_stdio(false) switches it off. The condition attached is straightforward: after doing this, do not use printf or scanf in the same program, because the ordering guarantee is exactly what you gave up.
The second line, std::cin.tie(nullptr), removes the tie that flushes std::cout before every read. That tie is what makes interactive prompts appear on time, and on an online judge there is nobody to read a prompt, so it is pure overhead. Do not use this in an interactive program you expect a human to sit in front of.
Together with using '\n' instead of std::endl, these two lines routinely turn a timing-out solution into an accepted one on problems with large input. They change nothing about correctness, which is why it is safe to make them a habit in that setting and to leave them out everywhere else.
#include <iostream>
#include <vector>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
// From here: no printf/scanf, and no interactive prompts.
int n = 0;
std::cin >> n;
std::vector<long long> a(n);
for (int i = 0; i < n; ++i) std::cin >> a[i];
long long sum = 0;
for (long long x : a) sum += x;
std::cout << sum << '\n'; // '\n', never endl, in a hot output loop
} - This is a competitive-programming tool, not general advice. In an application that talks to a user, or that mixes C and C++ output, leave both settings alone — the defaults exist for good reasons.
