Coming Soon

This lesson is currently being developed

Input and output (I/O) streams

Learn about Input and output (I/O) streams in C++.

Input and Output (I/O)
Chapter
Beginner
Difficulty
40min
Estimated Time

What to Expect

Comprehensive explanations with practical examples

Interactive coding exercises to practice concepts

Knowledge quiz to test your understanding

Step-by-step guidance for beginners

Development Status

In Progress

Content is being carefully crafted to provide the best learning experience

Preview

Early Preview Content

This content is still being developed and may change before publication.

28.1 — Input and output (I/O) streams

In this lesson, you'll learn about C++'s stream-based input/output system, which provides a unified way to handle data from various sources like the console, files, and strings.

What are I/O streams?

An I/O stream is an abstraction that represents a sequence of data that can be read from or written to. Think of streams like water pipes - data flows through them in one direction, and you can attach different sources (keyboard, file) or destinations (screen, file) to these pipes.

C++ uses streams for all input/output operations, making I/O consistent whether you're working with:

  • Console (keyboard/screen)
  • Files
  • Strings in memory
  • Network connections

The stream hierarchy

C++ provides several stream classes in the <iostream> header:

#include <iostream>
// This gives us access to:
// - std::cin   (input from console)
// - std::cout  (output to console)  
// - std::cerr  (error output to console)
// - std::clog  (logging output to console)

Key stream types

  1. Input streams (std::istream): Read data
  2. Output streams (std::ostream): Write data
  3. Input/output streams (std::iostream): Both read and write

Basic stream operations

Output with std::cout

You've already used std::cout many times:

#include <iostream>

int main()
{
    std::cout << "Hello, World!" << std::endl;
    
    int age = 25;
    std::cout << "I am " << age << " years old." << std::endl;
    
    // Chaining multiple outputs
    std::cout << "Values: " << 10 << ", " << 3.14 << ", " << 'A' << std::endl;
    
    return 0;
}

Output:

Hello, World!
I am 25 years old.
Values: 10, 3.14, A

Input with std::cin

Reading data from the console:

#include <iostream>
#include <string>

int main()
{
    std::string name;
    int age;
    
    std::cout << "Enter your name: ";
    std::cin >> name;
    
    std::cout << "Enter your age: ";
    std::cin >> age;
    
    std::cout << "Hello " << name << ", you are " << age << " years old." << std::endl;
    
    return 0;
}

Sample run:

Enter your name: Alice
Enter your age: 30
Hello Alice, you are 30 years old.

Understanding stream operators

Insertion operator (<<)

The << operator "inserts" data into an output stream:

std::cout << "Data flows into cout" << std::endl;
//        ^^
//    insertion operator

Extraction operator (>>)

The >> operator "extracts" data from an input stream:

int number;
std::cin >> number;  // Extract integer from cin into number
//       ^^
//   extraction operator

Stream manipulation and formatting

Basic formatting with std::cout

#include <iostream>
#include <iomanip>  // For stream manipulators

int main()
{
    double pi = 3.14159265359;
    
    // Default output
    std::cout << "Default: " << pi << std::endl;
    
    // Set precision
    std::cout << std::fixed << std::setprecision(2);
    std::cout << "2 decimal places: " << pi << std::endl;
    
    std::cout << std::setprecision(4);
    std::cout << "4 decimal places: " << pi << std::endl;
    
    // Set width and alignment
    std::cout << std::setw(10) << "Right" << std::endl;
    std::cout << std::left << std::setw(10) << "Left" << std::endl;
    
    return 0;
}

Output:

Default: 3.14159
2 decimal places: 3.14
4 decimal places: 3.1416
     Right
Left      

Number base formatting

#include <iostream>

int main()
{
    int number = 255;
    
    std::cout << "Decimal: " << std::dec << number << std::endl;
    std::cout << "Hexadecimal: " << std::hex << number << std::endl;
    std::cout << "Octal: " << std::oct << number << std::endl;
    
    // Show base prefixes
    std::cout << std::showbase;
    std::cout << "With prefixes:" << std::endl;
    std::cout << "Decimal: " << std::dec << number << std::endl;
    std::cout << "Hexadecimal: " << std::hex << number << std::endl;
    std::cout << "Octal: " << std::oct << number << std::endl;
    
    return 0;
}

Output:

Decimal: 255
Hexadecimal: ff
Octal: 377
With prefixes:
Decimal: 255
Hexadecimal: 0xff
Octal: 0377

Error streams: std::cerr and std::clog

std::cerr for error messages

#include <iostream>

int main()
{
    int divisor = 0;
    
    if (divisor == 0)
    {
        std::cerr << "Error: Division by zero!" << std::endl;
        return 1;  // Return error code
    }
    
    std::cout << "Result: " << 10 / divisor << std::endl;
    return 0;
}

std::clog for logging

#include <iostream>

int main()
{
    std::clog << "Program started" << std::endl;
    
    // Main program logic here
    std::cout << "Hello, World!" << std::endl;
    
    std::clog << "Program completed successfully" << std::endl;
    return 0;
}

