C++字符串trim函数中erase调用顺序异常的问题咨询
字符串修剪函数的两个问题解析
// lecture 15: program to trim the start and end white spaces from a string object. #include<iostream> #include<string> // function signature: void trim(std::string*); // main body: int main() { std::string cast = " pokemon legends , arceus "; //input string trim(&cast); return 0; } void trim(std::string* x) { int s = 0; // start index int size = (*x).size(); int e = size - 1; // end index //start whitespace terminator while (s < size && ((*x)[s] == ' ' || (*x)[s] == '\t' || (*x)[s] == '\n')) { // x[s] returns a char, therefore we should not compare with "" string type. s++; } //end whitespace terminator while (e > s && ((*x)[e] == ' ' || (*x)[e] == '\t' || (*x)[e] == '\n')) { e--; } (*x).erase(0, s); // if I call this first ,the second call is ignored. But the program runs fine if it is called after the trailing whitespace erase. (*x).erase(e + 1); //NOTE:: the order of these two functions is important for trimming whitespaces ??????????/learn why. also putting them inside the while loop create some errors ,check why . std::cout << "ok" + *x + "ok" << std::endl; }
为什么erase调用顺序会影响结果?
先调用erase(0, s)删除前导空格后,字符串长度会从原来的size缩减为size - s。而e是基于原字符串长度计算的末尾索引(原字符串的size-1),此时e + 1的值远大于新字符串的长度。根据C++标准库规则,当erase的起始位置超过字符串当前长度时,该操作不会执行任何内容,所以后续删除尾随空格的操作相当于被“跳过”了。
调换顺序后,先调用erase(e + 1)操作的是原字符串,e+1到原字符串末尾正好是需要删除的尾随空格,删除后字符串长度变为e+1。此时再调用erase(0, s),s是原字符串的前导空格数,而前导空格在删除尾随空格后并未被改动,所以这个操作能正确删除前导空格,最终得到预期结果。
为什么不能把erase放进while循环?
将erase放入while循环会引发两个核心问题:
索引混乱:每次调用
erase都会改变字符串的长度和字符位置。比如删除前导空格时,每删一个字符,后续字符都会向前移动一位,但循环里的s仍在递增,这会导致跳过部分字符或重复判断已处理位置,最终可能漏删空格或误删有效字符。效率低下:
string::erase是O(n)复杂度的操作(需要移动后续字符),如果在循环里每次只删一个字符,整个修剪过程的时间复杂度会变成O(n²),长字符串下性能极差。而先确定删除范围再一次性调用erase,只需要两次O(n)操作,效率高得多。
内容的提问来源于stack exchange,提问作者abdul baseer
相关产品推荐
相关产品推荐

