代码来自
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<class InputIterator, class UnaryPredicate> InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred) { while (first!=last) { if (pred(*first)) return first; ++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 bool IsOdd (int i) { 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;
}
