556

用另一个字符替换所有出现的字符的有效方法是什么std::string

4

16 回答 16

866

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'
}
于 2010-05-24T11:33:32.460 回答
151

问题集中在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;
}

用法:

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;

输出:

Number_Of_Beans

XXjXugtXty

好听的


编辑:

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

代码 :

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

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

于 2014-06-19T20:23:10.853 回答
142

我想我也会加入boost 解决方案

#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, "#", "@");
于 2013-02-27T12:10:27.817 回答
39

想象一个大的二进制 blob,其中所有 0x00 字节应替换为“\1\x30”,所有 0x01 字节应替换为“\1\x31”,因为传输协议不允许使用 \0 字节。

在以下情况下:

  • 替换和要替换的字符串具有不同的长度,
  • 源字符串中有很多次要替换的字符串,并且
  • 源字符串很大,

提供的解决方案无法应用(因为它们仅替换单个字符)或存在性能问题,因为它们会调用 string::replace 多次,这会一遍又一遍地生成 blob 大小的副本。(不知道boost解决方案,从那个角度来说可能还可以)

这个遍历源字符串中的所有出现,并一次一个地构建新的字符串:

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);
}
于 2015-04-20T16:07:38.777 回答
24

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

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

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

于 2010-05-24T11:56:37.343 回答
7

如果您要替换多个字符,并且只处理std::string,那么此代码段将起作用,将 sHaystack 中的 sNeedle 替换为 sReplace,并且 sNeedle 和 sReplace 不需要具有相同的大小。此例程使用 while 循环替换所有出现的事件,而不仅仅是从左到右找到的第一个。

while(sHaystack.find(sNeedle) != std::string::npos) {
  sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
于 2016-02-07T00:20:53.680 回答
6

为了完整起见,这里是如何使用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");
}
于 2020-07-28T02:52:41.100 回答
4

正如基里尔建议的那样,要么使用 replace 方法,要么沿着字符串迭代,独立地替换每个字符。

或者,您可以使用该find方法或find_first_of根据您需要做什么。这些解决方案都不会一次性完成这项工作,但是您应该通过几行额外的代码使它们为您工作。:-)

于 2010-05-24T11:36:44.967 回答
4

Abseil StrReplaceAll怎么样?从头文件:

// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
//                                                {"&", "&amp;"},
//                                                {"<", "&lt;"},
//                                                {">", "&gt;"},
//                                                {"\"", "&quot;"},
//                                                {"'", "&#39;"}});
于 2019-11-14T09:06:09.063 回答
3
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
    int len, loop=0;
    string nword="", let;
    len=word.length();
    len--;
    while(loop<=len){
        let=word.substr(loop, 1);
        if(let==target){
            nword=nword+replacement;
        }else{
            nword=nword+let;
        }
        loop++;
    }
    return nword;

}
//Main..
int main() {
  string word;
  cout<<"Enter Word: ";
  cin>>word;
  cout<<replace(word, "x", "y")<<endl;
  return 0;
}
于 2015-02-25T18:52:10.097 回答
2

老套 :-)

std::string str = "H:/recursos/audio/youtube/libre/falta/"; 

for (int i = 0; i < str.size(); i++) {
    if (str[i] == '/') {
        str[i] = '\\';
    }
}

std::cout << str;

结果:

H:\recursos\audio\youtube\libre\falta\

于 2018-05-20T19:55:36.853 回答
1

这是我以最大 DRI 精神推出的解决方案。它将在 sHaystack 中搜索 sNeedle 并将其替换为 sReplace,如果非 0,则为 nTimes,否则所有 sNeedle 出现。它不会在替换的文本中再次搜索。

std::string str_replace(
    std::string sHaystack, std::string sNeedle, std::string sReplace, 
    size_t nTimes=0)
{
    size_t found = 0, pos = 0, c = 0;
    size_t len = sNeedle.size();
    size_t replen = sReplace.size();
    std::string input(sHaystack);

    do {
        found = input.find(sNeedle, pos);
        if (found == std::string::npos) {
            break;
        }
        input.replace(found, len, sReplace);
        pos = found + replen;
        ++c;
    } while(!nTimes || c < nTimes);

    return input;
}
于 2020-04-01T23:42:52.577 回答
1

我想我会用std::replace_if()

可以使用标准库函数编写一个简单的字符替换器(由 OP 请求)。

对于就地版本:

#include <string>
#include <algorithm>

void replace_char(std::string& in,
                  std::string::value_type srch,
                  std::string::value_type repl)
{
    std::replace_if(std::begin(in), std::end(in),
                    [&srch](std::string::value_type v) { return v==srch; },
                    repl);
    return;
}

如果输入是const字符串,则返回副本的重载:

std::string replace_char(std::string const& in,
                         std::string::value_type srch,
                         std::string::value_type repl)
{
    std::string result{ in };
    replace_char(result, srch, repl);
    return result;
}
于 2021-09-14T10:35:16.193 回答
1

对于简单的情况,这在不使用任何其他库的情况下效果很好,然后 std::string (已经在使用)。

将some_string中所有出现的字符a替换为字符b

for (size_t i = 0; i < some_string.size(); ++i) {
    if (some_string[i] == 'a') {
        some_string.replace(i, 1, "b");
    }
}

如果字符串很大或多次调用替换是一个问题,您可以应用此答案中提到的技术:https ://stackoverflow.com/a/29752943/3622300

于 2018-01-29T12:46:21.540 回答
0

这行得通!我在书店应用程序中使用了与此类似的东西,其中库存存储在 CSV(如 .dat 文件)中。但是在单字符的情况下,意味着替换器只是单字符,例如'|',必须用双引号“|” 为了不抛出无效的转换 const char。

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int count = 0;  // for the number of occurences.
    // final hold variable of corrected word up to the npos=j
    string holdWord = "";
    // a temp var in order to replace 0 to new npos
    string holdTemp = "";
    // a csv for a an entry in a book store
    string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";

    // j = npos
    for (int j = 0; j < holdLetter.length(); j++) {

        if (holdLetter[j] == ',') {

            if ( count == 0 ) 
            {           
                holdWord = holdLetter.replace(j, 1, " | ");      
            }
            else {

                string holdTemp1 = holdLetter.replace(j, 1, " | ");

                // since replacement is three positions in length,
                // must replace new replacement's 0 to npos-3, with
                // the 0 to npos - 3 of the old replacement 
                holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3); 

                holdWord = "";

                holdWord = holdTemp;

            }
            holdTemp = "";
            count++;
        }
    } 
    cout << holdWord << endl;
    return 0;
}

// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85

我现在不习惯使用 CentOS,所以我的编译器版本低于 . C++版本(g++),C++98默认:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
于 2016-04-30T22:33:41.360 回答
0

这不是标准库中唯一缺少的方法,它本来是低级的。通用库涵盖了此用例和许多其他用例,例如:

QtCore & QString 有我的偏好:它支持 UTF8 并使用更少的模板,这意味着可以理解的错误和更快的编译。它使用“q”前缀,这使得命名空间变得不必要并简化了标题。
Boost 通常会产生可怕的错误消息和缓慢的编译时间。
POCO 似乎是一个合理的妥协。

于 2021-03-17T16:11:43.013 回答