OOP · ENCT 151

Ch 7. Stream Computation

6 hours · 8 marks

7.1 Input/Output Stream Class Hierarchy

A stream is an abstraction representing a flow of data (bytes) between a program and a device (console, file, memory). C++ I/O is built around a class hierarchy in <iostream>:

Predefined objects: cin (standard input), cout (standard output), cerr (unbuffered standard error), clog (buffered standard error).

7.2 Testing Stream Errors

Each stream maintains state flags checked via member functions:

FunctionMeaning
good()No error flags set — stream is usable.
eof()End-of-file has been reached.
fail()A formatting or extraction error occurred (recoverable).
bad()A serious, likely unrecoverable I/O error occurred.
clear()Resets all error state flags.
int x;
cin >> x;
if (cin.fail()) { cout << "Invalid input"; cin.clear(); }

7.3 Unformatted and Formatted I/O

Unformatted I/O works with raw characters/bytes without interpretation — e.g., get(), put(), getline(), read(), write().

Formatted I/O interprets data according to type and formatting rules, using >>/<< along with manipulators (setw, setprecision, fixed) to control width, precision, base, and alignment.

#include <iomanip>
cout << setw(10) << setfill('*') << 42 << endl;    // formatted
cout << fixed << setprecision(2) << 3.14159 << endl; // 3.14

char ch;
cin.get(ch);                 // unformatted single character input
cout.put('A');                // unformatted single character output

7.4 Stream Operator Overloading

The insertion (<<) and extraction (>>) operators can be overloaded for user-defined classes so objects can be directly written to/read from streams. Because the left operand is a stream object (ostream/istream), these MUST be overloaded as non-member (usually friend) functions.

class Point {
    int x, y;
public:
    Point(int a=0, int b=0): x(a), y(b) {}
    friend ostream &operator<<(ostream &out, const Point &p) {
        out << "(" << p.x << ", " << p.y << ")";
        return out;                 // returning ostream& allows chaining: cout << p1 << p2;
    }
    friend istream &operator>>(istream &in, Point &p) {
        in >> p.x >> p.y;
        return in;
    }
};
int main() {
    Point p;
    cin >> p;
    cout << p;
}

7.5 File Input/Output with Streams

File streams (from <fstream>) let a program read from or write to files on disk, using the same <</>> syntax as console I/O.

#include <fstream>
ofstream fout("data.txt");     // open for writing (creates/truncates file)
fout << "Hello File";
fout.close();

ifstream fin("data.txt");       // open for reading
string line;
getline(fin, line);
fin.close();

7.6 File Stream Class Hierarchy

All three ultimately derive from the common base ios, inheriting formatting and error-state functionality.

7.7 ASCII and Binary Files

ASCII (text) fileBinary file
Data stored as human-readable charactersData stored as raw bytes (memory representation)
Opened without ios::binary (default text mode)Opened with ios::binary flag
Larger file size, portable, editable with any text editorCompact, faster I/O, but not human-readable
Uses <</>>Uses read()/write()
ofstream fout("data.bin", ios::binary);
fout.write(reinterpret_cast<char*>(&obj), sizeof(obj));

7.8 Read/Write from File

struct Record { int id; char name[20]; };
Record r = {1, "Ram"};
ofstream fout("rec.dat", ios::binary);
fout.write((char*)&r, sizeof(r));
fout.close();

Record r2;
ifstream fin("rec.dat", ios::binary);
fin.read((char*)&r2, sizeof(r2));
fin.close();

7.9 Sequential Access to File

Data is read/written in order from beginning to end, one record after another — simplest and most common access mode, suitable when records are always processed in order.

7.10 Random Access to File

Allows jumping directly to any position in the file without reading everything before it, using file pointer manipulation functions (seekg/seekp) combined with fixed-size records.

fstream file("rec.dat", ios::in | ios::out | ios::binary);
file.seekg(2 * sizeof(Record));   // jump directly to the 3rd record (index 2)
file.read((char*)&r, sizeof(r));

7.11 File Access Pointers and Their Manipulators

7.12 Testing Errors During File Operations

ifstream fin("nofile.txt");
if (!fin) { cout << "File could not be opened"; }   // uses overloaded operator!
if (fin.is_open()) { ... }
if (fin.fail()) { ... }

7.13 File I/O with Member Functions

Instead of overloaded operators, file streams offer explicit member functions for finer control: open(), close(), is_open(), read(), write(), get(), put(), getline(), eof().

fstream f;
f.open("data.txt", ios::out);
if (f.is_open()) { f << "text"; f.close(); }

Most Probable Questions

Q1. Explain the C++ stream class hierarchy with a diagram. 6 marks
Draw/describe: ios at the top, branching to istream and ostream; iostream inherits both; ifstream derives from istream, ofstream from ostream, fstream from iostream — see section 7.1.
Q2. Write a program to overload the << and >> operators for a user-defined class Complex. 7 marks
Explain why these must be non-member/friend functions (left operand is the stream, not the class object), then adapt the pattern in section 7.4 for a Complex class with real and imaginary parts.
Q3. Differentiate between sequential access and random access to files. 4 marks
Sequential access reads/writes records strictly in order from the start; to reach record N you must pass through records 1..N-1. Random access uses seekg/seekp with fixed-size records to jump directly to any record's byte offset, giving direct O(1) access. See sections 7.9–7.11.
Q4. Write a program to write a class object to a file and read it back using binary mode. 7 marks
#include <fstream>
#include <iostream>
using namespace std;
class Student { public: int roll; char name[20]; };
int main() {
    Student s1 = {1, "Ram"};
    ofstream fout("s.dat", ios::binary);
    fout.write((char*)&s1, sizeof(s1));
    fout.close();

    Student s2;
    ifstream fin("s.dat", ios::binary);
    fin.read((char*)&s2, sizeof(s2));
    fin.close();
    cout << s2.roll << " " << s2.name;
}
Q5. Differentiate between ASCII (text) files and binary files. 4 marks
See table in section 7.7: text files store human-readable characters and use <</>>; binary files store raw memory bytes, need the ios::binary flag and read()/write(), and are more compact but not human-readable.
Q6. Explain seekg(), seekp(), tellg(), and tellp() with examples. 5 marks
See section 7.11 — seekg/tellg control/query the read (get) pointer position; seekp/tellp control/query the write (put) pointer position; both accept an optional direction flag (ios::beg, ios::cur, ios::end).
Q7. What is the difference between formatted and unformatted I/O? Give examples of each. 4 marks
Unformatted I/O transfers raw characters without type interpretation (get(), put(), read(), write()). Formatted I/O interprets data according to its type and applies formatting via manipulators like setw, setprecision, fixed, used with <</>>. See section 7.3.
Q8. How do you test for errors during file operations in C++? 4 marks
Check the stream's state after opening/using it: the overloaded ! operator or fail() after opening (file may not exist), is_open() to confirm a stream is currently attached to a file, eof() to detect end-of-file, and good()/bad() for overall/serious error checks. See section 7.12.
← Chapter 6 Next: Chapter 8 — Templates →