如何不使用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),逻辑清晰易懂,新手也能快速上手:
- 先遍历原字符串,过滤掉空格和横杠,得到一个“干净”的字符串
- 再遍历这个干净的字符串,每数到第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
相关产品推荐
相关产品推荐

