从字符串中删除前导和尾随空格

Ank*_*kur 74 c++ string

如何在C++中从字符串对象中删除空格.
例如,如何从下面的字符串对象中删除前导和尾随空格.

//Original string: "         This is a sample string                    "
//Desired string: "This is a sample string"
Run Code Online (Sandbox Code Playgroud)

据我所知,字符串类没有提供任何删除前导和尾随空格的方法.

要添加问题,如何扩展此格式以处理字符串的单词之间的额外空格.例如,

// Original string: "          This       is         a sample   string    " 
// Desired string:  "This is a sample string"  
Run Code Online (Sandbox Code Playgroud)

使用解决方案中提到的字符串方法,我可以考虑分两步执行这些操作.

  1. 删除前导和尾随空格.
  2. 在字边界处重复使用find_first_of,find_last_of,find_first_not_of,find_last_not_of和substr以获得所需的格式.

GMa*_*ckG 117

这称为修剪.如果你可以使用Boost,我会推荐它.

否则,使用find_first_not_of获取第一个非空白字符find_last_not_of的索引,然后从不是空白的结尾获取索引.使用这些,用于substr获取没有周围空白的子字符串.

为了回应你的编辑,我不知道这个术语,但我猜的是"减少"的东西,所以这就是我所说的.:)(注意,我已将白色空间更改为参数,以获得灵活性)

#include <iostream>
#include <string>

std::string trim(const std::string& str,
                 const std::string& whitespace = " \t")
{
    const auto strBegin = str.find_first_not_of(whitespace);
    if (strBegin == std::string::npos)
        return ""; // no content

    const auto strEnd = str.find_last_not_of(whitespace);
    const auto strRange = strEnd - strBegin + 1;

    return str.substr(strBegin, strRange);
}

std::string reduce(const std::string& str,
                   const std::string& fill = " ",
                   const std::string& whitespace = " \t")
{
    // trim first
    auto result = trim(str, whitespace);

    // replace sub ranges
    auto beginSpace = result.find_first_of(whitespace);
    while (beginSpace != std::string::npos)
    {
        const auto endSpace = result.find_first_not_of(whitespace, beginSpace);
        const auto range = endSpace - beginSpace;

        result.replace(beginSpace, range, fill);

        const auto newStart = beginSpace + fill.length();
        beginSpace = result.find_first_of(whitespace, newStart);
    }

    return result;
}

int main(void)
{
    const std::string foo = "    too much\t   \tspace\t\t\t  ";
    const std::string bar = "one\ntwo";

    std::cout << "[" << trim(foo) << "]" << std::endl;
    std::cout << "[" << reduce(foo) << "]" << std::endl;
    std::cout << "[" << reduce(foo, "-") << "]" << std::endl;

    std::cout << "[" << trim(bar) << "]" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

结果:

[too much               space]  
[too much space]  
[too-much-space]  
[one  
two]  
Run Code Online (Sandbox Code Playgroud)


Evg*_*pov 44

轻松地从一行中的std :: string中删除前导,尾随和额外空格

value = std::regex_replace(value, std::regex("^ +| +$|( ) +"), "$1");
Run Code Online (Sandbox Code Playgroud)

仅删除前导空格

value.erase(value.begin(), std::find_if(value.begin(), value.end(), std::bind1st(std::not_equal_to<char>(), ' ')));
Run Code Online (Sandbox Code Playgroud)

要么

value = std::regex_replace(value, std::regex("^ +"), "");
Run Code Online (Sandbox Code Playgroud)

仅删除尾随空格

value.erase(std::find_if(value.rbegin(), value.rend(), std::bind1st(std::not_equal_to<char>(), ' ')).base(), value.end());
Run Code Online (Sandbox Code Playgroud)

要么

value = std::regex_replace(value, std::regex(" +$"), "");
Run Code Online (Sandbox Code Playgroud)

只删除额外的空格

value = regex_replace(value, std::regex(" +"), " ");
Run Code Online (Sandbox Code Playgroud)

  • 它不会删除标签,但可以修复.无法修复的是它非常慢(比使用`substr`或`erase`的答案慢约100倍). (7认同)
  • 好一个.提供一些关于这里发生的事情的信息会很有用,因为很难理解这些代码. (3认同)

Gal*_*lik 38

我目前正在使用这些功能:

// trim from left
inline std::string& ltrim(std::string& s, const char* t = " \t\n\r\f\v")
{
    s.erase(0, s.find_first_not_of(t));
    return s;
}

// trim from right
inline std::string& rtrim(std::string& s, const char* t = " \t\n\r\f\v")
{
    s.erase(s.find_last_not_of(t) + 1);
    return s;
}

// trim from left & right
inline std::string& trim(std::string& s, const char* t = " \t\n\r\f\v")
{
    return ltrim(rtrim(s, t), t);
}

// copying versions

inline std::string ltrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return ltrim(s, t);
}

inline std::string rtrim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return rtrim(s, t);
}

