Fundamentals

Input and Output

Master C++ I/O — cin, cout, cerr, getline, formatted output with iomanip, file streams, and printf vs cout comparison.

Input and Output

C++ provides two I/O systems: the classic C-style printf/scanf and the modern C++ stream library (iostream). Streams are type-safe and extensible — you can overload << and >> for your own types. This topic covers everything you need to read input and format output professionally.


The Standard Streams

cpp
#include <iostream>
using namespace std;

int main() {
    // cout — standard output (screen)
    cout << "Hello, World!\n";

    // cerr — standard error (unbuffered, always visible even with redirected output)
    cerr << "Error: something went wrong\n";

    // clog — standard log (buffered standard error)
    clog << "Info: program started\n";

    // endl vs "\n"
    cout << "With endl" << endl;    // flushes buffer (slower)
    cout << "With newline\n";       // just a newline (faster)

    return 0;
}

Note: Prefer "\n" over endl in performance-sensitive code. endl flushes the output buffer every time it is called, which is significantly slower when printing many lines.


Basic Output with cout

cpp
#include <iostream>
using namespace std;

int main() {
    int    age    = 25;
    double salary = 75000.50;
    char   grade  = 'A';
    bool   active = true;

    // Chain multiple values with <<
    cout << "Age: " << age << "\n";
    cout << "Salary: " << salary << "\n";
    cout << "Grade: " << grade << "\n";
    cout << boolalpha << "Active: " << active << "\n";
    // Output:
    // Age: 25
    // Salary: 75000.5
    // Grade: A
    // Active: true

    // Concatenation-style output
    cout << "Name: " << "Alice" << ", Age: " << age << ", Grade: " << grade << "\n";
    // Name: Alice, Age: 25, Grade: A

    return 0;
}

Formatted Output with iomanip

cpp
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    double pi = 3.14159265358979;

    // Precision
    cout << pi                        << "\n";  // 3.14159  (default 6 significant digits)
    cout << fixed << setprecision(2) << pi << "\n";  // 3.14
    cout << fixed << setprecision(8) << pi << "\n";  // 3.14159265
    cout << scientific << pi          << "\n";  // 3.141593e+00

    // Width and alignment
    cout << setw(10) << "Name" << setw(8) << "Score" << "\n";
    cout << setw(10) << "Alice" << setw(8) << 95     << "\n";
    cout << setw(10) << "Bob"   << setw(8) << 87     << "\n";
    // Output:
    //       Name   Score
    //      Alice      95
    //        Bob      87

    // Left-align with setfill
    cout << left << setfill('-') << setw(20) << "Hello" << "\n";
    // Hello---------------

    // Right-align (default)
    cout << right << setfill('0') << setw(8) << 42 << "\n";
    // 00000042

    // Hexadecimal, octal, decimal
    int n = 255;
    cout << dec << n << "\n";   // 255
    cout << hex << n << "\n";   // ff
    cout << oct << n << "\n";   // 377
    cout << hex << uppercase << n << "\n";  // FF

    return 0;
}

Basic Input with cin

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
    // Read a single integer
    int age;
    cout << "Enter your age: ";
    cin >> age;
    cout << "Age: " << age << "\n";

    // Read a double
    double weight;
    cout << "Enter weight (kg): ";
    cin >> weight;

    // Read a single word (stops at whitespace)
    string firstName;
    cout << "Enter first name: ";
    cin >> firstName;
    cout << "Hello, " << firstName << "!\n";

    // Read multiple values at once
    int x, y;
    cout << "Enter two numbers: ";
    cin >> x >> y;
    cout << "Sum: " << x + y << "\n";

    return 0;
}

Reading Full Lines with getline

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
    string fullName;
    int age;

    cout << "Enter age: ";
    cin >> age;

    // IMPORTANT: cin >> leaves '\n' in the buffer
    // getline after cin >> will read empty line without this fix
    cin.ignore();              // Discard the leftover newline

    cout << "Enter full name: ";
    getline(cin, fullName);   // Reads the entire line including spaces

    cout << "Name: " << fullName << ", Age: " << age << "\n";

    // Reading multiple lines
    string line;
    cout << "Enter lines (type 'quit' to stop):\n";
    while (getline(cin, line) && line != "quit") {
        cout << "You said: " << line << "\n";
    }

    return 0;
}

Input Validation

cpp
#include <iostream>
#include <string>
#include <limits>
using namespace std;

