4.3 C++ Streams
What is a Stream?
A stream is an abstraction for a sequence of bytes flowing between a program and a device (keyboard, screen, file, network). C++ I/O is stream-based — the same operators (<<, >>) work for any stream.
Source → Stream → Destination
| Direction | Examples |
|---|---|
| Input | Keyboard, file, network → program |
| Output | Program → screen, file, network |
---
The C++ Stream Class Hierarchy
ios_base
│
▼
ios
/ \
/ \
istream ostream
| \ / |
/ iostream \
/ | \
ifstream fstream ofstream
istringstream stringstream ostringstream
| Class | Header | Role |
|---|---|---|
ios_base | <ios> | Base format flags |
ios | <ios> | Generic stream state |
istream | <istream> | Input stream |
ostream | <ostream> | Output stream |
iostream | <iostream> | Bidirectional |
ifstream | <fstream> | File input |
ofstream | <fstream> | File output |
fstream | <fstream> | File input + output |
stringstream | <sstream> | In-memory string |
---
Predefined Stream Objects
| Object | Type | Connected to | Buffered |
|---|---|---|---|
cin | istream | Keyboard (stdin) | Line-buffered |
cout | ostream | Screen (stdout) | Line/full-buffered |
cerr | ostream | Screen (stderr) | Unbuffered — appears immediately |
clog | ostream | Screen (stderr) | Buffered |
Plus wide-character variants: wcin, wcout, wcerr, wclog (for wchar_t).
---
Basic I/O Operations
Output with << (insertion operator)
cout << "Hello"; // string literal
cout << 42; // int
cout << 3.14; // double
cout << 'A'; // char
cout << endl; // newline + flush
cout << "Name: " << name << ", Age: " << age << endl; // chained
Input with >> (extraction operator)
int age;
string name;
cin >> age; // reads an int
cin >> name; // reads a word (no spaces)
cin >> age >> name; // both, in order
>> skips leading whitespace and stops at next whitespace.
Reading a line with spaces — getline
string fullName;
getline(cin, fullName); // reads until newline
Reading single character — get()
char c;
cin.get(c); // reads one character (including whitespace)
Writing single character — put()
cout.put('A'); // outputs A
---
Unformatted I/O
| Method | Purpose |
|---|---|
cin.get() | Read one character |
cin.get(buf, size) | Read up to size-1 chars |
cin.getline(buf, size) | Read line into char buffer |
cin.read(buf, n) | Read exactly n bytes (binary) |
cin.ignore(n) | Skip n characters |
cin.peek() | Look at next char without consuming |
cin.putback(c) | Put back one character |
cin.gcount() | Number of characters last read |
cout.put(c) | Write one character |
cout.write(buf, n) | Write exactly n bytes (binary) |
---
Manipulators
Manipulators are functions that modify stream state. Used with << or >>.
Common manipulators
#include <iomanip> // for setw, setprecision, etc.
int main() {
double pi = 3.141592653589;
cout << pi << endl; // 3.14159 (default 6 digits)
cout << setprecision(4) << pi << endl; // 3.142
cout << fixed << setprecision(2) << pi; // 3.14
cout << endl;
cout << setw(10) << "Hi" << endl; // " Hi" (right-aligned, width 10)
cout << setw(10) << left << "Hi" << endl; // "Hi " (left-aligned)
cout << setfill('*') << setw(8) << 42 << endl; // "******42"
cout << hex << 255 << endl; // ff
cout << oct << 8 << endl; // 10
cout << dec << 255 << endl; // 255
cout << boolalpha << true << endl; // true (not 1)
cout << showpos << 42 << endl; // +42
return 0;
}
Manipulator categories
| Category | Examples |
|---|---|
| Width | setw(n) |
| Precision | setprecision(n), fixed, scientific |
| Base | hex, oct, dec, showbase |
| Alignment | left, right, internal |
| Fill | setfill(c) |
| Boolean | boolalpha, noboolalpha |
| Sign | showpos, noshowpos |
| Case | uppercase, nouppercase |
| Flush | endl, flush, ends |
| Whitespace | skipws, noskipws |
Custom manipulators
// Simple manipulator — function taking and returning ostream&
ostream& tab(ostream& os) {
return os << "\t";
}
cout << "Name" << tab << "Age"; // "Name\tAge"
---
Stream State / Error Checking
Streams maintain state flags:
| Flag | Meaning |
|---|---|
goodbit | All OK |
eofbit | End-of-file reached |
failbit | Format error (e.g., reading "abc" into int) |
badbit | Stream corrupted (low-level I/O error) |
Check methods
if (cin.good()) { /* all OK */ }
if (cin.eof()) { /* end of file */ }
if (cin.fail()) { /* format error or EOF */ }
if (cin.bad()) { /* serious error */ }
if (cin) { /* shorthand: not fail and not bad */ }
Idiomatic input loop
int n;
while (cin >> n) { // continues until extraction fails
cout << n * 2 << endl;
}
When cin >> n fails (non-int input or EOF), the conversion to bool returns false.
Recovering from error
int n;
cin >> n;
if (cin.fail()) {
cin.clear(); // clear error flags
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // discard bad input
}
---
stringstream — In-Memory Streams
A stringstream reads/writes to a string instead of console or file. Useful for parsing or building strings.
#include <sstream>
// Read from string (like cin):
istringstream iss("42 3.14 hello");
int n;
double d;
string s;
iss >> n >> d >> s;
cout << n << " " << d << " " << s; // 42 3.14 hello
// Write to string (like cout):
ostringstream oss;
oss << "Value is " << 42;
string result = oss.str(); // "Value is 42"
Common uses
- Parsing input fields
- Building log messages
- Number-to-string and string-to-number conversion (before C++11's
std::to_string)
---
Overloading << and >> for User-Defined Types
Already mentioned in Unit III; here's the full pattern:
class Point {
private:
int x, y;
public:
Point(int a = 0, int b = 0) : x(a), y(b) {}
friend ostream& operator<<(ostream& os, const Point& p);
friend istream& operator>>(istream& is, Point& p);
};
ostream& operator<<(ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os;
}
istream& operator>>(istream& is, Point& p) {
is >> p.x >> p.y;
return is;
}
int main() {
Point p(3, 4);
cout << p << endl; // (3, 4)
Point p2;
cin >> p2;
cout << p2;
return 0;
}
Key points:
- Returns the stream reference → enables chaining
- Friend (or non-member) because left operand is the stream
- For output, take
const T&(no modification); for input, takeT&(modifies)
---
Buffered vs Unbuffered I/O
Buffered (default for cout)
- Output collected in a buffer until flushed
- Flushed by:
endl,flush, buffer full, program end
Unbuffered (cerr)
- Each character written immediately
- For error output that must appear even if program crashes
cout << "Hello"; // may not appear yet
cout << flush; // forces flush
cout << "World" << endl; // newline + flush
cerr << "Error!"; // appears immediately
\n vs endl:
\n— just newline characterendl— newline + flush (slower but ensures output appears)
For performance, prefer \n inside loops; use endl when you need immediate output.
---
Synchronisation with C stdio
By default, C++ cin / cout are synchronised with C's scanf / printf — allowing mixed use. This has a performance cost.
ios_base::sync_with_stdio(false); // disable sync — faster I/O
cin.tie(nullptr); // untie cin from cout
After these calls, cin / cout are 2-5× faster (relevant for competitive programming).
---
Complete Example — Reading & Printing Student Records
#include <iostream>
#include <iomanip>
using namespace std;
struct Student {
string name;
int id;
double marks;
};
int main() {
int n;
cout << "Enter number of students: ";
cin >> n;
Student* students = new Student[n];
for (int i = 0; i < n; i++) {
cout << "Student " << i + 1 << "\n";
cout << " Name: ";
cin >> students[i].name;
cout << " ID: ";
cin >> students[i].id;
cout << " Marks: ";
cin >> students[i].marks;
}
cout << "\n" << left
<< setw(20) << "Name"
<< setw(10) << "ID"
<< setw(10) << "Marks" << "\n";
cout << string(40, '-') << "\n";
for (int i = 0; i < n; i++) {
cout << left
<< setw(20) << students[i].name
<< setw(10) << students[i].id
<< fixed << setprecision(2) << students[i].marks << "\n";
}
delete[] students;
return 0;
}
---
Study deep
endlflushes —\ndoes not. For tight loops outputting many lines, prefer\n.endlis for when output must be visible (interactive prompts, error messages, before crashes).
>>skips whitespace;get/getlinedon't. Mix carefully. Aftercin >> age, a newline remains in the buffer —getlinereads it as empty. Fix:cin.ignore();
- Streams are stateful. Stream flags persist across calls (e.g.,
hex). Forgetting to reset them causes confusing output.
- Modern
std::format(C++20) — like Python's f-strings:
cout << format("Hello {}, you are {} years old", name, age);
Type-safe alternative to printf.
- Boost.Format and
std::formatfor complex output.<iomanip>is verbose;std::formatis concise and modern. For now, IPU expects<iomanip>style.
Key Terms — Lesson 4.3
The terms below cover C++ streams — the stream class hierarchy, I/O operations, manipulators — every PYQ on streams expects fluent use.
Stream — An abstraction representing a sequential flow of bytes to or from a source/destination. In C++ a stream is an object of a class derived from ios_base. Streams unify console, file, and string I/O behind the same operators (<<, >>).
ios / ios_base — The root of the C++ stream class hierarchy. Provides the common state (flags, format, error bits, locale) used by all streams. Application code rarely uses it directly; it sits one level beneath istream/ostream.
istream / ostream / iostream — Three core stream classes. istream is for input (cin is an istream). ostream is for output (cout, cerr, clog are ostreams). iostream is for bidirectional I/O (combines both).
Stream Hierarchy — The inheritance graph: ios → istream/ostream → iostream (bidirectional). File streams (ifstream, ofstream, fstream) and string streams (istringstream, ostringstream, stringstream) derive from the corresponding classes.
Predefined Stream Objects — Four stream instances declared in <iostream>: cin (standard input), cout (standard output, buffered), cerr (standard error, unbuffered), clog (standard error, buffered).
cin — Standard Input Stream — The istream object bound to stdin (keyboard / piped input). Reading with >> skips leading whitespace and stops at the first whitespace.
cout — Standard Output Stream — The ostream object bound to stdout (terminal / piped output). Buffered by default — output may not appear until the buffer flushes (endl, flush, program end, full buffer).
cerr — Standard Error Stream (Unbuffered) — The ostream bound to stderr, unbuffered so error messages appear immediately. Good for urgent diagnostics; not affected by cout redirection.
clog — Standard Error Stream (Buffered) — A buffered counterpart of cerr for log messages where immediate visibility is less critical.
Insertion Operator << — In stream context, the operator that inserts the right operand into the left stream. cout << x writes x to cout. Returns the stream by reference to enable chaining (cout << a << b << c).
Extraction Operator >> — In stream context, the operator that extracts a value from the left stream into the right variable. cin >> x reads from cin into x. Returns the stream by reference; checking the returned stream in a boolean context indicates success.
Manipulator — A function (or function-like object) applied to a stream to modify its behaviour. Includes endl (newline + flush), flush (force buffer flush), setw(n) (field width), setfill(c) (fill character), setprecision(n) (decimal precision), fixed / scientific (notation), hex / oct / dec (number base), boolalpha (print bools as true/false), left/right/internal (alignment).
<iomanip> Header — The standard header providing parameterised manipulators — setw, setprecision, setfill, setbase. Manipulators without parameters live in <iostream>.
endl vs "\n" — Both insert a newline. endl also flushes the output buffer (slower but ensures immediate visibility). "\n" just writes the newline character. Use \n in tight loops, endl for prompts and error messages.
Buffered I/O — I/O that accumulates data in a memory buffer before transmitting. cout is buffered; output may sit in the buffer until endl, flush, a full buffer, or program termination forces it out. Improves throughput at the cost of latency.
Flushing — Forcing the stream buffer to write its contents to the underlying device. Achieved by endl, flush manipulator, or stream.flush() method. Important before crashes (so logged errors actually appear) and in interactive prompts.
Format State / Stream State — A set of persistent flags carried by the stream object — number base, precision, width, alignment, fill character, boolalpha. Changes persist across operations until explicitly reset. stream.setf(), stream.unsetf(), stream.flags() manipulate them.
Error State Flags — Stream state bits indicating I/O outcome. good (no errors), eof (end-of-file reached), fail (logical error — wrong type read), bad (irrecoverable I/O error — file gone). Checked via stream.good(), stream.eof(), stream.fail(), stream.bad().
getline() — A function that reads a full line (including spaces) from an istream until a delimiter (default \n). getline(cin, line);. Avoids the whitespace-stops-extraction behaviour of >>.
get() / put() — Character-level stream methods. cin.get(c) reads one character (including whitespace). cout.put(c) writes one character. The character-level equivalents of >> and <<.
read() / write() — Block-level binary stream methods. stream.read(buf, n) reads up to n raw bytes. stream.write(buf, n) writes n raw bytes. Used heavily in binary file I/O (next lesson).
Operator Overloading for Streams — Defining operator<< and operator>> for a user-defined class to support cout << myObj and cin >> myObj. Implemented as friend functions because the left operand is a stream (not the user class). Returns the stream by reference for chaining.
String Stream (stringstream) — A stream whose underlying source/destination is a std::string, not a file or console. istringstream for input, ostringstream for output, stringstream for both. Useful for parsing numbers from text, formatting strings, in-memory I/O.
Synchronisation with C Streams — By default, cin/cout are synchronised with stdin/stdout so they can be mixed. Disabling this with ios_base::sync_with_stdio(false); makes them 2–5× faster — relevant for competitive programming. cin.tie(nullptr); further decouples cin from cout flushing.
Stream Tying — A mechanism where one stream automatically flushes another before any operation. By default, cin is tied to cout, so reading from cin first flushes cout (ensuring prompts are visible before the user types).
std::format (C++20) — A modern, type-safe formatting library inspired by Python's f-strings. format("Hello {}, age {}", name, age). The C++20 alternative to verbose iomanip-based formatting or unsafe printf.
---
PYQ pattern: "Explain C++ stream classes and their hierarchy." — Define stream; show diagram (ios → istream/ostream → iostream → fstream); list predefined objects (cin, cout, cerr, clog).
PYQ pattern: "What are manipulators in C++? Give examples." — Define;setw,setprecision,hex,fixed,endl; show code using<iomanip>.
PYQ pattern: "Overload<<and>>operators for a class." — Use friend functions; return reference to stream; example with Point or Complex.