我目前正在使用以下代码在我的程序中右修剪所有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);
它工作得很好,但我想知道是否有一些最终情况下它可能会失败?
当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。
当前回答
看来我真的是姗姗来迟了——我不敢相信7年前有人问我这个问题!
以下是我对这个问题的看法。我正在做一个项目,现在不想麻烦地使用Boost。
std::string trim(std::string str) {
if(str.length() == 0) return str;
int beg = 0, end = str.length() - 1;
while (str[beg] == ' ') {
beg++;
}
while (str[end] == ' ') {
end--;
}
return str.substr(beg, end - beg + 1);
}
这个解决方案将从左边和右边修剪。
其他回答
Trim c++ 11实现:
static void trim(std::string &s) {
s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), [](char c){ return std::isspace(c); }));
s.erase(std::find_if_not(s.rbegin(), s.rend(), [](char c){ return std::isspace(c); }).base(), s.end());
}
一种优雅的方法可以是
std::string & trim(std::string & str)
{
return ltrim(rtrim(str));
}
支持功能实现为:
std::string & ltrim(std::string & str)
{
auto it = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( str.begin() , it);
return str;
}
std::string & rtrim(std::string & str)
{
auto it = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
str.erase( it.base() , str.end() );
return str;
}
一旦你把这些都准备好了,你也可以这样写:
std::string trim_copy(std::string const & str)
{
auto s = str;
return ltrim(rtrim(s));
}
对噪音做出我的解决方案。Trim默认创建一个新字符串并返回修改后的字符串,而trim_in_place则修改传递给它的字符串。trim函数支持c++11 move语义。
#include <string>
// modifies input string, returns input
std::string& trim_left_in_place(std::string& str) {
size_t i = 0;
while(i < str.size() && isspace(str[i])) { ++i; };
return str.erase(0, i);
}
std::string& trim_right_in_place(std::string& str) {
size_t i = str.size();
while(i > 0 && isspace(str[i - 1])) { --i; };
return str.erase(i, str.size());
}
std::string& trim_in_place(std::string& str) {
return trim_left_in_place(trim_right_in_place(str));
}
// returns newly created strings
std::string trim_right(std::string str) {
return trim_right_in_place(str);
}
std::string trim_left(std::string str) {
return trim_left_in_place(str);
}
std::string trim(std::string str) {
return trim_left_in_place(trim_right_in_place(str));
}
#include <cassert>
int main() {
std::string s1(" \t\r\n ");
std::string s2(" \r\nc");
std::string s3("c \t");
std::string s4(" \rc ");
assert(trim(s1) == "");
assert(trim(s2) == "c");
assert(trim(s3) == "c");
assert(trim(s4) == "c");
assert(s1 == " \t\r\n ");
assert(s2 == " \r\nc");
assert(s3 == "c \t");
assert(s4 == " \rc ");
assert(trim_in_place(s1) == "");
assert(trim_in_place(s2) == "c");
assert(trim_in_place(s3) == "c");
assert(trim_in_place(s4) == "c");
assert(s1 == "");
assert(s2 == "c");
assert(s3 == "c");
assert(s4 == "c");
}
好吧,这可能不是最快的,但是。简单。
str = " aaa ";
int len = str.length();
// rtrim
while(str[len-1] == ' ') { str.erase(--len,1); }
// ltrim
while(str[0] == ' ') { str.erase(0,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;
}