如何替换字符串中出现的所有字符?

big*_*g-z 450 c++ algorithm stdstring str-replace

将所有出现的角色替换为另一个角色的有效方法是什么std::string

Kir*_*sky 692

std::string不包含此类功能,但您可以使用标头中的独立replace功能algorithm.

#include <algorithm>
#include <string>

void some_func() {
  std::string s = "example string";
  std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,这允许用另一个char替换一个char.它不能用更多的字符(即字符串)替换字符.有没有办法用更多的字符进行搜索替换? (150认同)
  • `std :: string`是**一个专门设计用于操作字符序列的容器**.[链接](http://www.cplusplus.com/reference/string/string/) (6认同)
  • @Kirill V. Lyadvinsky如果我只想删除一个事件. (6认同)
  • @Transcendent:这正是`std :: string :: replace()`而不是`std :: replace()`所发生的事情!'x'(`char`)被隐含地转换为`size_t` [值120],因此整个字符串或其中的一部分将填充120个'y'副本. (5认同)
  • @ KirillV.Lyadvinsky:当我使用这个方法用y替换所有x时,无论原始字符串是什么,结果都是一个冗长的y字符串.我很好奇你认为这是什么问题.(代码和你写的完全一样) (4认同)
  • @FlowFlowOverFlow,我怀疑您是否有“代码完全相同”。在这里检查:http://codepad.org/UIcrFX1j - 它工作正常。 (2认同)

Unc*_*eiv 126

我以为我也会在增强解决方案中投入:

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

// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");

// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");
Run Code Online (Sandbox Code Playgroud)


Gau*_*lio 113

问题集中在character替换上,但是,由于我发现这个页面非常有用(特别是Konrad的评论),我想分享这个更通用的实现,它也允许处理substrings:

std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
    }
    return str;
}
Run Code Online (Sandbox Code Playgroud)

用法:

std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;
Run Code Online (Sandbox Code Playgroud)

输出:

Number_Of_Beans

XXjXugtXty

hhjhugthty


编辑:

上面的内容可以通过更合适的方式实现,如果您需要考虑性能,可以返回nothing(void)并直接对str作为参数给出的字符串执行更改,通过地址而不是传递.这将避免原始字符串的无用且昂贵的副本,同时返回结果.你的电话,然后......

代码:

static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
    // Same inner code...
    // No return statement
}
Run Code Online (Sandbox Code Playgroud)

希望这对其他人有帮助......

  • 如果源字符串很大并且要替换的字符串很多,则会出现性能问题.string :: replace()会多次调用,导致大量的字符串副本.请参阅解决该问题的解决方案. (4认同)

min*_*ros 28

想象一个大的二进制blob,其中所有0x00字节将被"\ 1\x30"替换,所有0x01字节将被"\ 1\x31"替换,因为传输协议不允许\ 0-bytes.

如果:

  • 替换和替换字符串有不同的长度,
  • 源字符串中有很多被替换字符串的出现
  • 源字符串很大,

提供的解决方案无法应用(因为它们只替换单个字符)或存在性能问题,因为它们会多次调用string :: replace,这会反复生成blob大小的副本.(我不知道增强解决方案,从这个角度来看也许没问题)

这一个沿源字符串中所有出现的散步和建立一块新的字符串件一次:

void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
    std::string newString;
    newString.reserve(source.length());  // avoids a few memory allocations

    std::string::size_type lastPos = 0;
    std::string::size_type findPos;

    while(std::string::npos != (findPos = source.find(from, lastPos)))
    {
        newString.append(source, lastPos, findPos - lastPos);
        newString += to;
        lastPos = findPos + from.length();
    }

    // Care for the rest after last occurrence
    newString += source.substr(lastPos);

    source.swap(newString);
}
Run Code Online (Sandbox Code Playgroud)

  • 最好使用 `newString.append(source, lastPos, source.length() - lastPos);` 而不是 `newString += source.substr(lastPos);` 以避免创建临时字符串 [如 `substr()`做]。(我无法编辑此答案,因为建议的编辑队列已满。) (3认同)

T.E*_*.D. 20

对单个字符的简单查找和替换将类似于:

s.replace(s.find("x"), 1, "y")

要对整个字符串执行此操作,最简单的方法是循环直到s.find开始返回npos.我想你也可以赶上range_error退出循环,但这有点难看.

  • 虽然当要替换的字符数与字符串的长度相比较小时,这可能是一个合适的解决方案,但它不能很好地扩展.由于原始字符串中需要替换的字符比例增加,此方法将及时接近O(N ^ 2). (7认同)
  • 真正.我的一般理念是做容易(写和读)的事情,直到效率低下导致实际问题为止.在某些情况下,你可能会有O(N**2)重要的单调字符串,但99%的情况下我的字符串是1K或更少. (7认同)
  • ...话虽如此,我更喜欢基里尔的方法(而且已经投了票). (3认同)

小智 19

为了完整起见,以下是如何使用std::regex.

#include <regex>
#include <string>

int main()
{
    const std::string s = "example string";
    const std::string r = std::regex_replace(s, std::regex("x"), "y");
}
Run Code Online (Sandbox Code Playgroud)


Vol*_*ike 6

如果你想要替换多个单个字符,并且只处理std::string,那么这个片段就可以了,用sReplace替换sHaystack中的sNeedle,sNeedle和sReplace不需要大小相同.此例程使用while循环替换所有出现,而不是仅从左到右找到的第一个出现.

while(sHaystack.find(sNeedle) != std::string::npos) {
  sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果 kNeedle 恰好是 sReplace 的子字符串,这将无限循环。 (4认同)
  • @ChangmingSun你的意思是O(n)解决方案? (3认同)