代码来自
https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring?page=1&tab=votes#tab-top
std::string 没有trim函数,需要自己实现。
ltrim实现如下:
// trim from start (inplace)
staticinlinevoid ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(),s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
std::string的erase()函数有如下三种形式。http://www.cplusplus.com/reference/string/string/erase/
sequence (1) | string& erase (size_t pos = 0, size_t len = npos); |
character (2) | iterator erase (const_iterator p); |
range (3) | iterator erase (const_iterator first, const_iterator last); |
1 从pos开始删除len个字符
2 删除p指向的字符
3 删除半开区间[first,last)内的字符。(如果first和last一样,则不删除任何字符。)
ltrim使用的是第三种形式。
std::find_if函数原型。http://www.cplusplus.com/reference/algorithm/find_if/
template<
classInputIterator,
classUnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while
(first!=last) {
if
(pred(*first))
returnfirst;
++first;
}
return
last;
}
其中,第三个参数pred是一个函数,表示搜索的条件,符合条件即返回。如果没有符合条件的iterator,就会返回last。在实际使用中,last经常是end。而end不是最后一个元素,而是位于最后一个元素的后面。因此,不会出现明明没有符合条件的元素,却会把最后一个元素错误的当成符合条件的元素而返回的问题。
下面的例子演示了如何找到第一个奇数。
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
boolIsOdd (
inti) {
return
((i%2)==1);
}
int main () {
std::vector<
int> myvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vector<
int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout <<
"The first odd value is "<< *it <<
'\n';
return
0;
}
Output:
The first odd value is 25 |
如果上面程序中push_back的数字都是偶数的话,也不会把最后一个偶数错误地输出,而是会出现运行时错误。因为*it表示end中的内容,而end中没有任何内容。
[](int ch) { return !std::isspace(ch); }
这是一个lambda函数(匿名函数),相当于上面例子中的IsOdd。
在ltrim中的意思是不是空白的字符。
空白字符不只是空格,还包含下表中的字符。http://www.cplusplus.com/reference/cctype/isspace/
For the "C" locale, white-spacecharacters are any of:
' ' | (0x20) | space (SPC) |
'\t' | (0x09) | horizontal tab (TAB) |
'\n' | (0x0a) | newline (LF) |
'\v' | (0x0b) | vertical tab (VT) |
'\f' | (0x0c) | feed (FF) |
'\r' | (0x0d) | carriage return (CR) |
其实,这里也可以把这个lambda函数写成有名字的函数,就像上面那个IsOdd。使用lambda只是更简洁一点而已。
关于lambda函数,这篇文章讲得非常清晰。
https://www.cnblogs.com/pzhfei/archive/2013/01/14/lambda_expression.html
ltrim的机制如下:
find_if会找到第一个不是空白的字符,erase会删除从第一个字符到找到的那个字符之前的所有字符。
如果string的第一个字符就不是空白字符,用半开区间表示就是[0,0),所以不会删除任何字符。
如果string全部是空白字符(比如说10个空格),找到的第一个不是空白的字符就是第11个字符,用半开区间表示就是[0,10),所以不会漏删最后一个空格。
全部的代码如下:
#include<algorithm>
#include<cctype>
#include<locale>
// trim from start (inplace)
staticinlinevoid ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(),s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
// trim from end (inplace)
staticinlinevoid rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (inplace)
staticinlinevoid trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start(copying)
staticinline std::string ltrim_copy(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
staticinline std::string rtrim_copy(std::string s) {
rtrim(s);
return s;
}
// trim from both ends(copying)
staticinline std::string trim_copy(std::string s) {
trim(s);
return s;
}