我目前正在使用以下代码在我的程序中右修剪所有std::字符串:

std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);

它工作得很好,但我想知道是否有一些最终情况下它可能会失败?

当然,有优雅的选择和左修剪解决方案的答案是受欢迎的。


当前回答

一种优雅的方法可以是

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));
}

其他回答

在空字符串的情况下,你的代码假设将1添加到string::npos得到0。String::npos的类型是String::size_type,无符号。因此,您依赖于加法的溢出行为。

s.erase(0, s.find_first_not_of(" \n\r\t"));                                                                                               
s.erase(s.find_last_not_of(" \n\r\t")+1);   

好吧,这可能不是最快的,但是。简单。

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;
}

还有一种选择-从两端删除一个或多个字符。

string strip(const string& s, const string& chars=" ") {
    size_t begin = 0;
    size_t end = s.size()-1;
    for(; begin < s.size(); begin++)
        if(chars.find_first_of(s[begin]) == string::npos)
            break;
    for(; end > begin; end--)
        if(chars.find_first_of(s[end]) == string::npos)
            break;
    return s.substr(begin, end-begin+1);
}