我目前正在使用以下代码在我的程序中右修剪所有std::字符串:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
我目前正在使用以下代码在我的程序中右修剪所有std::字符串:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
由于添加了back()和pop_back(),这在c++ 11中可以更简单地完成。
while ( !s.empty() && isspace(s.back()) ) s.pop_back();
其他回答
上面的方法很棒,但有时您想要使用函数组合来处理例程认为是空白的部分。在这种情况下,使用函子组合操作可能会变得混乱,所以我更喜欢一个简单的循环,我可以修改修剪。这里是一个稍微修改的修剪函数,从C版本复制到这里的SO。在这个例子中,我正在修剪非字母数字字符。
string trim(char const *str)
{
// Trim leading non-letters
while(!isalnum(*str)) str++;
// Trim trailing non-letters
end = str + strlen(str) - 1;
while(end > str && !isalnum(*end)) end--;
return string(str, end+1);
}
这个版本对内部空白和非字母数字进行了修整:
static inline std::string &trimAll(std::string &s)
{
if(s.size() == 0)
{
return s;
}
int val = 0;
for (int cur = 0; cur < s.size(); cur++)
{
if(s[cur] != ' ' && std::isalnum(s[cur]))
{
s[val] = s[cur];
val++;
}
}
s.resize(val);
return s;
}
有点晚了,不过没关系。c++ 11在这里,我们有lambda和auto变量。所以我的版本,也处理全空白和空字符串,是:
#include <cctype>
#include <string>
#include <algorithm>
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
return (wsback<=wsfront ? std::string() : std::string(wsfront,wsback));
}
我们可以从wsfront创建一个反向迭代器,并在第二个find_if_not中使用它作为终止条件,但这只在全空白字符串的情况下有用,gcc 4.8至少不足以用auto推断反向迭代器(std::string::const_reverse_iterator)的类型。我不知道构造反向迭代器有多贵,这里是YMMV。修改后,代码如下所示:
inline std::string trim(const std::string &s)
{
auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}
s.erase(0, s.find_first_not_of(" \n\r\t"));
s.erase(s.find_last_not_of(" \n\r\t")+1);
http://ideone.com/nFVtEo
std::string trim(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && isspace(*it))
it++;
std::string::const_reverse_iterator rit = s.rbegin();
while (rit.base() != it && isspace(*rit))
rit++;
return std::string(it, rit.base());
}