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

如何不使用stringstream实现字符串去空格横杠后每3字符插入空格?

替代stringstream实现字符串格式化需求

我编写了一个函数,用于去除字符串中的空格和横杠,随后在每第3个字符后插入一个空格。请问有没有不使用stringstream的其他实现方法?

原代码片段如下:

#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
string FormatString(string S) {
    /*统计空格和横杠*/
    auto newEnd = remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
    S.erase(newEnd, S.end());
    // 后续原本打算用stringstream处理空格插入
}

当然有啦!其实不用stringstream的话,有好几种直观又高效的实现方式,我给你整理了三种常用的方法,你可以根据需求选择:

方法一:手动遍历构建新字符串

这种方法最直接,完全不需要额外的库(除了基础的string),逻辑清晰易懂,新手也能快速上手:

  1. 先遍历原字符串,过滤掉空格和横杠,得到一个“干净”的字符串
  2. 再遍历这个干净的字符串,每数到第3个字符就插入一个空格(注意最后不要多插空格)

代码示例:

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

string FormatString(string S) {
    // 第一步:过滤掉空格和横杠
    string cleaned;
    for (char c : S) {
        if (c != ' ' && c != '-') {
            cleaned += c;
        }
    }

    // 第二步:每3个字符插入一个空格
    string result;
    int charCount = 0;
    for (char c : cleaned) {
        result += c;
        charCount++;
        // 不是最后一个字符,且刚好是第3个的倍数时插入空格
        if (charCount % 3 == 0 && charCount != cleaned.size()) {
            result += ' ';
        }
    }

    return result;
}

// 测试一下
int main() {
    string test = "123-45 678-901";
    cout << FormatString(test) << endl; // 输出:123 456 789 01
    return 0;
}

这种方法全程手动控制,没有依赖任何流类,时间复杂度是O(n)(两次线性遍历),效率很不错,维护起来也简单。

方法二:原地修改字符串(节省内存)

如果你的字符串特别长,不想额外创建中间字符串,可以试试原地修改的方式——先原地过滤掉无效字符,再从后往前插入空格(避免覆盖还没处理的字符):

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

string FormatString(string S) {
    // 第一步:原地过滤空格和横杠
    int writePos = 0;
    for (char c : S) {
        if (c != ' ' && c != '-') {
            S[writePos++] = c;
        }
    }
    S.resize(writePos); // 截断到有效字符的长度

    // 第二步:原地插入空格,先算好需要插多少个
    int spaceCount = (S.size() - 1) / 3;
    S.resize(S.size() + spaceCount); // 先预留足够的空间

    int readPos = S.size() - spaceCount - 1; // 原有效字符串的最后一个字符位置
    int finalWritePos = S.size() - 1;

    // 从后往前拷贝,同时插入空格
    while (readPos >= 0) {
        S[finalWritePos--] = S[readPos--];
        // 每4个位置(3个字符+1个空格)插一次,注意不要在开头插
        if ((S.size() - finalWritePos - 1) % 4 == 0 && finalWritePos >= 0) {
            S[finalWritePos--] = ' ';
        }
    }

    return S;
}

// 测试示例
int main() {
    string test = "12-345 6789";
    cout << FormatString(test) << endl; // 输出:123 456 789
    return 0;
}

这种方法的优势是减少了一次字符串内存分配,适合处理超大字符串,缺点是逻辑稍微绕一点,需要仔细处理索引。

方法三:结合STL算法(延续你原代码的风格)

你原来的代码已经用了remove_if来过滤字符,那可以直接在这个基础上用STL的insert方法插入空格,完全不用stringstream:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

string FormatString(string S) {
    // 第一步:和你原代码一样,过滤空格和横杠
    auto newEnd = remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
    S.erase(newEnd, S.end());

    // 第二步:每3个字符后插入空格,注意步长是4(3个字符+1个空格)
    for (int i = 3; i < S.size(); i += 4) {
        S.insert(i, " ");
    }

    return S;
}

// 测试一下
int main() {
    string test = "a b-cd-efg hi";
    cout << FormatString(test) << endl; // 输出:abc def ghi
    return 0;
}

这种方法代码简洁,和你原代码的风格保持一致,适合短字符串场景;不过因为每次insert可能会触发内存重新分配和拷贝,超长字符串的效率会稍低一点,但日常使用完全没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:37:34