C++ I/O 流通俗指南

发布于:2025-04-03 ⋅ 阅读:(21) ⋅ 点赞:(0)

1. std::ostream 是什么?

  • 定义std::ostream 是 C++ 标准库中的输出流类,负责将数据输出到各种目标(如屏幕、文件、网络等)。
  • 你可以把 std::ostream 想象成一根“数据水管”
    • 数据从 C++ 代码流进 std::ostream(比如 std::cout)。
    • std::ostream 负责把数据送到 终端、文件或者其他地方
  • “o” 表示 “output”(输出)
  • 特点
    • 不能单独使用,必须依赖一个流缓冲区std::streambuf)。
    • 常见的实例:std::cout(输出到控制台)。

比喻std::ostream 就像一根“数据水管”,数据从程序流进去,最终送到屏幕或文件。

示例

std::cout << "Hello, World!" << std::endl;  // 输出到屏幕

2. 为什么不能直接创建 std::ostream

std::ostream os;  // ❌ 错误!没有默认构造函数
  • 原因std::ostream 需要一个 std::streambuf 来管理数据缓冲,但它本身不提供默认缓冲区。
  • 解决办法:用现有的流(如 std::cout)或手动关联缓冲区。

正确用法

std::filebuf buff;
buff.open("a.txt", std::ios::out);
std::ostream os(&buff);  // 关联文件缓冲区
os << "Hello, File!" << std::endl;

3. C++ 中的“流”是什么?

  • 流(Stream):数据的抽象化处理方式,像水流一样从一端流向另一端。
    • 输入流std::istream):外部(如键盘、文件) → 程序。
    • 输出流std::ostream):程序 → 外部(如屏幕、文件)。

4. I/O 流家族一览

C++ 的 I/O 流类分布在几个头文件中:

头文件 作用 继承关系
<iostream> std::istream 输入流(如 std::cin 继承 std::ios
std::ostream 输出流(如 std::cout 继承 std::ios
std::iostream 输入+输出流 继承 std::istreamstd::ostream
<fstream> std::ifstream 文件输入 继承 std::istream
std::ofstream 文件输出 继承 std::ostream
std::fstream 文件输入+输出 继承 std::iostream
<sstream> std::istringstream 从字符串解析数据 继承 std::istream
std::ostringstream 将数据写入字符串 继承 std::ostream
std::stringstream 字符串读+写 继承 std::iostream

5. 常见用法与代码示例

5.1 标准输入输出(<iostream>

  • std::cout 输出
std::cout << "Hello, World!" << std::endl;  // 输出到屏幕
  • std::cin 输入
int x;
std::cout << "请输入一个数字: ";
std::cin >> x;
std::cout << "你输入的是: " << x << std::endl;
  • 读取整行
std::string name;
std::cout << "请输入全名: ";
std::getline(std::cin, name);  // 支持空格
std::cout << "你好, " << name << "!" << std::endl;
  • 错误和日志
std::cerr << "错误: 文件未找到!" << std::endl;  // 无缓冲,立即输出
std::clog << "日志: 程序启动..." << std::endl;  // 有缓冲

代码示例:

#include <iostream>
#include <fstream>

int main() {
    std::filebuf buff;
    buff.open("a.txt", std::ios::out);
    std::ostream os(&buff);
    os << "aaa" << std::endl;
    os << "aaa" << std::endl;

    // 这里不需要显式关闭文件,析构时会自动关闭。
    // 但如果你希望在某个时刻显式关闭,可以调用 buff.close() 或 os.close()
    
    return 0;
}


#include <iostream>
#include <fstream>
int main()
{
    {
        std::filebuf buff;
        buff.open("a.txt", std::ios::in);
        std::iostream os(&buff);
        std::string line;
        std::getline(os, line);
        std::cout << line << std::endl;
    }
    {   
        std::filebuf buff;
        buff.open("b.txt", std::ios::out);
        std::iostream is(&buff);
        is << "xxx" << 1.2 << std::endl;
    }
    return 0;
}
  • 无需显式关闭std::ostreamstd::filebuf 会在对象析构时自动处理文件关闭。
  • 显式关闭:如果你想要在某个特定时刻手动关闭文件,可以调用 buff.close()os.close()

不过,在多数情况下,依赖于析构时自动关闭文件是一个更简单且推荐的做法。

5.2 文件输入输出(<fstream>

  • 写入文件
std::ofstream file("test.txt");
if (file.is_open()) {
    file << "Hello, 文件!" << std::endl;
    file.close();  // 可选,析构时自动关闭
}
  • 读取文件
std::ifstream file("test.txt");
if (file.is_open()) {
    std::string line;
    while (std::getline(file, line)) {
        std::cout << line << std::endl;
    }
    file.close();
}
  • 读写结合
std::filebuf buff;
buff.open("a.txt", std::ios::out);
std::ostream os(&buff);
os << "Hello" << std::endl;

5.3 字符串流(<sstream>

  • 字符串转数值
std::string str = "42";
int num;
std::istringstream iss(str);
iss >> num;  // 解析为 42
std::cout << num << std::endl;
  • 数值转字符串
int num = 100;
std::ostringstream oss;
oss << "数值: " << num;
std::cout << oss.str() << std::endl;  // "数值: 100"
  • 读写混合
std::stringstream ss;
ss << "Hello " << 42;
std::string word;
while (ss >> word) {
    std::cout << word << std::endl;  // 输出 "Hello" 和 "42"
}

5.4 格式化输出(<iomanip>

double num = 1234.56789;
std::cout << std::fixed << std::setprecision(2) << num << std::endl;  // 1234.57
std::cout << std::setw(10) << std::setfill('*') << 42 << std::endl;   // *******42

6. 关键点总结

  • std::ostream:输出流的核心,用于将数据送到外部,依赖 std::streambuf
  • 流类型
    • <iostream>:标准输入输出(cincoutcerr)。
    • <fstream>:文件操作(ifstreamofstreamfstream)。
    • <sstream>:字符串处理(istringstreamostringstreamstringstream)。
  • 格式化:用 <iomanip> 控制输出样式。
  • 自动管理:流对象析构时会自动关闭文件,无需手动清理(但可以显式关闭)。

💡 C++ 的 I/O 流就像“水管系统”,统一了各种数据处理方式,既灵活又强大!


网站公告

今日签到

点亮在社区的每一天
去签到