我目前正在使用以下代码在我的程序中右修剪所有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);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
下面是一个简单的实现。对于这样一个简单的操作,您可能不应该使用任何特殊的构造。内置的isspace()函数负责处理各种形式的白色字符,因此我们应该充分利用它。您还必须考虑字符串为空或只是一堆空格的特殊情况。向左或向右修剪可以从下面的代码派生。
string trimSpace(const string &str) {
if (str.empty()) return str;
string::size_type i,j;
i=0;
while (i<str.size() && isspace(str[i])) ++i;
if (i == str.size())
return string(); // empty string
j = str.size() - 1;
//while (j>0 && isspace(str[j])) --j; // the j>0 check is not needed
while (isspace(str[j])) --j
return str.substr(i, j-i+1);
}
其他回答
这太烦人了,我
必须谷歌它 发现我必须使用火箭科学 字符串中没有简单的trim/toupper函数
对我来说,这是最快的解决方法:
CString tmp(line.c_str());
tmp = tmp.Trim().MakeLower();
string buffer = tmp;
我可以使用lambda ops,迭代器,以及所有的东西,这很酷。但我只需要处理一个字符串而不是一个字符…
上面的方法很棒,但有时您想要使用函数组合来处理例程认为是空白的部分。在这种情况下,使用函子组合操作可能会变得混乱,所以我更喜欢一个简单的循环,我可以修改修剪。这里是一个稍微修改的修剪函数,从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);
}
为什么不用?
auto no_space = [](char ch) -> bool {
return !std::isspace<char>(ch, std::locale::classic());
};
auto ltrim = [](std::string& s) -> std::string& {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), no_space));
return s;
};
auto rtrim = [](std::string& s) -> std::string& {
s.erase(std::find_if(s.rbegin(), s.rend(), no_space).base(), s.end());
return s;
};
auto trim_copy = [](std::string s) -> std::string& { return ltrim(rtrim(s)); };
auto trim = [](std::string& s) -> std::string& { return ltrim(rtrim(s)); };
这个好吗?(因为这篇文章完全需要另一个答案:)
string trimBegin(string str)
{
string whites = "\t\r\n ";
int i = 0;
while (whites.find(str[i++]) != whites::npos);
str.erase(0, i);
return str;
}
类似的情况下,trimEnd,只是反转极化,指数。
有点晚了,不过没关系。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());
}