C++ cin cout input output - keyboard data streams flowing into holographic terminal screen

C++ Input & Output: Master cin, cout, Formatting & File I/O Basics

Back to C++ RoadmapC++ Programming Course • 65 Lessons

What Are Streams in C++?

In C++, input and output are handled through streams — abstract sequences of bytes that flow between your program and the outside world. Think of a stream as a pipe: data goes in one end and comes out the other. The <iostream> header gives you four predefined streams:

  • std::cout — Standard output (your terminal). The << operator sends data to it.
  • std::cin — Standard input (your keyboard). The >> operator reads data from it.
  • std::cerr — Standard error (unbuffered, for error messages).
  • std::clog — Standard log (buffered, for log messages).

The stream model is one of C++’s most powerful abstractions because the same << and >> operators work with files, strings, and network sockets — not just the terminal. You learn the operators once and use them everywhere.

Output with std::cout

#include <iostream>
#include <string>

int main() {
    // Basic output
    std::cout << "Hello, World!" << std::endl;

    // Chaining multiple values
    std::string name = "Chirag";
    int age = 25;
    double gpa = 3.85;

    std::cout << "Name: " << name << ", Age: " << age << ", GPA: " << gpa << "\n";

    // endl vs \n
    // std::endl flushes the buffer (slower)
    // "\n" just adds a newline (faster)
    // Use "\n" in most cases. Use endl only when you need guaranteed flush.

    std::cout << "Line 1\n";
    std::cout << "Line 2\n";
    std::cout << "Line 3" << std::endl;  // Flush here

    // Printing special characters
    std::cout << "Tab:\there\n";
    std::cout << "Quote: \"hello\"\n";
    std::cout << "Backslash: \\\n";
    std::cout << "Newline in string: first\nsecond\n";

    return 0;
}

The << operator is called the insertion operator. It is overloaded for all fundamental types — int, double, char, const char*, std::string, and more. You will learn how to overload it for your own types in the operator overloading lesson.

Input with std::cin

#include <iostream>
#include <string>

int main() {
    // Reading a single value
    int age;
    std::cout << "Enter your age: ";
    std::cin >> age;
    std::cout << "You are " << age << " years old.\n";

    // Reading multiple values on one line
    double width, height;
    std::cout << "Enter width and height: ";
    std::cin >> width >> height;
    std::cout << "Area: " << width * height << "\n";

    // Reading a single word (cin stops at whitespace)
    std::string word;
    std::cout << "Enter a word: ";
    std::cin >> word;
    std::cout << "You entered: " << word << "\n";
    // If you type "Hello World", only "Hello" is read!

    return 0;
}

The >> operator is called the extraction operator. It reads from the input stream, skipping leading whitespace, and stops at the next whitespace character. This means std::cin >> word reads one word, not a full line.

Reading Full Lines with std::getline

#include <iostream>
#include <string>

int main() {
    std::string fullName;
    std::string city;

    std::cout << "Enter your full name: ";
    std::getline(std::cin, fullName);

    std::cout << "Enter your city: ";
    std::getline(std::cin, city);

    std::cout << "Hello, " << fullName << " from " << city << "!\n";
    return 0;
}
// Sample run:
// Enter your full name: Chirag Khatri
// Enter your city: San Francisco
// Hello, Chirag Khatri from San Francisco!

std::getline(std::cin, variable) reads the entire line including spaces, up to the newline character. It discards the newline but does not skip leading whitespace like >> does.

The cin/getline Trap

This is the most common beginner bug in C++ I/O. When you mix cin >> and getline, the leftover newline from cin >> causes getline to read an empty string:

#include <iostream>
#include <string>

