乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

字符串流

定义与作用

字符串流在内存中模拟 IO——将字符串当作"文件"进行输入输出操作,常用于格式化和解析。

std::ostringstream oss;
oss << "CPU: " << 62.5 << "%";      // 格式化拼接
std::string result = oss.str();     // "CPU: 62.5%"

std::istringstream iss("42 3.14 hello");
int a; double b; std::string c;
iss >> a >> b >> c;                 // 解析:42, 3.14, "hello"

核心原理

字符串流与 streambuf

完整示例

示例一:飞翔科技日志解析器

场景说明:李眉用 istringstream 解析飞翔科技服务器日志格式。

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

struct LogEntry {
    std::string timestamp;
    std::string level;
    std::string source;
    std::string message;
    double cpuUsage = 0;
};

LogEntry parseLog(const std::string& line) {
    LogEntry entry;
    std::istringstream iss(line);

    // 格式: "2026-06-14|WARN|web-01|CPU 62.5%|high load"
    std::getline(iss, entry.timestamp, '|');
    std::getline(iss, entry.level, '|');
    std::getline(iss, entry.source, '|');
    std::getline(iss, entry.message, '|');

    // 从 message 中提取数值
    std::istringstream msgStream(entry.message);
    std::string label;
    msgStream >> label >> entry.cpuUsage;  // "CPU 62.5%" → label="CPU", cpuUsage=62.5

    return entry;
}

int main() {
    std::vector<std::string> rawLogs = {
        "2026-06-14 09:00|INFO|web-01|CPU 12.5%|正常",
        "2026-06-14 09:05|WARN|db-02|CPU 62.5%|负载偏高",
        "2026-06-14 09:10|ERROR|cache-03|CPU 95.0%|即将过载",
        "2026-06-14 09:15|INFO|web-02|CPU 8.0%|正常",
        "2026-06-14 09:20|WARN|mq-01|CPU 78.0%|需关注",
    };

    std::cout << "=== 飞翔科技日志解析 ===\n\n";

    // 格式化表头
    std::ostringstream header;
    header << std::left
           << std::setw(22) << "时间"
           << std::setw(8)  << "级别"
           << std::setw(12) << "来源"
           << std::setw(10) << "CPU"
           << "状态";
    std::cout << header.str() << "\n";
    std::cout << std::string(60, '-') << "\n";

    // 解析并输出
    double totalCpu = 0;
    int warnCount = 0;
    for (const auto& raw : rawLogs) {
        auto entry = parseLog(raw);

        std::ostringstream row;
        row << std::left
            << std::setw(22) << entry.timestamp
            << std::setw(8)  << entry.level
            << std::setw(12) << entry.source
            << std::setw(10) << (std::to_string(entry.cpuUsage) + "%")
            << entry.message;
        std::cout << row.str() << "\n";

        totalCpu += entry.cpuUsage;
        if (entry.level == "WARN" || entry.level == "ERROR") ++warnCount;
    }

    std::cout << std::string(60, '-') << "\n";

    // 汇总行
    std::ostringstream summary;
    summary << "平均 CPU: " << std::fixed << std::setprecision(1)
            << (totalCpu / rawLogs.size()) << "%"
            << "  |  告警数: " << warnCount << "/" << rawLogs.size();
    std::cout << summary.str() << "\n";
}

预期输出:

=== 飞翔科技日志解析 ===

时间                  级别    来源        CPU       状态
------------------------------------------------------------
2026-06-14 09:00      INFO    web-01      12.500000% CPU 12.5%
2026-06-14 09:05      WARN    db-02       62.500000% CPU 62.5%
2026-06-14 09:10      ERROR   cache-03    95.000000% CPU 95.0%
2026-06-14 09:15      INFO    web-02      8.000000%  CPU 8.0%
2026-06-14 09:20      WARN    mq-01       78.000000% CPU 78.0%
------------------------------------------------------------
平均 CPU: 51.2%  |  告警数: 3/5

逐段分析:

  • istringstream 用分隔符 | 解析结构化日志
  • ostringstream 配合 iomanip(setw、left)实现表格对齐
  • str() 提取缓冲区中完整字符串
  • 嵌套 istringstream 提取数值:在已解析字段中再做二次解析

示例二:字符串流实现模板数据填充

场景说明:黄俪用字符串流为飞翔科技通知模板填充动态数据。

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

std::string fillTemplate(const std::string& tpl,
                         const std::map<std::string, std::string>& vars) {
    std::istringstream iss(tpl);
    std::ostringstream oss;
    std::string line;

    while (std::getline(iss, line)) {
        for (const auto& [key, val] : vars) {
            std::string placeholder = "{{" + key + "}}";
            size_t pos;
            while ((pos = line.find(placeholder)) != std::string::npos)
                line.replace(pos, placeholder.length(), val);
        }
        oss << line << "\n";
    }
    return oss.str();
}

int main() {
    std::string tpl = R"(
========================================
  飞翔科技系统通知
========================================

致 {{name}}({{dept}}部):

  您的 {{item}} 审核已通过。
  有效期至:{{expireDate}}
  经办人:{{operator}}

如有疑问,请联系技术部(分机 {{ext}})。

         飞翔科技运维中心
         2026-06-14
)";

    std::map<std::string, std::string> vars = {
        {"name",   "黄俪"},
        {"dept",   "技术"},
        {"item",   "生产环境部署权限"},
        {"expireDate", "2026-12-31"},
        {"operator",   "白歌"},
        {"ext",    "8080"},
    };

    std::string result = fillTemplate(tpl, vars);
    std::cout << result;
}

预期输出:

========================================
  飞翔科技系统通知
========================================

致 黄俪(技术部):

  您的 生产环境部署权限 审核已通过。
  有效期至:2026-12-31
  经办人:白歌

如有疑问,请联系技术部(分机 8080)。

         飞翔科技运维中心
         2026-06-14

逐段分析:

  • istringstream 逐行读取模板,保留换行结构
  • ostringstream 逐行写入替换后的结果
  • std::string::replace 原地替换占位符
  • 字符串流比多次字符串拼接(+)更高效,避免频繁内存分配

易错场景与面试考点

易错场景

1. 清空字符串流不当

std::ostringstream oss;
oss << "hello";
oss.str("");  // ✅ 清空内容
oss.clear();  // ✅ 清空状态位(通常也需要)

// ❌ 仅 oss.str("") 不清状态位,可能在错误后仍无法写入

2. 重复获取 str()

std::ostringstream oss;
oss << "abc";
auto s1 = oss.str();  // "abc"
// oss.str("");        // 清空后重新使用
oss << "def";
auto s2 = oss.str();  // "abcdef"(不是 "def"!需要先 str("") 清空)

3. istringstream EOF 后重用

std::istringstream iss("1 2 3");
int x;
while (iss >> x) { /* ... */ }
// iss 处于 eofbit 状态
// iss.str("4 5 6");  // 不会自动清除状态位!
iss.clear();           // ✅ 必须
iss.str("4 5 6");

面试考点

考点要点
三个字符串流istringstream(读), ostringstream(写), stringstream(读写)
str() 方法获取/设置内部缓冲
格式化拼接ostringstream + iomanip 比 std::to_string + 拼接更高效
数据解析istringstream + >> 或 getline 解析结构化字符串
与 sprintf 对比类型安全、不易缓冲区溢出、可处理 std::string
内部 streambuf字符串流使用 stringbuf,与文件流不同
重用注意改 str 后需 clear 清除 eof/fail 标志
上一页
文件流操作
下一页
std::regex 正则表达式