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++ 的字符串流。

相关推荐
划破黑暗的第一缕曙光11 分钟前
[C++]:2.类和对象(上)
c++·类和对象
季明洵13 分钟前
C语言实现单链表
c语言·开发语言·数据结构·算法·链表
墨雪不会编程20 分钟前
C++之【深入理解Vector】三部曲最终章
开发语言·c++
cpp_250123 分钟前
P9586 「MXOI Round 2」游戏
数据结构·c++·算法·题解·洛谷
浅念-27 分钟前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
kyle~29 分钟前
ROS2---QoS策略
c++·机器人·ros2
小宋102138 分钟前
Java 项目结构 vs Python 项目结构:如何快速搭一个可跑项目
java·开发语言·python
爱吃生蚝的于勒39 分钟前
【Linux】进程信号之捕捉(三)
linux·运维·服务器·c语言·数据结构·c++·学习
一晌小贪欢1 小时前
Python 爬虫进阶:如何利用反射机制破解常见反爬策略
开发语言·爬虫·python·python爬虫·数据爬虫·爬虫python
君生我老1 小时前
C++自写list类
c++