You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么使用std::stringstream遍历std::string时末尾会出现异常字符?

问题原因

这个乱码和编码没有任何关系,是std::stringstream的读取逻辑错误导致的。

具体出错点:

  1. 你使用的while (s_fmt.good())判断逻辑存在漏洞:good()仅能代表上一次流操作没有发生错误,不能保证下一次get()操作能读取到有效字符。当流已经走到末尾时,good()仍然会返回true,进入循环后调用get()会返回EOF(通常值为-1),你将它强制转换为char类型就会生成一个不可打印的乱码字符,这就是末尾多余字符的来源。
  2. 你写的if (c == '\0') break判断完全没有作用:std::string存储字符串时不会把末尾终止符\0计入有效长度,std::stringstream初始化时也不会将\0放入流缓冲区,你永远读不到\0,这条语句可以直接删除。
  3. 额外隐患:当前逻辑如果遇到%后接未定义的格式符,会直接吞掉后面的字符且没有任何输出,你可以根据需求补充default分支处理这种情况。

修复方案

将循环逻辑修改为读取后先判断是否为EOF,再进行后续处理即可,修复后的完整代码如下:

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

int main() {
    std::string fmt = "[%t]%Y-%M-%D<%H:%m:%s>:c";
    std::stringstream s_res;
    std::stringstream s_fmt(fmt);
    int ch;
    // 先读取再判断是否为EOF,避免读取无效字符
    while ((ch = s_fmt.get()) != EOF) {
        char c = (char)ch;
        if (c == '%') {
            int next_ch = s_fmt.peek();
            if (next_ch == EOF) {
                // 处理%在末尾的边界情况
                s_res << c;
                break;
            }
            switch (next_ch) {
                case 't':
                    s_res << "Type";
                    break;
                case 'Y':
                    s_res << "Year";
                    break;
                case 'M':
                    s_res << "Month";
                    break;
                case 'D':
                    s_res << "Day";
                    break;
                case 'H':
                    s_res << "Hour";
                    break;
                case 'm':
                    s_res << "min";
                    break;
                case 's':
                    s_res << "sec";
                    break;
                case 'c':
                    s_res << "content";
                    break;
                default:
                    // 未定义的格式符,原样输出%和后面的字符
                    s_res << c << (char)next_ch;
                    break;
            }
            s_fmt.get();
            continue;
        }
        s_res << c;
    }
    std::cout << s_res.str();
    return 0;
}

运行修复后的代码就能得到预期输出:[Type]Year-Month-Day<Hour:min:sec>:content

内容的提问来源于stack exchange,提问作者MuxAte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 06:36:03