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

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

672380 次浏览

std::string不包含这样的函数,但您可以使用algorithm头中的独立replace函数。

#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'
}

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

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

一个简单的查找和替换单个字符是这样的:

# EYZ0

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

我想我也要扔提升解决方案:

#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, "#", "@");

问题集中在character替换上,但是,因为我发现这个页面非常有用(尤其是康拉德的注释),我想分享这个更通用的实现,它也可以处理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

hhjhugthty


编辑:

如果您关心性能,则可以通过不返回任何内容(void)并执行更改"in-place";;也就是说,通过直接修改字符串参数str,传递by reference,而不是by value。这将通过覆盖原始字符串来避免额外的开销。

代码:

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

希望这对其他人有所帮助…

#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;
}

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

在以下情况下:

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

提供的解决方案不能应用(因为它们只替换单个字符)或有性能问题,因为它们会多次调用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);
}

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

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

这个工作!我在书店应用程序中使用了类似的方法,其中库存存储在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.

对于简单的情况,无需使用任何其他库就可以很好地工作,然后使用std::string(已经在使用)。

一个字符替换为some_string中的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

老派:-)

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: \ recurso项目\音响\ \自由\ falta \ youtube

下降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;"}});

这是我滚动的一个解决方案,在最大的DRI精神。 它将在sHaystack中搜索sNeedle并将其替换为sReplace, nTimes如果不为0,否则所有的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;
}

为了完整起见,下面是如何使用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");
}
这不是标准库中唯一缺少的方法,它是低级别的。 这个用例和许多其他用例由通用库涵盖,例如:

  • POCO
  • < a href = " https://abseil。io/docs/cpp/guides/strings" rel="nofollow noreferrer">Abseil .
  • Boost
  • QtCore
< p > QtCore,QString有我的偏好:它支持UTF8,使用更少的模板,这意味着可以理解的错误和更快的编译。它使用&;q"前缀,使名称空间变得不必要,并简化了头部。
Boost经常生成可怕的错误消息和缓慢的编译时间。
POCO似乎是一个合理的妥协

我想我会用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;
}

如何替换任何字符串与任何字符串仅使用良好的旧C字符串函数?

char original[256]="First Line\nNext Line\n", dest[256]="";
char* replace_this = "\n"; // this is now a single character but could be any string
char* with_this = "\r\n"; // this is 2 characters but could be of any length


/* get the first token */
char* token = strtok(original, replace_this);


/* walk through other tokens */
while (token != NULL) {
strcat(dest, token);
strcat(dest, with_this);
token = strtok(NULL, replace_this);
}

dest现在应该有我们正在寻找的东西。