什么是有效的方法来取代一个字符的所有出现与另一个字符在std::字符串?
当前回答
我想我会使用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;
}
其他回答
想象一个大的二进制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不包含这样的函数,但你可以使用独立的替换函数从算法头。
#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,这取决于您需要做什么。这些解决方案都不能一次性完成工作,但是通过几行额外的代码,您应该让它们为您工作。: -)
这不是标准库中缺少的唯一方法,它本来是低级别的。 这个用例和许多其他用例由通用库涵盖,例如:
波科 绳降 提高 QtCore
QtCore & QString有我的偏好:它支持UTF8,使用更少的模板,这意味着可以理解的错误和更快的编译。它使用了“q”前缀,使命名空间变得不必要,并简化了头文件。 Boost经常生成可怕的错误消息和缓慢的编译时间。 POCO似乎是一种合理的妥协。
这个问题集中在字符替换上,但是,我发现这个页面非常有用(尤其是Konrad的评论),我想分享这个更通用的实现,它也允许处理子字符串:
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)并执行“就地”更改;也就是说,通过直接修改字符串参数str,通过引用而不是值传递。这将通过覆盖原始字符串来避免额外的开销。
代码:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
希望这对其他人有所帮助…