Skip to content

C++ 基本输入/输出

C++ 使用基于流(stream)的方法处理输入和输出。流是 I/O 设备(如键盘、屏幕、文件、网络连接)的抽象表示,被视为字节序列。本章涵盖使用标准流进行控制台 I/O 的基础知识。

输入操作涉及字节 从 输入设备(例如键盘)流向 内存。输出操作涉及字节 从 内存 流向 输出设备(例如显示屏)。

C++ 的 I/O 功能由多个头文件提供:

头文件 (Header File)功能和描述 (Function and Description)
<iostream>定义了核心标准 I/O 流对象:std::cin(标准输入)、std::cout(标准输出)、std::cerr(标准错误,无缓冲)和 std::clog(标准错误,缓冲)。
<iomanip>提供了用于格式化输出的流操纵符(stream manipulators)(例如,std::setw 设置字段宽度,std::setprecision 设置浮点精度,std::fixed,std::scientific)。
<fstream>声明了用于文件 I/O 的类:std::ifstream(文件输入)、std::ofstream(文件输出)、std::fstream(文件输入/输出)。
<sstream>声明了用于字符串 I/O 的类:std::istringstream(字符串输入)、std::ostringstream(字符串输出)、std::stringstream(字符串输入/输出)。对于解析和格式化字符串很有用。

std::cout 是 ostream 类的一个预定义对象,通常连接到控制台显示器。它与流插入运算符(<<)一起使用,将数据(变量、字面值、表达式结果)发送到标准输出。

#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. // std::endl 插入换行符 ('\n') 并刷新输出缓冲区。
// '\n' alone just inserts a newline and might be slightly more performant // 仅使用 '\n' 只插入换行符,如果不需要立即刷新,性能可能会略好。
// if immediate flushing isn't needed.
std::cout << "End of program.\n";
return 0;
}

输出:

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

<< 运算符可以链式使用,以便在单个语句中输出多个项。编译器会自动确定数据类型并使用正确的 << 重载。

std::cin 是 istream 类的一个预定义对象,通常连接到键盘。它与流提取运算符(>>)一起使用,从标准输入读取数据并将其存储到变量中。

#include <iostream>
#include <string>
#include <limits> // Required for std::numeric_limits // 用于 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::getline(std::cin, fullName);
std::cout << "Your full name is: " << fullName << std::endl;
return 0;
}

示例交互:

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

std::cin 的关键点:

  • >> 运算符通常会跳过前导空白字符(如空格、制表符)并在第一个尾随空白字符(空格、制表符、换行符)处停止读取。
  • 要读取整行内容(包括空格),请使用 std::getline(std::cin, your_string_variable);。
  • 如果用户输入了不兼容类型的数据(例如,在期望数字时输入文本),输入可能会失败。在输入操作后,始终检查 std::cin 的状态(例如,使用 std::cin.fail() 或在布尔上下文检查流,如 if (std::cin >> age)),并适当地处理错误。
  • 混合使用 >> 和 std::getline 需要小心,因为 >> 通常会在输入缓冲区中留下换行符(\n),紧随其后的 std::getline 会立即消耗掉它,导致意外的空输入。在 >> 之后调用 std::getline 之前,使用 std::cin.ignore() 丢弃剩余字符,特别是换行符。

std::cerr 是一个 ostream 对象,通常连接到控制台显示器,专门用于错误消息。它是无缓冲的(unbuffered),这意味着发送到 std::cerr 的输出会立即被刷新(显示)。这确保了即使程序随后崩溃,错误消息也能及时出现。

#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 // 使用 cerr 输出错误消息
std::cerr << "Error: Failed to open file '" << filename << "'" << std::endl;
return 1; // Indicate failure // 指示失败
}
// ... process file ... // ... 处理文件 ...
infile.close();
return 0;
}

输出(如果文件不存在):

Error: Failed to open file 'nonexistent_file.txt'

std::clog 是另一个 ostream 对象,也通常连接到控制台,用于记录信息。与 std::cerr 不同,std::clog 是缓冲的(buffered)。输出可能会被保存在缓冲区中,只有当缓冲区满、手动刷新或程序正常结束时才会被写入。这对于频繁的日志消息来说比无缓冲输出更高效。

#include <iostream>
int main() {
// Use clog for general logging or progress messages // 使用 clog 输出通用日志或进度消息
std::clog << "Log: Program starting initialization phase." << std::endl;
// ... some operations ... // ... 一些操作 ...
std::clog << "Log: Initialization complete." << std::endl;
return 0;
}

使用 std::cout 用于正常的程序输出,std::cerr 用于错误,std::clog 用于日志/状态消息。这种分离允许用户在需要时独立重定向这些流(例如,将错误重定向到单独的文件)。