Docs

README

C++ Input and Output

Table of Contents

  1. Introduction to I/O Streams
  2. The iostream Library
  3. Standard Output with cout
  4. Standard Input with cin
  5. Output Formatting
  6. Input Handling and Validation
  7. String Input with getline
  8. Error Streams
  9. Buffer Management
  10. Best Practices

Introduction to I/O Streams

C++ uses a stream-based model for input and output. Think of streams as channels through which data flows:

┌─────────────┐     ┌───────────────┐     ┌─────────────┐
│  Keyboard   │────▶│  Input Stream │────▶│  Program    │
└─────────────┘     │    (cin)      │     └─────────────┘
                    └───────────────┘

┌─────────────┐     ┌───────────────┐     ┌─────────────┐
│   Program   │────▶│ Output Stream │────▶│   Screen    │
└─────────────┘     │   (cout)      │     └─────────────┘
                    └───────────────┘

Stream Concept

A stream is:

  • An abstraction representing a device where characters are read or written
  • A sequence of bytes flowing from source to destination
  • Buffered for efficiency (data collected before transfer)

Key Benefits

  • Uniform interface: Same syntax for console, files, strings
  • Type safety: Compiler checks types automatically
  • Extensibility: Can add custom types to stream system

The iostream Library

Including iostream

#include <iostream>  // Required for I/O operations

using namespace std;  // Optional: allows cout instead of std::cout

Standard Stream Objects

ObjectTypePurpose
cinistreamStandard input (keyboard)
coutostreamStandard output (screen)
cerrostreamStandard error (unbuffered)
clogostreamStandard log (buffered error)

Stream Operators

OperatorNameUsage
<<InsertionSend data TO stream (output)
>>ExtractionGet data FROM stream (input)
cout << "Hello";      // Insert "Hello" into output stream
cin >> variable;      // Extract value from input stream

Standard Output with cout

Basic Output

#include <iostream>
using namespace std;

int main() {
    // Simple text output
    cout << "Hello, World!";

    // Output with newline
    cout << "First line" << endl;
    cout << "Second line\n";

    return 0;
}

Chaining Output

The << operator returns the stream, allowing chaining:

// All equivalent:
cout << "Name: " << "Alice" << ", Age: " << 25 << endl;

// Same as:
cout << "Name: ";
cout << "Alice";
cout << ", Age: ";
cout << 25;
cout << endl;

Output Different Types

int age = 25;
double price = 19.99;
char grade = 'A';
string name = "Bob";
bool active = true;

cout << "Age: " << age << endl;         // Integer
cout << "Price: $" << price << endl;    // Double
cout << "Grade: " << grade << endl;     // Character
cout << "Name: " << name << endl;       // String
cout << "Active: " << active << endl;   // Boolean (prints 1 or 0)

endl vs \n

MethodDescriptionWhen to Use
endlNewline + flush bufferInteractive output, before input
\nJust newlinePerformance-critical, bulk output
// endl flushes the buffer (ensures immediate display)
cout << "Enter name: " << flush;  // Just flush, no newline
cout << "Prompt: " << endl;       // Newline and flush

// \n is faster for bulk operations
for (int i = 0; i < 1000; i++) {
    cout << i << "\n";  // Faster than endl
}

Standard Input with cin

Basic Input

#include <iostream>
using namespace std;

int main() {
    int age;

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

    cout << "You are " << age << " years old." << endl;

    return 0;
}

Input Multiple Values

int a, b, c;

// Input on separate lines
cout << "Enter three numbers:\n";
cin >> a;
cin >> b;
cin >> c;

// Or chain them (can be space or newline separated)
cout << "Enter three numbers: ";
cin >> a >> b >> c;

Input Different Types

int age;
double salary;
char initial;
string firstName;  // Note: reads only until whitespace

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

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

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

cout << "Enter first name: ";
cin >> firstName;  // "John Smith" would only read "John"

How cin Works

Input buffer: "42 3.14 A\n"
              ▲

cin >> intVar;    // Reads 42, stops at space
              ▲

Input buffer: " 3.14 A\n"
               ▲

cin >> doubleVar; // Skips whitespace, reads 3.14
                  ▲

Input buffer: " A\n"
               ▲

cin >> charVar;   // Skips whitespace, reads 'A'
                 ▲

Key Points:

  • >> skips leading whitespace
  • Stops reading at whitespace (for strings) or invalid character
  • Leaves newline and remaining characters in buffer

Output Formatting