int readPositiveInt(const string& prompt) {
    int value;
    while (true) {
        cout << prompt;
        if (cin >> value && value > 0) {
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            return value;
        }

        // Input failed or value <= 0
        cout << "Invalid input. Please enter a positive integer.\n";
        cin.clear();                                         // Clear error flags
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Discard bad input
    }
}

double readDouble(const string& prompt, double min, double max) {
    double value;
    while (true) {
        cout << prompt;
        if (cin >> value && value >= min && value <= max) {
            return value;
        }
        cout << "Please enter a number between " << min << " and " << max << ".\n";
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
}

int main() {
    int count = readPositiveInt("How many items? ");
    double price = readDouble("Price (0–1000): ", 0.0, 1000.0);
    cout << "Total: " << count * price << "\n";
    return 0;
}

printf and scanf (C-Style)

Although cout/cin are preferred in C++, the C-style functions work in C++ and are sometimes used in competitive programming or performance-critical code:

cpp
#include <cstdio>

int main() {
    // printf — formatted output
    int age = 25;
    double pi = 3.14159;
    printf("Age: %d\n", age);          // Age: 25
    printf("Pi: %.4f\n", pi);          // Pi: 3.1416
    printf("Hex: %X\n", 255);          // Hex: FF
    printf("Sci: %e\n", pi);           // Sci: 3.141590e+00
    printf("%-10s|%5d\n", "Alice", 95);// Alice     |   95

    // scanf — formatted input (no type safety!)
    int n;
    scanf("%d", &n);   // Note: & required for address

    return 0;
}
Featurecout / cinprintf / scanf
Type safetyYes — compiler checksNo — format string mismatch = UB
ExtensibleYes — overload <</>>No
SpeedSlightly slower (can be made fast)Fast
SyntaxIntuitiveCompact but error-prone
Recommended forModern C++Performance-critical, competitive

Practical Example: Formatted Report

cpp
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;

struct Student {
    string name;
    int    score;
    double gpa;
};

void printReport(const vector<Student>& students) {
    const int W_NAME  = 15;
    const int W_SCORE =  8;
    const int W_GPA   =  8;
    const int W_GRADE =  8;

    // Header
    cout << string(W_NAME + W_SCORE + W_GPA + W_GRADE + 3, '-') << "\n";
    cout << left  << setw(W_NAME)  << "Name"
         << right << setw(W_SCORE) << "Score"
                  << setw(W_GPA)   << "GPA"
                  << setw(W_GRADE) << "Grade" << "\n";
    cout << string(W_NAME + W_SCORE + W_GPA + W_GRADE + 3, '-') << "\n";

    // Rows
    for (const auto& s : students) {
        string grade = (s.score >= 90) ? "A" :
                       (s.score >= 80) ? "B" :
                       (s.score >= 70) ? "C" : "F";

        cout << fixed << setprecision(2);
        cout << left  << setw(W_NAME)  << s.name
             << right << setw(W_SCORE) << s.score
                      << setw(W_GPA)   << s.gpa
                      << setw(W_GRADE) << grade << "\n";
    }
    cout << string(W_NAME + W_SCORE + W_GPA + W_GRADE + 3, '-') << "\n";
}

int main() {
    vector<Student> students = {
        {"Alice",   92, 3.9},
        {"Bob",     78, 3.2},
        {"Charlie", 85, 3.5},
        {"Diana",   60, 2.1},
    };

    cout << "\n  === Student Report ===\n\n";
    printReport(students);
    return 0;
}
// Output:
//   === Student Report ===
//
// -------------------------------------------
// Name           Score     GPA   Grade
// -------------------------------------------
// Alice             92    3.90       A
// Bob               78    3.20       B
// Charlie           85    3.50       B
// Diana             60    2.10       F
// -------------------------------------------

Summary

  • cout, cin, cerr, clog are the four standard streams — use cerr for errors
  • Chain values with << for output and >> for input
  • cin >> str reads one word; getline(cin, str) reads the entire line
  • Always call cin.ignore() after cin >> before getline to discard the leftover newline
  • Use <iomanip>: setw(), setprecision(), fixed, left, right, setfill() for professional formatting
  • Validate user input with cin.clear() and cin.ignore() to recover from bad input
  • printf/scanf are faster but not type-safe — prefer cout/cin in modern C++

Next, we'll dive into strings — std::string methods, manipulation, string_view, and the differences between C strings and C++ strings.