Remplacer une partie d'une chaîne par une autre chaîne

est-il possible en C++ de remplacer une partie d'une chaîne par une autre chaîne?

en gros, je voudrais faire ceci:

QString string("hello $name");
string.replace("$name", "Somename");

mais je voudrais utiliser les bibliothèques C++ Standard.

149
demandé sur Peter Mortensen 2010-08-05 23:06:13

12 réponses

il y a une fonction pour trouver un substrat dans une chaîne ( find ), et une fonction pour remplacer une plage particulière dans une chaîne par une autre chaîne ( replace ), vous pouvez donc les combiner pour obtenir l'effet que vous voulez:

bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if(start_pos == std::string::npos)
        return false;
    str.replace(start_pos, from.length(), to);
    return true;
}

std::string string("hello $name");
replace(string, "$name", "Somename");

en réponse à un commentaire, je pense que replaceAll ressemblerait probablement à quelque chose comme ceci:

void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
        return;
    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(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}
238
répondu Michael Mrozek 2013-08-28 17:37:34

avec C++11 Vous pouvez utiliser std::regex comme suit:

    std::string string("hello $name");
    string = std::regex_replace(string, std::regex("\$name"), "Somename");

le double backslash est nécessaire pour échapper à un caractère de fuite.

57
répondu Tom 2015-07-25 13:24:54

std::string a une méthode replace , est-ce que c'est ce que vous cherchez?

Vous pouvez essayer:

s.replace(s.find("$name"), sizeof("Somename")-1, "Somename");

Je n'ai pas essayé moi-même, il suffit de lire la documentation sur find() et replace() .

15
répondu S.C. Madsen 2012-10-30 13:56:55

pour que la nouvelle chaîne soit retournée utilisez ceci:

std::string ReplaceString(std::string subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return subject;
}

si vous avez besoin de performances, voici une fonction optimisée qui modifie la chaîne de saisie, elle ne crée pas de copie de la chaîne:

void ReplaceStringInPlace(std::string& subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while ((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
}

Essais:

std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;

std::cout << "ReplaceString() return value: " 
          << ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: " 
          << input << std::endl;

ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;

sortie:

Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
7
répondu Czarek Tomczak 2013-02-26 01:19:19

Oui, vous pouvez le faire, mais vous devez trouver la position de la première chaîne avec le membre find() De string, et ensuite remplacer par son membre replace ().

string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
   s.replace( pos, 5, "somename" );   // 5 = length( $name )
}

si vous prévoyez d'utiliser la bibliothèque Standard, vous devriez vraiment obtenir une copie du livre la bibliothèque standard C++ qui couvre tous ces trucs très bien.

6
répondu Drew Noakes 2012-05-09 14:28:27

cela ressemble à une option

string.replace(string.find("%s"), string("%s").size(), "Something");

vous pouvez envelopper cela dans une fonction mais cette solution d'une ligne semble acceptable. Le problème est que cela va changer la première occurence, vous pouvez faire une boucle sur elle, mais il vous permet également d'insérer plusieurs variables dans cette chaîne avec le même jeton ( %s )

4
répondu maxoumime 2015-04-04 20:29:30

si toutes les chaînes sont std::string, vous trouverez des problèmes étranges avec la coupure des caractères si vous utilisez sizeof() parce que c'est destiné aux chaînes C, pas aux chaînes C++. Le correctif est d'utiliser la méthode de classe .size() de std::string .

sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);

Qui remplace sHaystack en ligne, pas besoin de faire une affectation = sur ce retour.

exemple d'usage:

std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;
3
répondu Volomike 2016-02-04 04:15:26
std::string replace(std::string base, const std::string from, const std::string to) {
    std::string SecureCopy = base;

    for (size_t start_pos = SecureCopy.find(from); start_pos != std::string::npos; start_pos = SecureCopy.find(from,start_pos))
    {
        SecureCopy.replace(start_pos, from.length(), to);
    }

    return SecureCopy;
}
2
répondu Lucas Civali 2014-04-17 14:08:03

j'utilise généralement ceci:

std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
            s.replace(pos, from.size(), to);
    return s;
}

il appelle à plusieurs reprises std::string::find() pour localiser d'autres occurrences de la chaîne recherchée jusqu'à ce que std::string::find() ne trouve rien. Parce que std::string::find() renvoie la position de la correspondance nous n'avons pas le problème d'invalider les itérateurs.

1
répondu Galik 2015-06-20 12:29:00

Si vous voulez le faire rapidement, vous pouvez utiliser une des deux scan approche. Pseudo code:

  1. première analyse. trouvez le nombre de caractères correspondant.
  2. étendre la longueur de la chaîne.
  3. deuxième analyse. Commencez à partir de la fin de la chaîne lorsque nous obtenons une correspondance que nous remplaçons, sinon nous copions simplement les caractères de la première chaîne.

Je ne suis pas sûr que cela puisse être optimisé pour une algo en place.

et un exemple de code C++11 mais je ne cherche qu'un seul char.

#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

void ReplaceString(string& subject, char search, const string& replace)
{   
    size_t initSize = subject.size();
    int count = 0;
    for (auto c : subject) { 
        if (c == search) ++count;
    }

    size_t idx = subject.size()-1 + count * replace.size()-1;
    subject.resize(idx + 1, '"151900920"');

    string reverseReplace{ replace };
    reverse(reverseReplace.begin(), reverseReplace.end());  

    char *end_ptr = &subject[initSize - 1];
    while (end_ptr >= &subject[0])
    {
        if (*end_ptr == search) {
            for (auto c : reverseReplace) {
                subject[idx - 1] = c;
                --idx;              
            }           
        }
        else {
            subject[idx - 1] = *end_ptr;
            --idx;
        }
        --end_ptr;
    }
}

int main()
{
    string s{ "Mr John Smith" };
    ReplaceString(s, ' ', "%20");
    cout << s << "\n";

}
1
répondu Damian 2016-07-13 11:38:52

je viens juste d'apprendre le C++, mais en éditant une partie du code précédemment posté, j'utiliserais probablement quelque chose comme ça. Cela vous donne la possibilité de remplacer 1 ou plusieurs instances, et vous permet également de spécifier le point de départ.

using namespace std;

// returns number of replacements made in string
long strReplace(string& str, const string& from, const string& to, size_t start = 0, long count = -1) {
    if (from.empty()) return 0;

    size_t startpos = str.find(from, start);
    long replaceCount = 0;

    while (startpos != string::npos){
        str.replace(startpos, from.length(), to);
        startpos += to.length();
        replaceCount++;

        if (count > 0 && replaceCount >= count) break;
        startpos = str.find(from, startpos);
    }

    return replaceCount;
}
0
répondu someprogrammer 2015-12-07 16:55:43
wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";
for (int i = myString.find(search); i >= 0; i = myString.find(search))
    myString.replace(i, search.size(), replace);
0
répondu user3016543 2016-01-27 16:37:45