什么是有效的方法来取代一个字符的所有出现与另一个字符在std::字符串?


当前回答

这是我滚动的一个解决方案,在最大的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;
}

其他回答

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

波科 绳降 提高 QtCore

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

为了完整起见,下面是如何使用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");
}

想象一个大的二进制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);
}

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

我想我也会加入促进方案:

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