如何截取一个std::string?

1001
我目前在我的程序中使用以下代码来去除所有的std::string的右空格:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);

它运行良好,但我想知道是否存在一些极端情况会导致它失败?
当然,欢迎提供优雅的替代方案和左修剪解决方案。
52个回答

2
上述方法很好,但有时您想要使用一组函数来处理例程认为的空格。在这种情况下,使用函数对象组合操作可能会变得混乱,因此我更喜欢一个简单的循环,可以修改用于修剪。下面是从 SO 上复制的 C 版本稍微修改过的修剪函数示例。在此示例中,我修剪了非字母数字字符。
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);
}

1
忘记了 const char* end - SSpoke

2

这个怎么样?

#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 ++还比较新,所以如果我在这里犯错,请原谅我。

7
使用正则表达式来修剪字符串有点过头了。 - user1095108
2
它比其他选项更加CPU密集吗? - Duncan
1
与此相关的问题(@user1095108):https://stackoverflow.com/questions/68648591/how-can-i-trim-empty-whitespace-lines-without-using-regex - TylerH

1

我想更新我的旧C++ trim函数,采用C++ 11方式。我测试了很多发布的答案,我的结论是我仍然使用我的旧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;
}

1

使用std::find_if_not和反向迭代器(无需+1/-1调整),并返回修剪空格的数量

// returns number of spaces removed
std::size_t RoundTrim(std::string& s)
{
    auto const beforeTrim{ s.size() };

    auto isSpace{ [](auto const& e) { return std::isspace(e); } };

    s.erase(cbegin(s), std::find_if_not(cbegin(s), cend(s), isSpace));
    s.erase(std::find_if_not(crbegin(s), crend(s), isSpace).base(), end(s));

    return beforeTrim - s.size();
};

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

1
另一种选择-从两端删除一个或多个字符。
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);
}

1

好的,这可能不是最快的方法,但它很简单。

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

这是不正确的。你需要反转 ltrim 和 rtrim 才能使其工作。 - Mathieu Westphal
这是不正确的:如果 str==""str==" "(三个空格),它会抛出一个数组异常错误。为了修复,需要在两个 while 循环的 第一个 检查中添加一个检查 !copy.empty() &&rtrim 实现在每一步都将整个字符串向下移动,这可能效率低下。如果效率很重要,请提供其他解决方案,该方案执行扫描,然后进行单个修剪操作。 - Contango

0
我正在使用这个:
void trim(string &str){
    int i=0;

    //left trim
    while (isspace(str[i])!=0)
        i++;
    str = str.substr(i,str.length()-i);

    //right trim
    i=str.length()-1;
    while (isspace(str[i])!=0)
        i--;
    str = str.substr(0,i+1);
}

0
以下是一种单通(也可能是双通)解决方案。它会两次遍历字符串中的空格部分,一次遍历非空格部分。
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;                                                                                                                                                                                                                               
}                                          

0

简易字符串修剪(仅限空格):

std::string trimSpaces(const std::string& str)
{
    int start, len;
    
    for (start = 0; start < str.size() && str[start] == ' '; start++);
    for (len = str.size() - start; len > 0 && str[start + len - 1] == ' '; len--);
    
    return str.substr(start, len);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接