int main() {
    int age;
    std::string name;

    // BUG VERSION
    std::cout << "Enter age: ";
    std::cin >> age;              // Reads "25" but leaves "\n" in the buffer

    std::cout << "Enter name: ";
    std::getline(std::cin, name);  // Reads the leftover "\n" immediately!
    // name is now empty!

    std::cout << "Age: " << age << ", Name: '" << name << "'\n";
    // Output: Age: 25, Name: ''

    return 0;
}
#include <iostream>
#include <string>
#include <limits>

int main() {
    int age;
    std::string name;

    // FIX 1: Use cin.ignore() to discard the leftover newline
    std::cout << "Enter age: ";
    std::cin >> age;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

    std::cout << "Enter name: ";
    std::getline(std::cin, name);

    std::cout << "Age: " << age << ", Name: '" << name << "'\n";
    // Now works correctly!

    return 0;
}

// FIX 2: Use getline for everything and convert
// std::string ageStr;
// std::getline(std::cin, ageStr);
// int age = std::stoi(ageStr);

This trap catches every beginner. Memorize the fix: after every cin >> that precedes a getline, call cin.ignore().

Error Output — cerr and clog

#include <iostream>
#include <fstream>

int main() {
    // cerr — for error messages (unbuffered, writes immediately)
    std::cerr << "Error: file not found!\n";

    // clog — for log messages (buffered, more efficient)
    std::clog << "Log: application started\n";

    // Why separate streams? You can redirect them independently:
    // ./program > output.txt 2> errors.txt
    // stdout goes to output.txt, stderr goes to errors.txt

    std::cout << "This goes to stdout\n";
    std::cerr << "This goes to stderr\n";

    return 0;
}

Formatting Output — Manipulators

#include <iostream>
#include <iomanip>    // Required for most manipulators

int main() {
    double pi = 3.14159265358979;

    // Precision control
    std::cout << "Default:  " << pi << "\n";               // 3.14159
    std::cout << std::setprecision(3) << pi << "\n";       // 3.14
    std::cout << std::fixed << std::setprecision(2) << pi << "\n";  // 3.14
    std::cout << std::scientific << pi << "\n";            // 3.14e+00

    // Reset to default
    std::cout << std::defaultfloat;

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

    // Fill character
    std::cout << std::setfill('-') << std::setw(30) << "" << "\n";  // prints 30 dashes
    std::cout << std::setfill('0') << std::setw(5) << 42 << "\n";  // 00042
    std::cout << std::setfill(' ');  // Reset fill

    // Number bases
    int num = 255;
    std::cout << "Decimal: " << std::dec << num << "\n";     // 255
    std::cout << "Hex:     " << std::hex << num << "\n";     // ff
    std::cout << "Octal:   " << std::oct << num << "\n";     // 377
    std::cout << std::dec;  // Reset to decimal

    // Show base prefix
    std::cout << std::showbase;
    std::cout << "Hex: " << std::hex << num << "\n";  // 0xff
    std::cout << std::dec << std::noshowbase;

    // Boolean output
    bool flag = true;
    std::cout << "bool: " << flag << "\n";                    // 1
    std::cout << "bool: " << std::boolalpha << flag << "\n"; // true

    return 0;
}

printf-Style Output in C++

#include <cstdio>     // C-style printf
#include <iostream>

// C++20 introduced std::format (header <format>)
// C++23 introduced std::print (header <print>)

int main() {
    // Classic printf — still works in C++ and is sometimes more readable
    printf("Name: %s, Age: %d, GPA: %.2f\n", "Chirag", 25, 3.85);
    printf("Hex: 0x%X, Octal: %o\n", 255, 255);
    printf("Padded: %010d\n", 42);  // 0000000042

    // C++20 std::format (if your compiler supports it)
    // #include <format>
    // std::string s = std::format("Name: {}, Age: {}, GPA: {:.2f}", "Chirag", 25, 3.85);
    // std::cout << s << "\n";

    // C++23 std::print (if your compiler supports it)
    // #include <print>
    // std::print("Name: {}, Age: {}\n", "Chirag", 25);

    return 0;
}

