Basic Input and Output
Variables and Data Types

1.2 Basic Input and Output

In the previous lessons, we used std::cout to print strings to the screen. Now, let's explore how to read values from the user using std::cin and examine performance hacks when printing to the console (because no one likes slow applications).

Reading Input with `std::cin`

Just as std::cout represents the standard output stream (the screen), std::cin represents the standard input stream (the keyboard).

To read input, we use std::cin along with the extraction operator >>. Think of the arrows as pointing to the right, showing that data flows from the keyboard into the variable.

#include <iostream>

int main() {
    std::cout << "Enter your age and height: ";
    
    int age{};
    double height{};
    
    // Read two variables sequentially from keyboard
    std::cin >> age >> height;
    
    std::cout << "You are " << age << " years old and " << height << "m tall.\n";
    return 0;
}
Reading integer and double inputs from the user.

When you run this program, it will pause and wait for the user to type. The extraction operator automatically splits inputs based on whitespace (spaces, tabs, or newlines). If the user types 24 1.82 and hits Enter, 24 is extracted into age and 1.82 is extracted into height.

Handling Stream Fail States (Input Corruption)

What happens if the program asks for an integer age, but the user types a word like 'twenty'? In JavaScript or Python, this might evaluate to NaN. In C++, it corrupts the input stream.

When extraction fails, std::cin enters a fail state (setting a flag inside the stream), ignores all future input requests (your program will bypass all subsequent cin calls entirely!), and leaves the target variable unmodified (or set to 0 in modern C++).

To build resilient code, we must explicitly detect and clear stream fail states:

#include <iostream>
#include <limits> // Required for std::numeric_limits

int main() {
    int age{};
    std::cout << "Enter your age: ";
    
    while (!(std::cin >> age)) { // If extraction returns false (failed)
        std::cout << "Invalid input! Please enter a number: ";
        std::cin.clear();  // Clear the fail state flags
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard corrupted buffer
    }
    
    std::cout << "Age registered: " << age << '\n';
    return 0;
}
Safe input recovery with cin.

The Performance Pitfall: `std::endl` vs `\n`

When writing loops or high frequency prints, using std::endl can make your program significantly slower. This is a very common performance mistake that makes senior engineers twitch.

To understand why, you must understand how operating systems write text. Accessing the physical console is slow. To speed things up, the OS stores characters in an internal memory buffer first, and prints them in batches.

As I mentioned earlier, std::endl does two things:

1. Inserts a newline character (\n) into the output stream.

2. Flushes the stream buffer (forces the OS to immediately write the buffer contents to the screen).

Flushing the buffer forces a slow system call. If you are printing 100,000 lines of data and use std::endl on each line, your CPU will spend most of its time waiting for the physical output to complete. It's like calling a delivery driver to deliver one french fry at a time.

Instead, if you use the character \n (or "\n"), C++ will buffer the output. The buffer will only flush when it fills up or when the program finishes, making execution drastically faster. It's like delivering the whole meal in one trip.

SLOW: Flushes the console buffer on every single iteration!
for (int i{0}; i < 100000; ++i) {
    std::cout << i << std::endl;
}

//  FAST: Buffers the output, flushing only when necessary.
for (int i{0}; i < 100000; ++i) {
    std::cout << i << '\n';
}
Fast printing vs slow printing in C++.

Competitive Programming Speed Hack

If you are ever writing code that processes millions of lines of input and output, the C++ standard library syncs itself with C's stdio library by default to allow mixing printf and cout. This synchronization adds overhead.

You can disable this synchronization at the top of your main function to make std::cin and std::cout just as fast as raw C functions:

int main() {
    // Turn off synchronization with C standard I/O library
    std::ios_base::sync_with_stdio(false);
    // Untie cin from cout (prevents automatic flushing before reading input)
    std::cin.tie(nullptr);

    // Your code here...
    return 0;
}
Optimizing I/O performance in main.

Only use this speed hack when you are sure you won't be mixing C style I/O functions (like printf and scanf) with C++ stream functions.

Finished reading this lesson?