The iomanip Library

#include <iostream>
#include <iomanip>  // For setw, setprecision, etc.
using namespace std;

Field Width: setw

cout << setw(10) << 42 << endl;        // "        42"
cout << setw(10) << "Hello" << endl;   // "     Hello"

// setw only affects NEXT output
cout << setw(5) << 1 << setw(5) << 2 << setw(5) << 3 << endl;
// "    1    2    3"

Fill Character: setfill

cout << setfill('*') << setw(10) << 42 << endl;  // "********42"
cout << setfill('0') << setw(5) << 7 << endl;    // "00007"
cout << setfill('-') << setw(20) << "" << endl;  // "--------------------"

Alignment

cout << left << setw(10) << "Left" << "|" << endl;   // "Left      |"
cout << right << setw(10) << "Right" << "|" << endl; // "     Right|"
cout << internal << setw(10) << -42 << endl;         // "-       42"

Floating-Point Precision

double pi = 3.14159265358979;

// Default precision (6 significant digits)
cout << pi << endl;  // 3.14159

// Set precision
cout << setprecision(3) << pi << endl;   // 3.14
cout << setprecision(10) << pi << endl;  // 3.141592654

// Fixed notation (digits after decimal)
cout << fixed << setprecision(2) << pi << endl;  // 3.14

// Scientific notation
cout << scientific << setprecision(2) << pi << endl;  // 3.14e+00

Number Bases

int num = 255;

cout << "Decimal: " << dec << num << endl;  // 255
cout << "Hex: " << hex << num << endl;      // ff
cout << "Octal: " << oct << num << endl;    // 377

// Show base prefix
cout << showbase;
cout << "Hex: " << hex << num << endl;      // 0xff
cout << "Octal: " << oct << num << endl;    // 0377

// Uppercase hex
cout << uppercase << hex << num << endl;    // 0XFF

Boolean Output

bool flag = true;

cout << flag << endl;              // 1
cout << boolalpha << flag << endl; // true
cout << noboolalpha << flag << endl; // 1

Formatting Table

ManipulatorEffectSticky?
setw(n)Field widthNo (one-time)
setfill(c)Fill characterYes
setprecision(n)Decimal precisionYes
fixedFixed-point notationYes
scientificScientific notationYes
leftLeft alignYes
rightRight alignYes
hex/dec/octNumber baseYes
boolalphatrue/false for boolsYes
showbaseShow 0x, 0 prefixYes
showpointAlways show decimalYes

Input Handling and Validation

Check Input Success

int num;
cout << "Enter a number: ";

if (cin >> num) {
    cout << "You entered: " << num << endl;
} else {
    cout << "Invalid input!" << endl;
}

Input State Flags

cin.good()   // No errors
cin.eof()    // End of file reached
cin.fail()   // Logical error (wrong type)
cin.bad()    // Read/write error

Clearing Errors

int num;
cout << "Enter a number: ";
cin >> num;

if (cin.fail()) {
    cout << "Invalid input! Try again." << endl;

    cin.clear();  // Clear error flags
    cin.ignore(numeric_limits<streamsize>::max(), '\n');  // Clear buffer

    cout << "Enter a number: ";
    cin >> num;
}

Input Validation Loop

#include <limits>  // For numeric_limits

