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

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

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

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


当前回答

因为我想用c++ 11的方法更新我的旧c++修剪函数,我已经测试了很多关于这个问题的答案。我的结论是,我保留了旧的c++解决方案!

它是总体上最快的一个,即使添加更多的字符来检查(例如\r\n我没有看到\f\v的用例)仍然比使用算法的解决方案更快。

std::string & trimMe (std::string & str)
{
   // right trim
   while (str.length () > 0 && (str [str.length ()-1] == ' ' || str [str.length ()-1] == '\t'))
      str.erase (str.length ()-1, 1);

   // left trim
   while (str.length () > 0 && (str [0] == ' ' || str [0] == '\t'))
      str.erase (0, 1);
   return str;
}

其他回答

试试这个,对我很管用。

inline std::string trim(std::string& str)
{
    str.erase(str.find_last_not_of(' ')+1);         //suffixing spaces
    str.erase(0, str.find_first_not_of(' '));       //prefixing spaces
    return str;
}

使用下面的代码对std::strings (ideone)中的空格和制表符进行右对齐:

// trim trailing spaces
size_t endpos = str.find_last_not_of(" \t");
size_t startpos = str.find_first_not_of(" \t");
if( std::string::npos != endpos )
{
    str = str.substr( 0, endpos+1 );
    str = str.substr( startpos );
}
else {
    str.erase(std::remove(std::begin(str), std::end(str), ' '), std::end(str));
}

为了平衡,我将包括左边的代码(ideone):

// trim leading spaces
size_t startpos = str.find_first_not_of(" \t");
if( string::npos != startpos )
{
    str = str.substr( startpos );
}

我已经阅读了大部分答案,但没有发现任何人使用istringstream

std::string text = "Let me split this into words";

std::istringstream iss(text);
std::vector<std::string> results((std::istream_iterator<std::string>(iss)),
                                 std::istream_iterator<std::string>());

结果是单词的向量,它可以处理有内部空白的字符串,希望这有帮助。

在c++ 17中,你可以使用basic_string_view::remove_prefix和basic_string_view::remove_suffix:

std::string_view trim(std::string_view s)
{
    s.remove_prefix(std::min(s.find_first_not_of(" \t\r\v\n"), s.size()));
    s.remove_suffix(std::min(s.size() - s.find_last_not_of(" \t\r\v\n") - 1, s.size()));

    return s;
}

一个不错的替代方案:

std::string_view ltrim(std::string_view s)
{
    s.remove_prefix(std::distance(s.cbegin(), std::find_if(s.cbegin(), s.cend(),
         [](int c) {return !std::isspace(c);})));

    return s;
}

std::string_view rtrim(std::string_view s)
{
    s.remove_suffix(std::distance(s.crbegin(), std::find_if(s.crbegin(), s.crend(),
        [](int c) {return !std::isspace(c);})));

    return s;
}

std::string_view trim(std::string_view s)
{
    return ltrim(rtrim(s));
}

下面是一个简单的实现。对于这样一个简单的操作,您可能不应该使用任何特殊的构造。内置的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);
}