C++中string流知识详解和示例

一、概览与类体系

C++ 提供三种基于内存字符串的流,定义在 <sstream> 中:

  • std::istringstream:输入流,从已有字符串中读取并解析。
  • std::ostringstream:输出流,向内部缓冲区写入内容,最终取回为字符串。
  • std::stringstream :读写流,兼具 istringstreamostringstream 的功能。

它们都继承自 std::basic_iostream<char>,可使用所有流操作符与格式化工具。


二、常见用法

1. 构造与取出字符串

cpp 复制代码
std::ostringstream oss;             // 默认空缓冲
oss << "Value=" << 42 << ", Pi=" 
    << std::fixed << std::setprecision(3) << 3.14159;
// 获取结果
std::string s = oss.str();          // s == "Value=42, Pi=3.142"
  • str():获取当前缓冲区的字符串。
  • str(const std::string&):重置缓冲区内容。

2. 字符串解析

cpp 复制代码
std::string line = "123  45.6 OK";
// 将 line 内容作为流缓冲
std::istringstream iss(line);

int    a;
double b;
std::string status;

// 按空白自动切分并转换
if (iss >> a >> b >> status) {
    // a==123, b==45.6, status=="OK"
}

// 检查是否完全消费或错误
if (iss.fail() && !iss.eof()) {
    // 转换中发生格式错误
}
  • 运算符>> 会跳过空白,并尝试按目标类型解析。
  • 解析失败时,流会置 failbit,后续操作将不中断程序,除非打开异常模式。

3. 读写混合

cpp 复制代码
std::stringstream ss;
ss << "X=" << 10 << ";Y=" << 20;
// 重设读写位置到开头
ss.seekg(0);

// 逐字符读取、跳过标识
char    ch;
int     x, y;
ss >> ch >> ch >> x;   // 假设格式 "X=10"
ss >> ch >> ch >> y;   // 跳过 ";Y="
  • seekg /seekp 可重定位读/写指针,方便混合使用。
  • 在写完后若要读,通常要 ss.seekg(0);同理,由读转写可用 ss.seekp(0, std::ios::end)

三、格式控制与状态检查

  1. 格式化 :与标准流一致,可用 <iomanip> 中的操纵器,如 std::hexstd::setwstd::setfillstd::boolalphastd::fixedstd::scientific 等调整输出格式。

  2. 状态位 :用 good()fail()eof()bad()rdstate() 检测流状态;用 clear() 重置。

  3. 异常模式

    cpp 复制代码
    iss.exceptions(std::ios::failbit | std::ios::badbit);
    try {
      int v; 
      iss >> v;  // 解析失败即抛异常
    } catch (const std::ios_base::failure& e) {
      // 处理错误
    }

    默认不会抛。


四、性能与注意事项

  • 避免频繁 str() 调用 :每次 str() 都会拷贝缓冲区字符串,影响性能。可在最后一次取用时再调用。
  • 预分配缓冲 :可用 ss.str().reserve(n) 或先构造带初始字符串的 stringstream,减少动态分配。
  • 切换格式后状态保留 :如果你在一个流上设置了某个格式(如 std::hex),它会一直生效, remember to reset(std::dec)。
  • 注意空白和分隔>> 默认以空白分隔,解析整行或含空格的字段时要用 std::getline
  • 多语种/宽字符 :对于 Unicode 或宽字符流请使用 std::basic_stringstream<wchar_t>

五、综合示例

cpp 复制代码
#include <iostream>
#include <sstream>
#include <iomanip>

int main() {
    // 构建字符串
    std::ostringstream oss;
    oss << "Point(" 
        << std::setw(2) << std::setfill('0')
        << 7 << "," 
        << std::fixed << std::setprecision(1)
        << 3.14 << ")";
    std::string desc = oss.str();  // "Point(07,3.1)"
    std::cout << desc << "\n";

    // 解析回数值
    std::istringstream iss(desc);
    char ch;
    int ix;
    double dy;
    if ( (iss >> ch >> ch >> ix >> ch >> dy >> ch).good() ) {
        std::cout << "Parsed: x=" << ix << ", y=" << dy << "\n";
    } else {
        std::cerr << "Parse error\n";
    }

    // 读写混合:累加偏移
    std::stringstream ss("100 200 300");
    int sum = 0, v;
    while (ss >> v) sum += v;  // sum=600
    std::cout << "Sum=" << sum << "\n";

    return 0;
}

小结

  • std::ostringstream:安全构建复杂字符串/格式化输出。
  • std::istringstream:高效拆解、解析已知格式的文本。
  • std::stringstream:读写一体,用于需要往返操作的场景。
  • 始终关注流状态格式保留,并合理管理缓冲与性能。

掌握这些知识,你就能在日志构建、文本解析、动态内容生成等场景中,灵活高效地运用 C++ 的字符串流。

相关推荐
这是个栗子44 分钟前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
凤凰院凶涛QAQ1 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
研☆香1 小时前
为什么变量声明在赋值前也能使用?—— 深入理解 JavaScript 变量提升与作用域
开发语言·前端·javascript
右耳朵猫AI1 小时前
PHP周刊2026W28 | 安全更新、Laravel 13.18、Twig 3.28
开发语言·php·laravel
second601 小时前
第一部分:快速上手 —— 建立 C++ 基本语法与编程范式
开发语言·c++
郝学胜-神的一滴2 小时前
算法实战:最小k个数——大顶堆的优雅解法
开发语言·数据结构·c++·python·程序人生·算法·排序算法
bksczm2 小时前
linux之线程概念和控制
linux·开发语言·c++
JackieZhengChina2 小时前
零依赖轻量级JS悬浮提示插件title2tip-js的使用教程
开发语言·javascript·ecmascript
hehelm2 小时前
Linux网络编程—TCP字典翻译系统
linux·开发语言·网络·c++·tcp/ip
hansang_IR2 小时前
【记录】「SCOI2016」三道模拟赛/26.7.12
c++·算法