C++移除字符串多余空格代码 为何未删除单词间单个空格
C++移除字符串多余空格代码逻辑解析
对应实现代码
#include <iostream> #include <string> void RemoveExcessSpaces(std::string &s) { for (int i = 0; i < s.length(); i++) { while (s[i] == ' ')s.erase(s.begin() + i); while (s[i] != ' ' && i < s.length())i++; } if (s[s.length() - 1] == ' ')s.pop_back(); } int main() { std::string s(" this is string "); RemoveExcessSpaces(s); std::cout << "\"" << s << "\""; return 0; }
逻辑解释
你觉得while (s[i] == ' ')s.erase(s.begin() + i);会删掉所有空格,是没捋顺两段while和外层for循环的i自增的配合规则——单词之间的单个空格从头到尾都没被这句删空格的代码碰到,自然会保留下来。
先明确外层for循环的固定执行顺序:每轮循环先跑完大括号里的两段while逻辑,跑完之后才会自动执行一次i++,再判断i是否越界、决定要不要进入下一轮。
- 第一段删空格的while,只有刚进入本轮循环时,i指向的位置是空格才会触发删除。
- 第二段while的作用很简单:从当前i位置开始,只要指的不是空格、也没到字符串末尾,就一直把i往后挪,直到碰到第一个空格、或者走到字符串结尾才停下。
拿测试用的字符串" this is string "走一遍关键流程就很清楚:
- 初始i=0进第一轮循环:第一段while先把开头两个前导空格全删掉,此时i=0位置是't',删空格逻辑退出;紧接着第二段while一路往后跳过t、h、i、s四个字母,最终i停在"this"后面的第一个空格位置(索引4),这时候本轮循环体跑完了,外层for自动做一次
i++,i直接变成5,刚好把索引4位置的那个单个空格跳了过去。 - i=5进第二轮循环:此时s[5]是"is"的首字符'i',根本不是空格,删空格的while连触发都不会触发;紧接着第二段while往后跳过i、s两个字母,i停在"is"后面的第一个空格位置(索引7),本轮循环结束,外层for又自动做一次
i++把i改成8,又跳过了索引7位置的单个空格。 - i=8进第三轮循环:"is"后面总共有3个连续空格,索引7是刚才被跳过的第一个空格,索引8、9都是多出来的空格,此时s[8]是空格,删空格的while触发,连续删掉这两个多余空格,直到i=8位置变成"string"的首字符's'才停;之后第二段while跳过s、t、r、i、n、g所有字母,i停在字符串尾部的空格位置,本轮跑完后for的i++直接走到字符串长度位置,外层循环结束。
- 最后执行尾部判断,把残留的末尾空格删掉,最终输出就是正确的
"this is string"。
说白了这段代码的效果就是:每遇到连续空格,只留最靠近前一个单词的那一个,剩下的全删掉,刚好符合去多余空格的要求。
顺带提一句,这段代码有边界bug,如果传入空字符串,访问
s[s.length() - 1]会直接越界,实际用的时候要补个空串判断。
内容的提问来源于stack exchange,提问作者Rocket Procd
相关产品推荐
相关产品推荐