int getValidInteger() {
    int num;

    while (true) {
        cout << "Enter an integer: ";

        if (cin >> num) {
            // Clear any remaining input
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
            return num;
        }

        cout << "Invalid input! Please enter an integer." << endl;
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
}

Range Validation

int getNumberInRange(int min, int max) {
    int num;

    while (true) {
        cout << "Enter a number (" << min << "-" << max << "): ";

        if (cin >> num && num >= min && num <= max) {
            return num;
        }

        cout << "Invalid! Must be between " << min << " and " << max << endl;
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }
}

String Input with getline

The Problem with cin >> string

string fullName;
cout << "Enter your full name: ";
cin >> fullName;  // Only reads first word!

// Input: "John Smith"
// fullName = "John" (Smith left in buffer)

Solution: getline()

string fullName;
cout << "Enter your full name: ";
getline(cin, fullName);  // Reads entire line

// Input: "John Smith"
// fullName = "John Smith"

Mixing cin >> and getline()

int age;
string name;

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

cout << "Enter name: ";
getline(cin, name);  // PROBLEM: reads empty line!

The Issue:

Buffer after "cin >> age": "\n" (newline still there)
getline reads the newline immediately, gets empty string

Solution: Clear the newline first

int age;
string name;

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

cin.ignore();  // Ignore the newline

cout << "Enter name: ";
getline(cin, name);  // Now works correctly

getline with Delimiter

string data;

// Read until newline (default)
getline(cin, data);

// Read until comma
getline(cin, data, ',');

// Read until specific character
getline(cin, data, '#');

Error Streams

cerr - Unbuffered Error Output

cerr << "Error: File not found!" << endl;
  • Unbuffered: Output appears immediately
  • Use for: Error messages, crash diagnostics
  • Separate from cout (can redirect separately)

clog - Buffered Log Output

clog << "Debug: Processing started" << endl;
  • Buffered: More efficient for multiple messages
  • Use for: Logging, debug messages

Redirecting Streams

# In terminal:
./program > output.txt       # Redirect cout to file
./program 2> errors.txt      # Redirect cerr to file
./program > out.txt 2>&1     # Both to same file
./program 2>/dev/null        # Discard errors

Practical Usage

void processFile(const string& filename) {
    // Normal output to cout
    cout << "Processing: " << filename << endl;

    // Errors to cerr
    if (!fileExists(filename)) {
        cerr << "Error: Cannot find " << filename << endl;
        return;
    }

    // Debug info to clog
    clog << "Debug: File size = " << getFileSize(filename) << endl;
}

Buffer Management

What is Buffering?

Program Output:  "H" "e" "l" "l" "o"
       ↓   ↓   ↓   ↓   ↓
    ┌─────────────────────┐
    │  Output Buffer      │    Buffer collects data
    │  [H][e][l][l][o]    │
    └─────────────────────┘
              │
              │ Flush (when full, endl, or explicit)
              ▼
    ┌─────────────────────┐
    │     Screen          │    "Hello" appears
    └─────────────────────┘

When Buffer Flushes

  1. Buffer becomes full
  2. endl is used
  3. flush is called
  4. Program ends normally
  5. Input is requested (cin)

Explicit Flushing

cout << "Processing..." << flush;  // Flush without newline
doLongOperation();
cout << "Done!" << endl;

// Or use manipulator
cout << "Data" << flush;

Buffer States

// Tie cin to cout (default)
// Ensures cout is flushed before cin reads
cin.tie(&cout);  // Default behavior

// Untie for performance (be careful!)
cin.tie(nullptr);

// Sync with C stdio (default: synced)
ios_base::sync_with_stdio(true);  // Default

// Disable sync for performance
ios_base::sync_with_stdio(false);

Best Practices

1. Always Prompt Before Input

// Good
cout << "Enter your age: ";
cin >> age;

// Bad (user doesn't know what to enter)
cin >> age;

2. Validate All User Input

int age;
while (!(cin >> age) || age < 0 || age > 150) {
    cout << "Please enter a valid age (0-150): ";
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
}

3. Use getline for Strings with Spaces

string address;
cout << "Enter address: ";
getline(cin, address);  // Not: cin >> address

4. Clear Buffer When Mixing cin >> and getline

int num;
string line;

cin >> num;
cin.ignore();  // Clear the newline!
getline(cin, line);

5. Use Appropriate Precision for Money

double price = 19.99;
cout << fixed << setprecision(2) << "$" << price << endl;

6. Format Tables Consistently

cout << left;
cout << setw(20) << "Name" << setw(10) << "Age" << setw(15) << "City" << endl;
cout << setfill('-') << setw(45) << "" << setfill(' ') << endl;
cout << setw(20) << "Alice" << setw(10) << 25 << setw(15) << "New York" << endl;
cout << setw(20) << "Bob" << setw(10) << 30 << setw(15) << "Boston" << endl;

7. Use cerr for Errors

if (error_condition) {
    cerr << "Error: " << error_message << endl;
    return 1;
}

8. Consider Performance

// For competitive programming or bulk output:
ios_base::sync_with_stdio(false);
cin.tie(nullptr);

// Use '\n' instead of endl
cout << value << '\n';

Summary

TaskMethod
Output textcout << "text"
Output variablecout << variable
Newlineendl or "\n"
Input valuecin >> variable
Input linegetline(cin, string)
Format widthsetw(n)
Format precisionsetprecision(n)
Format fixedfixed
Validate inputif (cin >> var)
Clear errorcin.clear()
Clear buffercin.ignore(...)
Error outputcerr << "error"

Previous: Syntax and Structure | Next: Variables and Data Types

README - C++ Tutorial | DeepML