Voici un code qui minimise le nombre d'affectations et d'allocations. Il est basé sur la réponse suivante à une question similaire: https://stackoverflow.com/a/32322122/3903076
Les cas où la chaîne de remplacement a la longueur 0 ou 1 sont traités séparément. Sinon, la chaîne doit grandir.
S'il n'y a pas assez de capacité, un tampon externe sera nécessaire de toute façon, donc nous ne faisons que copier-remplacer et échanger.
Le cas intéressant est quand la chaîne a déjà assez de capacité, ainsi nous pouvons réellement faire un remplacement in-situ non-trivial. Nous faisons cela avec une copie inverse-remplacer, en arrêtant quand nous n'avons pas besoin de remplacer quoi que ce soit d'autre.
Ceci peut être vu dans la dernière ligne de la fonction.
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());
}
Voici une implémentation de l'algorithme 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);
}
}
Où prévoyez-vous les personnages supplémentaires seront affectés? – AShelly
Ya thats ce que réellement je demande cela parce que j'ai vu une implémentation de code dans Java qui a calculé la nouvelle longueur de la chaîne et commence à placer des caractères de la fin au début. C'est pourquoi je me demande si java autorise ce type de changement de longueur de chaîne au moment de l'exécution ... – Madu
Il existe un moyen d'insérer une chaîne commençant une position particulière, en supprimant le caractère à cette position seulement mais cela augmentera la taille de tampon interne. – hmjd