inline std::string trim_copy(std::string s, const char* t = " \t\n\r\f\v")
{
    return trim(s, t);
}
Run Code Online (Sandbox Code Playgroud)


jon*_*son 19

提升字符串修剪算法

#include <boost/algorithm/string/trim.hpp>

[...]

std::string msg = "   some text  with spaces  ";
boost::algorithm::trim(msg);
Run Code Online (Sandbox Code Playgroud)


jig*_*ius 9

C++17 引入了std::basic_string_view,一个类模板,它引用类似 char 的对象的常量连续序列,即字符串的视图。除了与 非常相似的界面外std::basic_string,它还有两个附加功能:remove_prefix(),通过向前移动起始点来缩小视图;和 remove_suffix(),通过向后移动其末端来缩小视图。这些可用于修剪前导和尾随空格:

#include <string_view>
#include <string>

std::string_view ltrim(std::string_view str)
{
    const auto pos(str.find_first_not_of(" \t\n\r\f\v"));
    str.remove_prefix(std::min(pos, str.length()));
    return str;
}

std::string_view rtrim(std::string_view str)
{
    const auto pos(str.find_last_not_of(" \t\n\r\f\v"));
    str.remove_suffix(std::min(str.length() - pos - 1, str.length()));
    return str;
}

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

int main()
{
    std::string str = "   hello world   ";
    auto sv1{ ltrim(str) };  // "hello world   "
    auto sv2{ rtrim(str) };  // "   hello world"
    auto sv3{ trim(str) };   // "hello world"

    //If you want, you can create std::string objects from std::string_view objects
    std::string s1{ sv1 };
    std::string s2{ sv2 };
    std::string s3{ sv3 };
}
Run Code Online (Sandbox Code Playgroud)

注意:使用 来std::min确保pos不大于size(),当字符串中的所有字符都是空格并find_first_not_of返回时,就会发生这种情况npos。此外,std::string_view是一个非拥有引用,因此仅当原始字符串仍然存在时它才有效。修剪字符串视图对其所基于的字符串没有影响。


jha*_*a-G 8

以下是如何做到这一点:

std::string & trim(std::string & str)
{
   return ltrim(rtrim(str));
}
Run Code Online (Sandbox Code Playgroud)

支持功能的实现如下:

std::string & ltrim(std::string & str)
{
  auto it2 =  std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
  str.erase( str.begin() , it2);
  return str;   
}

std::string & rtrim(std::string & str)
{
  auto it1 =  std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
  str.erase( it1.base() , str.end() );
  return str;   
}
Run Code Online (Sandbox Code Playgroud)

一旦你完成所有这些,你也可以这样写:

std::string trim_copy(std::string const & str)
{
   auto s = str;
   return ltrim(rtrim(s));
}
Run Code Online (Sandbox Code Playgroud)

试试这个


小智 7

这是我剥离前导和尾随空格的解决方案......

std::string stripString = "  Plamen     ";
while(!stripString.empty() && std::isspace(*stripString.begin()))
    stripString.erase(stripString.begin());

while(!stripString.empty() && std::isspace(*stripString.rbegin()))
    stripString.erase(stripString.length()-1);
Run Code Online (Sandbox Code Playgroud)

结果是"Plamen"


Sem*_*ger 7

在jon-hanson建议使用boost之后修剪前导空格和尾随空格的示例(仅删除尾随空格和待处理空格):

#include <boost/algorithm/string/trim.hpp>

std::string str = "   t e s t    ";

boost::algorithm::trim ( str );
Run Code Online (Sandbox Code Playgroud)

结果是 "t e s t"

还有

  • trim_left 结果是 "t e s t "
  • trim_right 结果是 " t e s t"


Mur*_*y78 5

/// strip a string, remove leading and trailing spaces
void strip(const string& in, string& out)
{
    string::const_iterator b = in.begin(), e = in.end();

    // skipping leading spaces
    while (isSpace(*b)){
        ++b;
    }

    if (b != e){
        // skipping trailing spaces
        while (isSpace(*(e-1))){
            --e;
        }
    }

    out.assign(b, e);
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,isSpace() 函数是一个布尔函数,它告诉我们一个字符是否是空格,你可以实现这个函数来反映你的需要,或者如果你想从“ctype.h”调用 isspace() .


Thi*_* VB 5

修剪前导空格和尾随空格的示例

std::string aString("    This is a string to be trimmed   ");
auto start = aString.find_first_not_of(' ');
auto end = aString.find_last_not_of(' ');
std::string trimmedString;
trimmedString = aString.substr(start, (end - start) + 1);
Run Code Online (Sandbox Code Playgroud)

或者

trimmedSring = aString.substr(aString.find_first_not_of(' '), (aString.find_last_not_of(' ') - aString.find_first_not_of(' ')) + 1);
Run Code Online (Sandbox Code Playgroud)

  • 人们不喜欢查看 10 页代码来学习如何修剪字符串。 (3认同)
  • 如果字符串只有空格,则会损坏 (3认同)