Use cout with manipulators for type-safe output. Use printf when format strings are more readable (tables, aligned columns). In C++23, std::print gives you the best of both worlds.

String Streams — std::stringstream

#include <iostream>
#include <sstream>
#include <string>

int main() {
    // Building strings with stringstream
    std::ostringstream oss;
    oss << "Score: " << 95 << "/100 (" << 95.0 << "%)";
    std::string result = oss.str();
    std::cout << result << "\n";

    // Parsing strings with istringstream
    std::string data = "42 3.14 Hello";
    std::istringstream iss(data);
    int num;
    double pi;
    std::string word;
    iss >> num >> pi >> word;
    std::cout << "Parsed: " << num << ", " << pi << ", " << word << "\n";

    // Converting string to number
    std::string numStr = "12345";
    int value = std::stoi(numStr);      // string to int
    double dval = std::stod("3.14");    // string to double
    std::cout << value << " " << dval << "\n";

    // Converting number to string
    std::string s = std::to_string(42);
    std::cout << "As string: " << s << "\n";

    return 0;
}

Input Validation and Error Handling

#include <iostream>
#include <limits>

int main() {
    int number;

    while (true) {
        std::cout << "Enter a positive integer: ";

        if (std::cin >> number) {
            if (number > 0) {
                break;  // Valid input
            }
            std::cout << "Must be positive!\n";
        } else {
            // Input was not a valid integer
            std::cout << "Invalid input! Please enter a number.\n";
            std::cin.clear();  // Clear the error flag
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // Discard bad input
        }
    }

    std::cout << "You entered: " << number << "\n";
    return 0;
}
// Sample run:
// Enter a positive integer: abc
// Invalid input! Please enter a number.
// Enter a positive integer: -5
// Must be positive!
// Enter a positive integer: 42
// You entered: 42

When cin >> fails (e.g., you type letters when it expects a number), the stream enters a fail state. You must call cin.clear() to reset the error flag and cin.ignore() to discard the bad input before trying again.

Reading Multiple Values

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

int main() {
    // Reading comma-separated values
    std::string line;
    std::cout << "Enter numbers separated by commas: ";
    std::getline(std::cin, line);

    std::vector<int> numbers;
    std::istringstream iss(line);
    std::string token;

    while (std::getline(iss, token, ',')) {
        numbers.push_back(std::stoi(token));
    }

    std::cout << "You entered " << numbers.size() << " numbers: ";
    for (int n : numbers) {
        std::cout << n << " ";
    }
    std::cout << "\n";

    // Reading until EOF (useful for competitive programming)
    // int x;
    // while (std::cin >> x) {
    //     // Process x
    // }

    return 0;
}
// Sample run:
// Enter numbers separated by commas: 10,20,30,40
// You entered 4 numbers: 10 20 30 40

Practice Exercises

// Exercise 1: Create a receipt formatter
// Input: item name, quantity, price per item
// Output: formatted receipt with total, aligned columns

// Exercise 2: Build a number base converter
// Input: a decimal number
// Output: same number in binary, octal, and hexadecimal

// Exercise 3: Create a simple calculator
// Input: two numbers and an operator (+, -, *, /)
// Output: the result, formatted to 2 decimal places
// Handle division by zero!

// Exercise 4: Read a full paragraph (multiple lines) until the user types "END"
// Print the total word count and character count

// Exercise 5: Build a "Mad Libs" game
// Ask for: a noun, a verb, an adjective, a place
// Print a silly story using those words

Summary

C++ I/O is built on the stream abstraction. std::cout and << handle output. std::cin and >> handle input. std::getline reads full lines. Manipulators from <iomanip> control formatting — precision, width, fill, alignment, and number bases. std::stringstream lets you build and parse strings using the same stream operators. Always validate user input and watch out for the cin >> / getline trap.

In the next lesson, we cover operators and expressions — arithmetic, comparison, logical, bitwise, and the precedence rules that govern them all.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *