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

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

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

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


当前回答

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

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

其他回答

由于添加了back()和pop_back(),这在c++ 11中可以更简单地完成。

while ( !s.empty() && isspace(s.back()) ) s.pop_back();

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

str = "   aaa    ";
int len = str.length();
// rtrim
while(str[len-1] == ' ') { str.erase(--len,1); }
// ltrim
while(str[0] == ' ') { str.erase(0,1); }

这就是我用的。继续把前面的空格去掉,然后,如果还有剩余的,从后面也这样做。

void trim(string& s) {
    while(s.compare(0,1," ")==0)
        s.erase(s.begin()); // remove leading whitespaces
    while(s.size()>0 && s.compare(s.size()-1,1," ")==0)
        s.erase(s.end()-1); // remove trailing whitespaces
}

使用Boost的字符串算法是最简单的:

#include <boost/algorithm/string.hpp>

std::string str("hello world! ");
boost::trim_right(str);

STR现在是"hello world!"。还有trim_left和trim,它们修剪两边。


如果你给上面的函数名加上_copy后缀,例如trim_copy,函数将返回一个经过修剪的字符串副本,而不是通过引用修改它。

如果你给上面的任何函数名加上_if后缀,例如trim_copy_if,你可以修剪所有满足自定义谓词的字符,而不是只有空白。

这个版本对内部空白和非字母数字进行了修整:

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