在C++中从std :: string中删除空格

Ste*_*nov 209 c++ stl

在C++中从字符串中删除空格的首选方法是什么?我可以循环遍历所有字符并构建一个新字符串,但有更好的方法吗?

Mat*_*ice 241

最好的办法是使用算法remove_if和isspace:

remove_if(str.begin(), str.end(), isspace);
Run Code Online (Sandbox Code Playgroud)

现在算法本身不能更改容器(只修改值),所以它实际上会将值移动并返回指向现在应该在哪里的指针.所以我们必须调用string :: erase来实际修改容器的长度:

str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
Run Code Online (Sandbox Code Playgroud)

我们还应该注意,remove_if最多只能创建一个数据副本.这是一个示例实现:

template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
    T dest = beg;
    for (T itr = beg;itr != end; ++itr)
        if (!pred(*itr))
            *(dest++) = *itr;
    return dest;
}
Run Code Online (Sandbox Code Playgroud)

  • 因为'isspace'有重载,所以您可能需要限定通用代码以使用:: isspace(不采用语言环境的C实现)或者使用神秘的模板实例化错误. (50认同)
  • -1对于除原始7位ASCII之外的所有字符集,`isspace`的使用是UB.C99§7.4/ 1.它*我并不感到惊讶*我现在已经被赞成71票,尽管是非常糟糕的建议. (30认同)
  • 重复一遍,对于所有非ASCII字符,此答案中的代码将负值(不同于EOF)传递给`isspace`,实际默认选择`char`的签名.因此它有**未定义的行为**.我正在重复它,因为我怀疑故意企图在噪音中淹没这个事实. (15认同)
  • @Joe答案明确提到你之后需要调用`erase`.这将返回正确的结果. (6认同)
  • 全部 - 警惕上述方法(两条单行,不是模板化版本,尽管它可能有同样的问题).我在一个项目中使用它而没有意识到它并不总是正确的.例如,如果您将字符串"1 + 1"传递给它,则返回"1 + 11".我切换到@rupello的方法,它适用于这种情况.快乐的编码! (4认同)
  • @JFSebastian:您几乎错过了大多数(即使不是“每个”)现存的C ++编译器,默认情况下,“ char”是一种“带符号整数”类型。因此,对于非ASCII字符,您将获得负值。例如,在使用Latin-1和默认签名选择的情况下,挪威字符ÆØÅ和æøå为负。 (2认同)
  • @JFSebastian:当您将除EOF以外的负值传递给isspace时,您将具有未定义的行为。因为C ++标准是这样说的,所以要通过合并C标准来实现。就这么简单。您可能会将其与您的论点(得出不同结论)联系起来,以确定一个或多个缺陷。无论如何,此答案中的代码会为所有非ASCII字符传递负值,默认符号为char。因此,它具有“未定义的行为” **,可以*具有您幼稚和错误预期的效果。那是基础知识。 (2认同)
  • 要进行尝试,您可以在Visual C ++的调试版本中尝试使用不同的字符分类功能。一些实现是表驱动的,并且将在非EOF否定参数上崩溃。这就是拥有UB的意思:在某些情况下,使用某些编译器或上下文,您会得到除天真和错误预期之外的其他行为,即不可移植的代码。 (2认同)
  • @JFSebastian:按照标准使用的可表示的含义,约有一半的“有符号字符”值不能表示为“无符号字符”。从无符号到有符号的转换使用相同的术语,其中“否则,值是实现定义的”(C ++ 11§4.7/ 3)。因此,您实际上是在声称,在同一事物中使用的可表示一词在标准的两个不同部分中意味着两个完全不同的事物。如果是这样,那么这就是该标准迄今未知的缺陷。您应该举报。 (2认同)
  • @Cheersandhth.-Alf:你是对的。+1。在 C11 中将非 EOF 的负数 `int` 传递给 `isspace()` 是**未定义的行为**。我问了这个问题 [C11 中“可表示的”是什么意思?](http://stackoverflow.com/q/25776824/4279) 才明白。“永远不要把可以用愚蠢充分解释的东西归咎于恶意”:) (2认同)
  • `错误:没有匹配的函数用于调用 'remove_if(std::__cxx11::basic_string&lt;char&gt;::iterator, std::__cxx11::basic_string&lt;char&gt;::iterator, &lt;unresolved 重载函数类型&gt;)'` (2认同)
  • `没有匹配函数调用'remove_if'`甚至包括算法库。 (2认同)

小智 96

std::string::iterator end_pos = std::remove(str.begin(), str.end(), ' ');
str.erase(end_pos, str.end());
Run Code Online (Sandbox Code Playgroud)

  • 我对规范擦除/删除习语的投票.可以做成一个单元格:str.erase(std :: remove(str.begin(),str.end(),''),str.end()); (31认同)
  • 注意:你需要包含`<algorithm>`才能工作. (11认同)

rup*_*llo 35

来自gamedev

string.erase(std::remove_if(string.begin(), string.end(), std::isspace), string.end());
Run Code Online (Sandbox Code Playgroud)

  • 由于std :: isspace的语言环境重载,这不会在符合标准的实现上进行编译.您需要使用:: isspace或使用std :: bind2nd执行一些不可读的阴谋.通用代码不漂亮吗? (21认同)
  • C++17 解决方案:`string.erase(std::remove_if(string.begin(), string.end(), [](unsigned char x) { return std::isspace(x); }), string.结束());` (5认同)

Nem*_*vic 30

你能使用Boost String Algo吗?http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573

erase_all(str, " "); 
Run Code Online (Sandbox Code Playgroud)

  • 它比`remove_if(str.begin(),str.end(),isspace)慢;`Matt Price提到.我不知道为什么.实际上,所有具有STL替代品的增强功能都比相应的gcc(所有我测试过的)慢.其中一些非常慢!(在unordered_map插入中最多5次)可能是因为共享环境的CPU缓存或类似的东西. (3认同)

小智 15

对于修剪,请使用增强字符串算法:

#include <boost/algorithm/string.hpp>

using namespace std;
using namespace boost;

// ...

string str1(" hello world! ");
trim(str1);      // str1 == "hello world!"
Run Code Online (Sandbox Code Playgroud)

  • -1:这个修剪; 它不会删除所有空格. (12认同)

小智 15

您可以使用此解决方案来删除char:

#include <algorithm>
#include <string>
using namespace std;

str.erase(remove(str.begin(), str.end(), char_to_remove), str.end());
Run Code Online (Sandbox Code Playgroud)

  • 应避免使用命名空间 std。/sf/ask/101690501/ (2认同)

dda*_*cot 11

嗨,你可以做那样的事情.此函数删除所有空格.

string delSpaces(string &str) 
{
   str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
   return str;
}
Run Code Online (Sandbox Code Playgroud)

我做了另一个函数,删除所有不必要的空格.

string delUnnecessary(string &str)
{
    int size = str.length();
    for(int j = 0; j<=size; j++)
    {
        for(int i = 0; i <=j; i++)
        {
            if(str[i] == ' ' && str[i+1] == ' ')
            {
                str.erase(str.begin() + i);
            }
            else if(str[0]== ' ')
            {
                str.erase(str.begin());
            }
            else if(str[i] == '\0' && str[i-1]== ' ')
            {
                str.erase(str.end() - 1);
            }
        }
    }
    return str;
}
Run Code Online (Sandbox Code Playgroud)


NoS*_*tAl 10

在 C++20 中,您可以使用自由函数 std::erase

std::string str = " Hello World  !";
std::erase(str, ' ');
Run Code Online (Sandbox Code Playgroud)

完整示例:

#include<string>
#include<iostream>

int main() {
    std::string str = " Hello World  !";
    std::erase(str, ' ');
    std::cout << "|" << str <<"|";
}
Run Code Online (Sandbox Code Playgroud)

我打印| 很明显,开头的空格也被删除了。

注意:这仅删除空格,而不删除所有其他可能被视为空格的字符,请参阅https://en.cppreference.com/w/cpp/string/byte/isspace


Sud*_*ash 7

string replaceinString(std::string str, std::string tofind, std::string toreplace)
{
        size_t position = 0;
        for ( position = str.find(tofind); position != std::string::npos; position = str.find(tofind,position) )
        {
                str.replace(position ,1, toreplace);
        }
        return(str);
}
Run Code Online (Sandbox Code Playgroud)

用它:

string replace = replaceinString(thisstring, " ", "%20");
string replace2 = replaceinString(thisstring, " ", "-");
string replace3 = replaceinString(thisstring, " ", "+");
Run Code Online (Sandbox Code Playgroud)


Vol*_*ike 6

如果你想用一个简单的宏来做这个,这里有一个:

#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end())
Run Code Online (Sandbox Code Playgroud)

这假设你#include <string>当然已经完成了.

这样称呼它:

std::string sName = " Example Name ";
REMOVE_SPACES(sName);
printf("%s",sName.c_str()); // requires #include <stdio.h>
Run Code Online (Sandbox Code Playgroud)

  • 你为什么要用这个宏呢? (5认同)
  • 同样,调用站点的简称是调用一个以左值引用字符串的_function_。宏与参数交互时会具有令人惊讶的行为(特别是带有副作用),但是更糟的是,如果它们涉及错误,它们的名称就不会在编译器消息中显示,而它们的实现会。 (3认同)