Stream chaining and the return value

Stream operations return a reference to the stream, enabling chaining:

#include <iostream>

int main()
{
    // These are equivalent:
    std::cout << "Hello, ";
    std::cout << "World!";
    std::cout << std::endl;
    
    // Chained version:
    std::cout << "Hello, " << "World!" << std::endl;
    
    // Reading multiple values:
    int a, b, c;
    std::cout << "Enter three numbers: ";
    std::cin >> a >> b >> c;  // Chained input
    std::cout << "You entered: " << a << ", " << b << ", " << c << std::endl;
    
    return 0;
}

Sample run:

Hello, World!
Hello, World!
Enter three numbers: 1 2 3
You entered: 1, 2, 3

Working with different data types

Streams automatically handle different data types:

#include <iostream>
#include <string>

int main()
{
    // Output different types
    int intValue = 42;
    double doubleValue = 3.14159;
    char charValue = 'A';
    std::string stringValue = "Hello";
    bool boolValue = true;
    
    std::cout << "Integer: " << intValue << std::endl;
    std::cout << "Double: " << doubleValue << std::endl;
    std::cout << "Character: " << charValue << std::endl;
    std::cout << "String: " << stringValue << std::endl;
    std::cout << "Boolean: " << boolValue << std::endl;
    
    // Show boolean values as words instead of 0/1
    std::cout << std::boolalpha;
    std::cout << "Boolean (text): " << boolValue << std::endl;
    
    return 0;
}

Output:

Integer: 42
Double: 3.14159
Character: A
String: Hello
Boolean: 1
Boolean (text): true

Stream state and error handling

Streams maintain state flags that indicate their current condition:

#include <iostream>

int main()
{
    int number;
    
    std::cout << "Enter a number: ";
    std::cin >> number;
    
    if (std::cin.good())
    {
        std::cout << "Successfully read: " << number << std::endl;
    }
    else
    {
        std::cerr << "Error: Invalid input!" << std::endl;
        
        // Clear error flags and ignore bad input
        std::cin.clear();
        std::cin.ignore(10000, '\n');
    }
    
    return 0;
}

Sample run with valid input:

Enter a number: 42
Successfully read: 42

Sample run with invalid input:

Enter a number: abc
Error: Invalid input!

Common stream methods

#include <iostream>
#include <string>

int main()
{
    // Check stream state
    if (std::cin.good())    std::cout << "Stream is good" << std::endl;
    if (std::cin.eof())     std::cout << "End of file reached" << std::endl;
    if (std::cin.fail())    std::cout << "Last operation failed" << std::endl;
    if (std::cin.bad())     std::cout << "Stream is corrupted" << std::endl;
    
    // Get single character
    char ch;
    std::cout << "Enter a character: ";
    ch = std::cin.get();    // Get single character including whitespace
    std::cout << "You entered: '" << ch << "'" << std::endl;
    
    // Read entire line
    std::string line;
    std::cout << "Enter a line: ";
    std::cin.ignore();      // Clear newline from previous input
    std::getline(std::cin, line);
    std::cout << "You entered: " << line << std::endl;
    
    return 0;
}

Best practices for stream I/O

1. Always validate input

#include <iostream>

int getInteger()
{
    int value;
    while (!(std::cin >> value))
    {
        std::cout << "Invalid input. Please enter a number: ";
        std::cin.clear();
        std::cin.ignore(10000, '\n');
    }
    return value;
}

2. Use appropriate streams for different purposes

std::cout << "Normal output" << std::endl;     // Regular output
std::cerr << "Error message" << std::endl;     // Error messages  
std::clog << "Debug info" << std::endl;        // Logging/debugging

3. Flush streams when needed

std::cout << "Processing..." << std::flush;    // Force immediate output
// or
std::cout << "Processing..." << std::endl;     // Output with newline and flush

Summary

C++ streams provide a unified, type-safe way to handle input and output. The stream operators (<< and >>) work with all built-in types and can be overloaded for custom types. Streams maintain state flags for error handling and provide various formatting options. Understanding streams is fundamental to effective C++ I/O programming.

Quiz

  1. What's the difference between std::cout, std::cerr, and std::clog?
  2. Why do stream operations return a reference to the stream?
  3. What happens when you try to read an integer but the user enters text?
  4. How can you read a line containing spaces from the console?
  5. What's the purpose of stream manipulators like std::setprecision?

Practice exercises

  1. Write a program that reads a student's name and three test scores, then displays them in a formatted table.

  2. Create a program that safely reads integers from the user, handling invalid input gracefully.

  3. Write a function that formats and displays a floating-point number with exactly 2 decimal places, right-aligned in a field of width 10.

  4. Create a program that demonstrates the difference between >> and getline() when reading strings with spaces.

Continue Learning

Explore other available lessons while this one is being prepared.

View Course

Explore More Courses

Discover other available courses while this lesson is being prepared.

Browse Courses

Lesson Discussion

Share your thoughts and questions

💬

No comments yet. Be the first to share your thoughts!

Sign in to join the discussion