火龙信奥
  • 首页
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

C++ 字符串流 stringstream 实战教程

作者: 作者的头像   刘杰 , 时间:2026-03-21 15:28:33 , 所有人可见, 阅读  29

信奥必备:字符串流 stringstream 实战教程

在信息学奥林匹克竞赛(CSP-J/S、NOIP)中,字符串处理类题目是入门级高频考点,手写字符串类型转换不仅耗时,还可能因边界条件(如负数、多分隔符、不规则空格)出错。stringstream 是 C++ <sstream> 库的“轻量化神器”——它把字符串封装成“内存流”,让你像操作 cin/cout 一样处理字符串,能大幅简化代码、降低出错率,是信奥生必须掌握的基础工具。

前置知识(必记)

  1. 头文件:#include <sstream> 已包含在万能头 #include <bits/stdc++.h> 中。
  2. 核心操作:
  3. <<:向流中写入数据(赋值/拼接);
  4. >>:从流中读取数据(按类型解析,自动忽略空格/制表符);
  5. str():获取流中完整字符串;str(""):清空流的内容;
  6. 复用规则:多次使用同一个 stringstream 时,必须先 clear()(重置流状态,如结束符/错误标记),再 str("")(清空内容),否则会读取失败。

场景1:[字符串 ↔ 数值]快速转换(替代手写/atoi)

适用情况

题目需要将字符串形式的数字(含负数、小数)转成 int/double,或把数值转成字符串;尤其适合处理“不确定位数的数字”和“带符号的数字”,避免手写遍历字符计算的麻烦。

适用题目(CSP-J 2020 模拟题)

题目描述:
输入一个仅包含整数的字符串(整数之间用单个空格分隔,可能有负数),求这些整数的和。
输入示例:"12 -3 45 0 -9"
输出示例:45

解题思路:
用 stringstream 读取整个字符串,通过 >> 逐个解析成 int,累加即可。相比手写转换(逐字符判断正负、计算位数),stringstream 能直接处理负数,且代码简单。

核心代码:

#include <bits/stdc++.h>
using namespace std;

int main() {
    string s;
    getline(cin, s);  // 读取整行输入(含空格)
    stringstream ss(s);  // 初始化流,传入待处理字符串
    int num, sum = 0;

    // 逐个读取整数(自动忽略空格,直到流结束)
    while (ss >> num) {
        sum += num;
    }

    cout << sum << endl;  // 输出:45
    return 0;
}

竞赛小贴士

  • atoi() 仅支持正/负整数,且无法处理格式错误;stringstream 支持 int/double,且解析失败时仅会终止读取,不会直接崩溃;
  • 数值转字符串:ss << 123; string res = ss.str(); 即可,比 to_string() 更灵活(支持多类型拼接)。

场景2:按自定义分隔符拆分字符串(替代手写split)

适用情况

输入字符串用非空格分隔符(如逗号、竖线、分号)分割子串,需要拆分出所有子串;替代手写 split 函数(遍历字符+判断分隔符),避免漏处理“首尾分隔符”“连续分隔符”等边界。

适用题目(NOIP 2018 普及组改编)

题目描述:
输入一行字符串,单词之间用逗号分隔(可能有首尾空格、逗号前后空格),统计不同单词的数量(忽略单词前后空格)。
输入示例:" apple,banana,apple,orange ,pear"
输出示例:4

解题思路:
1. 先用 stringstream 读取整行,自动忽略首尾空格;
2. 用 getline(ss, temp, ',') 按逗号拆分,拆分后再用 stringstream 去除每个单词的前后空格;
3. 存入 set 自动去重,最终 set 的大小即为答案。

核心代码:

#include <iostream>
#include <sstream>
#include <string>
#include <set>
using namespace std;

// 去除字符串首尾空格(竞赛常用工具函数)
string trim(const string& s) {
    stringstream ss(s);
    string res;
    ss >> res;  // >> 自动忽略首尾空格
    return res;
}

int main() {
    string s;
    getline(cin, s);
    stringstream ss(s);
    string temp;
    set<string> words;  // 自动去重

    // 按逗号拆分字符串
    while (getline(ss, temp, ',')) {
        string word = trim(temp);  // 去除单词前后空格
        if (!word.empty()) {  // 避免空字符串(如连续逗号)
            words.insert(word);
        }
    }

    cout << words.size() << endl;  // 输出:4
    return 0;
}

竞赛小贴士

  • getline(ss, temp, 分隔符) 是拆分核心,分隔符只能是单个字符(如 , / |);
  • 若遇到多字符分隔符(如 ||),需先替换成单字符,再用 getline 拆分。

总结(信奥必记)

  1. 核心适用场景:数值与字符串互转、自定义分隔符拆分、格式化拼接、不规则空格输入处理;
  2. 避坑关键:复用 stringstream 时,必须先 clear()(重置状态)再 str("")(清空内容);

掌握 stringstream 后,信奥中棘手的字符串处理问题都能快速解决,建议结合上述案例综合记忆!

—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

©2026加盟我们 | 关于我们 | ACM课程 | 常见问题 | 成果墙 | 评测记录 | 浙ICP备2021013995号
在线画图 | OI WIki | 打字练习
火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码