Skip to content

C++ Basic Input/Output

C++ handles input and output using a stream-based approach. Streams are abstract representations of I/O devices (like the keyboard, screen, files, network connections) treated as sequences of bytes. This chapter covers the fundamentals of console I/O using the standard streams.

Input operations involve bytes flowing from an input device (e.g., keyboard) into memory. Output operations involve bytes flowing from memory to an output device (e.g., display screen).

Several header files provide C++‘s I/O capabilities:

Header FileFunction and Description
<iostream>Defines the core standard I/O stream objects: std::cin (standard input), std::cout (standard output), std::cerr (standard error, unbuffered), and std::clog (standard error, buffered).
<iomanip>Provides stream manipulators for formatting output (e.g., std::setw to set field width, std::setprecision for floating-point precision, std::fixed, std::scientific).
<fstream>Declares classes for file-based I/O: std::ifstream (input from files), std::ofstream (output to files), std::fstream (input/output on files).
<sstream>Declares classes for string-based I/O: std::istringstream (input from strings), std::ostringstream (output to strings), std::stringstream (input/output on strings). Useful for parsing and formatting strings.

std::cout is a predefined object of the ostream class, typically connected to the console display. It’s used with the stream insertion operator (<<) to send data (variables, literals, expression results) to the standard output.

#include <iostream> // Required for std::cout, std::endl
#include <string> // Recommended for using std::string
int main() {
std::string message = "Hello C++ Modern I/O!";
int year = 2023;
// The << operator is overloaded for various data types.
std::cout << "Message: " << message << std::endl;
std::cout << "Year: " << year << std::endl;
std::cout << "Next year: " << year + 1 << std::endl;
// std::endl inserts a newline character ('\n') and flushes the output buffer.
// '\n' alone just inserts a newline and might be slightly more performant
// if immediate flushing isn't needed.
std::cout << "End of program.\n";
return 0;
}

Output:

Message: Hello C++ Modern I/O!
Year: 2023
Next year: 2024
End of program.

The << operator can be chained to output multiple items in a single statement. The compiler automatically determines the data type and uses the correct overload of <<.

std::cin is a predefined object of the istream class, typically connected to the keyboard. It’s used with the stream extraction operator (>>) to read data from standard input and store it in variables.

#include <iostream>
#include <string>
#include <limits> // Required for std::numeric_limits
int main() {
std::string name;
int age;
std::cout << "Please enter your first name: ";
std::cin >> name; // Reads input until whitespace is encountered
std::cout << "Please enter your age: ";
std::cin >> age;
// Check if input failed (e.g., user entered text for age)
if (std::cin.fail()) {
std::cerr << "Error: Invalid input for age.\n";
// Clear the error state
std::cin.clear();
// Ignore the rest of the invalid input line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 1; // Indicate error
}
std::cout << "Hello, " << name << "! You are " << age << " years old." << std::endl;
// Consume the leftover newline character from the previous input
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::string fullName;
std::cout << "Please enter your full name: ";
// Use std::getline to read the entire line, including spaces
std::getline(std::cin, fullName);
std::cout << "Your full name is: " << fullName << std::endl;
return 0;
}

Sample Interaction:

Please enter your first name: Alice
Please enter your age: 30
Hello, Alice! You are 30 years old.
Please enter your full name: Alice Wonderland
Your full name is: Alice Wonderland

Key points about std::cin:

  • The >> operator typically skips leading whitespace and stops reading at the first trailing whitespace (space, tab, newline).
  • To read entire lines, including spaces, use std::getline(std::cin, your_string_variable);.
  • Input can fail if the user enters data of an incompatible type (e.g., text when expecting a number). Always check the state of std::cin (e.g., using std::cin.fail() or checking the stream in a boolean context like if (std::cin >> age) ) after input operations and handle errors appropriately.
  • Mixing >> and std::getline requires care, as >> often leaves the newline character (\n) in the input buffer, which can be immediately consumed by a subsequent std::getline, leading to unexpected empty input. Use std::cin.ignore() to discard leftover characters, especially the newline, before calling std::getline after >>.

std::cerr is an ostream object typically connected to the console display, intended specifically for error messages. It is unbuffered, meaning output sent to std::cerr is flushed (displayed) immediately. This ensures error messages appear promptly, even if the program crashes afterwards.

#include <iostream>
#include <fstream>
#include <string>
int main() {
std::string filename = "nonexistent_file.txt";
std::ifstream infile(filename);
if (!infile.is_open()) {
// Use cerr for error messages
std::cerr << "Error: Failed to open file '" << filename << "'" << std::endl;
return 1; // Indicate failure
}
// ... process file ...
infile.close();
return 0;
}

Output (if file doesn’t exist):

Error: Failed to open file 'nonexistent_file.txt'

std::clog is another ostream object, also typically connected to the console, intended for logging information. Unlike std::cerr, std::clog is buffered. Output might be held in a buffer and written only when the buffer is full, flushed manually, or when the program ends normally. This can be more efficient for frequent logging messages than unbuffered output.

#include <iostream>
int main() {
// Use clog for general logging or progress messages
std::clog << "Log: Program starting initialization phase." << std::endl;
// ... some operations ...
std::clog << "Log: Initialization complete." << std::endl;
return 0;
}

Use std::cout for normal program output, std::cerr for errors, and std::clog for logging/status messages. This separation allows users to redirect these streams independently if needed (e.g., redirect errors to a separate file).