C++ 用字符串中的一个空格替换多个空格

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8362094/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:26:07  来源:igfitidea点击:

Replace multiple spaces with one space in a string

c++stringreplace

提问by evenodd

How would I do something in c++similar to the following code:

我将如何执行c++类似于以下代码的操作:

//Lang: Java
string.replaceAll("  ", " ");

This code-snippet would replace all multiple spaces in a string with a single space.

此代码片段将用单个空格替换字符串中的所有多个空格。

回答by Benjamin Lindley

bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); }

std::string::iterator new_end = std::unique(str.begin(), str.end(), BothAreSpaces);
str.erase(new_end, str.end());   

How this works. The std::uniquehas two forms. The first form goes through a range and removes adjacent duplicates. So the string "abbaaabbbb" becomes "abab". The second form, which I used, takes a predicate which should take two elements and return true if they should be considered duplicates. The function I wrote, BothAreSpaces, serves this purpose. It determines exactly what it's name implies, that both of it's parameters are spaces. So when combined with std::unique, duplicate adjacent spaces are removed.

这是如何工作的。将std::unique有两种形式。第一种形式通过一个范围并删除相邻的重复项。所以字符串“abbaaabbbb”变成了“abab”。我使用的第二种形式采用一个谓词,该谓词应该包含两个元素,如果它们被认为是重复的,则返回 true。我写的函数BothAreSpaces,就是为了这个目的。它确切地确定了它的名称所暗示的含义,即它的两个参数都是空格。因此,当与 结合使用时std::unique,会删除重复的相邻空格。

Just like std::removeand remove_if, std::uniquedoesn't actually make the container smaller, it just moves elements at the end closer to the beginning. It returns an iterator to the new end of range so you can use that to call the erasefunction, which is a member function of the string class.

就像std::removeand一样remove_ifstd::unique实际上并没有使容器变小,它只是将末尾的元素移到更靠近开头的位置。它返回一个迭代器到新的范围结束,因此您可以使用它来调用erase函数,它是字符串类的成员函数。

Breaking it down, the erase function takes two parameters, a begin and an end iterator for a range to erase. For it's first parameter I'm passing the return value of std::unique, because that's where I want to start erasing. For it's second parameter, I am passing the string's end iterator.

分解它,擦除函数需要两个参数,一个开始和一个结束迭代器,用于擦除范围。对于它的第一个参数,我传递了 的返回值std::unique,因为这是我想要开始擦除的地方。对于它的第二个参数,我正在传递字符串的结束迭代器。

回答by paul23

So, I tried a way with std::remove_if & lambda expressions - though it seems still in my eyes easier to follow than above code, it doesn't have that "wow neat, didn't realize you could do that" thing to it.. Anyways I still post it, if only for learning purposes:

所以,我尝试了一种使用 std::remove_if 和 lambda 表达式的方法——尽管在我看来它仍然比上面的代码更容易理解,但它没有“哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇它..无论如何我仍然发布它,如果只是为了学习目的:

bool prev(false);
char rem(' ');
auto iter = std::remove_if(str.begin(), str.end(), [&] (char c) -> bool {
    if (c == rem && prev) {
        return true;
    }
    prev = (c == rem);
    return false;
});
in.erase(iter, in.end());

EDITrealized that std::remove_if returns an iterator which can be used.. removed unnecessary code.

编辑意识到 std::remove_if 返回一个可以使用的迭代器......删除了不必要的代码。

回答by tlaxcala

A variant of Benjamin Lindley's answer that uses a lambda expression to make things cleaner:

Benjamin Lindley 的答案的一个变体,它使用 lambda 表达式使事情更清晰:

std::string::iterator new_end = 
        std::unique(str.begin(), str.end(),
        [=](char lhs, char rhs){ return (lhs == rhs) && (lhs == ' '); }
        );
str.erase(new_end, str.end());

回答by Mike Jiang

Why not use a regular expression:

为什么不使用正则表达式:

boost::regex_replace(str, boost::regex("[' ']{2,}"), " ");

boost::regex_replace(str, boost::regex("[' ']{2,}"), " ");

回答by Patrick Neary

how about isspace(lhs) && isspace(rhs)to handle all types of whitespace

如何isspace(lhs) && isspace(rhs)处理所有类型的空格