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

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

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

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


当前回答

我知道这是一个非常老的问题,但我已经为您的问题添加了几行代码,它从两端删除了空白。

void trim(std::string &line){

    auto val = line.find_last_not_of(" \n\r\t") + 1;

    if(val == line.size() || val == std::string::npos){
        val = line.find_first_not_of(" \n\r\t");
        line = line.substr(val);
    }
    else
        line.erase(val);
}

其他回答

一种优雅的方法可以是

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));
}
str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); // left trim
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); // right trim

在网上试试!

我不确定您的环境是否相同,但在我的环境中,空字符串情况将导致程序中止。我要么用if(!s.empty())包装这个擦除调用,要么像前面提到的那样使用Boost。

有点晚了,不过没关系。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());
}

C++11:

int i{};
string s = " h e ll \t\n  o";
string trim = " \n\t";

while ((i = s.find_first_of(trim)) != -1)
    s.erase(i,1);

cout << s;

输出:

hello

也适用于空字符串