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

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

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

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


当前回答

你所做的是好的,是稳健的。我用同样的方法已经很长时间了,我还没有找到一个更快的方法:

const char* ws = " \t\n\r\f\v";

// trim from end of string (right)
inline std::string& rtrim(std::string& s, const char* t = ws)
{
    s.erase(s.find_last_not_of(t) + 1);
    return s;
}

// trim from beginning of string (left)
inline std::string& ltrim(std::string& s, const char* t = ws)
{
    s.erase(0, s.find_first_not_of(t));
    return s;
}

// trim from both ends of string (right then left)
inline std::string& trim(std::string& s, const char* t = ws)
{
    return ltrim(rtrim(s, t), t);
}

通过提供要修剪的字符,您可以灵活地修剪非空白字符,并高效地只修剪您想修剪的字符。

其他回答

下面是一个通道(可能是两个通道)的解决方案。它遍历字符串的空白部分两次,非空白部分一次。

void trim(std::string& s) {                                                                                                                                                                                                               
    if (s.empty())                                                                                                                                                                                                                        
        return;                                                                                                                                                                                                                           

    int l = 0, r = s.size()  - 1;                                                                                                                                                                                                         

    while (l < s.size() && std::isspace(s[l++])); // l points to first non-whitespace char.                                                                                                                                               
    while (r >= 0 && std::isspace(s[r--])); // r points to last non-whitespace char.                                                                                                                                                      

    if (l > r)                                                                                                                                                                                                                            
        s = "";                                                                                                                                                                                                                           
    else {                                                                                                                                                                                                                                
        l--;                                                                                                                                                                                                                              
        r++;                                                                                                                                                                                                                              
        int wi = 0;                                                                                                                                                                                                                       
        while (l <= r)                                                                                                                                                                                                                    
            s[wi++] = s[l++];                                                                                                                                                                                                             
        s.erase(wi);                                                                                                                                                                                                                      
    }                                                                                                                                                                                                                                     
    return;                                                                                                                                                                                                                               
}                                          

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

也适用于空字符串

使用下面的代码对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 );
}

这个……怎么样?

#include <iostream>
#include <string>
#include <regex>

std::string ltrim( std::string str ) {
    return std::regex_replace( str, std::regex("^\\s+"), std::string("") );
}

std::string rtrim( std::string str ) {
    return std::regex_replace( str, std::regex("\\s+$"), std::string("") );
}

std::string trim( std::string str ) {
    return ltrim( rtrim( str ) );
}

int main() {

    std::string str = "   \t  this is a test string  \n   ";
    std::cout << "-" << trim( str ) << "-\n";
    return 0;

}

注意:我对c++还是个新手,所以如果我在这里离题了,请原谅。

上面的方法很棒,但有时您想要使用函数组合来处理例程认为是空白的部分。在这种情况下,使用函子组合操作可能会变得混乱,所以我更喜欢一个简单的循环,我可以修改修剪。这里是一个稍微修改的修剪函数,从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);
}