这是一个最小化分配和分配数量的代码。它基于以下对类似问题的回答:
https ://stackoverflow.com/a/32322122/3903076
替换字符串长度为 0 或 1 的情况分别处理。否则,字符串必须增长。
如果没有足够的容量,那么无论如何都需要一个外部缓冲区,所以我们只需进行复制替换和交换。
有趣的情况是当字符串已经有足够的容量时,我们实际上可以进行非平凡的就地替换。我们通过反向复制替换来做到这一点,当我们不需要替换任何其他内容时停止。
这可以在函数的最后一行看到。
void replaceChar(std::string& input, const std::string& replacementString, char charToReplace)
{
if (replacementString.empty()) {
input.erase(std::remove(input.begin(), input.end(), charToReplace), input.end());
return;
}
if (replacementString.size() == 1) {
std::replace(input.begin(), input.end(), charToReplace, replacementString.front());
return;
}
const auto first_instance = std::find(input.begin(), input.end(), charToReplace);
auto count = std::count(first_instance, input.end(), charToReplace);
const auto extra_size = count * (replacementString.size() - 1);
const auto new_size = input.size() + extra_size;
if (input.capacity() < new_size) {
std::string aux;
aux.reserve(new_size);
replace_with_range_copy(input.cbegin(), input.cend(), std::back_inserter(aux), charToReplace, replacementString.cbegin(), replacementString.cend());
input.swap(aux);
return;
}
input.resize(new_size);
const auto rlast = std::make_reverse_iterator(first_instance);
const auto rfirst = input.rbegin();
const auto old_rfirst = rfirst + extra_size;
replace_with_range_copy(old_rfirst, rlast, rfirst, charToReplace, replacementString.crbegin(), replacementString.crend());
}
下面是replace_with_range_copy
算法的实现:
template <typename InputIt1, typename OutputIt, typename T, typename InputIt2>
OutputIt replace_with_range_copy(InputIt1 first, InputIt1 last, OutputIt d_first, const T& old_value, InputIt2 new_first, InputIt2 new_last)
{
InputIt1 next;
while (true) {
if (first == last) return d_first;
next = std::find(first, last, old_value);
d_first = std::copy(first, next, d_first);
if (next == last) return d_first;
d_first = std::copy(new_first, new_last, d_first);
first = std::next(next);
}
}