it-swarm.com.de

Wie ersetze ich alle Vorkommen eines Zeichens in einem String?

Was ist der effektive Weg, um alle Vorkommen eines Zeichens durch ein anderes Zeichen in std::string zu ersetzen?

439
big-z

std::string enthält keine solche Funktion, Sie können jedoch die eigenständige Funktion replace aus dem Header algorithm verwenden.

#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'
}
673

Ich dachte, ich würde auch Boost-Lösung einwerfen:

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

Die Frage konzentriert sich auf die Ersetzung von character, aber da ich diese Seite sehr nützlich fand (insbesondere die Bemerkung von Konrad ), möchte ich diese verallgemeinerte Implementierung, die es erlaubt, mit Ihnen teilen beschäftige dich auch mit substrings:

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

Verwendungszweck:

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;

Ausgänge:

Anzahl_der_Bohnen

XXjXugtXty

hhjhugthty


EDIT:

Das oben Genannte kann in geeigneterer Weise implementiert werden, wenn Sie Probleme mit den Leistungen haben, indem Sie nichts zurückgeben (void) und die Änderungen direkt an der angegebenen Zeichenfolge str vornehmen als Argument, übergeben von Adresse anstelle von von Wert . Dies würde unnötige und kostspielige Kopien der Originalzeichenfolge vermeiden und gleichzeitig das Ergebnis zurückgeben. Ihr Anruf, dann ...

Code:

static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
    // Same inner code...
    // No return statement
}

Hoffe, dass dies für einige andere hilfreich sein wird ...

110

Stellen Sie sich einen großen binären Blob vor, bei dem alle 0x00-Bytes durch "\ 1\x30" und alle 0x01-Bytes durch "\ 1\x31" ersetzt werden sollen, da das Transportprotokoll keine\0-Bytes zulässt.

In Fällen, in denen:

  • die ersetzende und die zu ersetzende Zeichenfolge haben unterschiedliche Längen.
  • es gibt viele Vorkommen der zu ersetzenden Zeichenfolge innerhalb der Quellzeichenfolge und
  • die Quellzeichenfolge ist groß,

die bereitgestellten Lösungen können nicht angewendet werden (weil sie nur einzelne Zeichen ersetzen) oder haben ein Leistungsproblem, weil sie string :: replace mehrmals aufrufen würden, wodurch immer wieder Kopien der Größe des Blobs generiert werden. (Ich kenne die Boost-Lösung nicht, vielleicht ist es aus dieser Perspektive in Ordnung)

Dieser geht alle Vorkommen in der Quellzeichenfolge durch und erstellt die neue Zeichenfolge Stück für Stück einmal:

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);
}
28
minastaros

Ein einfaches Suchen und Ersetzen für ein einzelnes Zeichen würde ungefähr so ​​aussehen:

s.replace(s.find("x"), 1, "y")

Um dies für die gesamte Zeichenfolge zu tun, ist es einfach, eine Schleife auszuführen, bis Ihr s.find anfängt, npos zurückzugeben. Ich nehme an, Sie könnten auch range_error fangen, um die Schleife zu verlassen, aber das ist irgendwie hässlich.

20
T.E.D.

Wenn Sie mehr als ein einzelnes Zeichen ersetzen möchten und nur mit std::string arbeiten, funktioniert dieses Snippet. Ersetzen Sie sNeedle in sHaystack durch sReplace, und sNeedle und sReplace müssen nicht dieselbe Größe haben. Diese Routine verwendet die while-Schleife, um alle Vorkommen zu ersetzen, und nicht nur die erste, die von links nach rechts gefunden wurde.

while(sHaystack.find(sNeedle) != std::string::npos) {
  sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
6
Volomike

Wie von Kirill vorgeschlagen, verwenden Sie entweder die Ersetzungsmethode oder iterieren Sie entlang der Zeichenfolge, wobei Sie jedes Zeichen unabhängig voneinander ersetzen.

Alternativ können Sie die Methode find oder find_first_of verwenden, je nachdem, was Sie tun müssen. Keine dieser Lösungen erledigt die Aufgabe auf einmal, aber mit ein paar zusätzlichen Codezeilen sollten Sie dafür sorgen, dass sie für Sie funktionieren. :-)

4
Konrad
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string Word, string target, string replacement){
    int len, loop=0;
    string nword="", let;
    len=Word.length();
    len--;
    while(loop<=len){
        let=Word.substr(loop, 1);
        if(let==target){
            nword=nword+replacement;
        }else{
            nword=nword+let;
        }
        loop++;
    }
    return nword;

}
//Main..
int main() {
  string Word;
  cout<<"Enter Word: ";
  cin>>Word;
  cout<<replace(Word, "x", "y")<<endl;
  return 0;
}
3
Lloydie

In einfachen Situationen funktioniert dies ziemlich gut, ohne eine andere Bibliothek als std :: string (die bereits verwendet wird) zu verwenden.

Ersetzen Sie alle Vorkommen des Zeichens a durch das Zeichen b in some_string :

for (size_t i = 0; i < some_string.size(); ++i) {
    if (some_string[i] == 'a') {
        some_string.replace(i, 1, "b");
    }
}

Wenn die Zeichenfolge groß ist oder mehrere Aufrufe zum Ersetzen ein Problem darstellen, können Sie die in dieser Antwort erwähnte Technik anwenden: https://stackoverflow.com/a/29752943/36223

0
Guney Ozsan

Wenn Sie bereit sind, std::strings zu verwenden, können Sie die strsub -Funktion dieser Beispiel-App unverändert verwenden oder sie aktualisieren, wenn Sie möchten, dass sie einen anderen Typ oder Parametersatz annimmt, um ungefähr das zu erreichen gleiches Ziel. Grundsätzlich werden die Eigenschaften und Funktionen von std::string verwendet, um den entsprechenden Zeichensatz schnell zu löschen und die gewünschten Zeichen direkt in std::string einzufügen. Jedes Mal, wenn dieser Ersetzungsvorgang ausgeführt wird, wird der Offset aktualisiert, wenn immer noch übereinstimmende Zeichen zum Ersetzen gefunden werden. Wenn keine weiteren Zeichen ersetzt werden müssen, wird die Zeichenfolge in ihrem Status aus der letzten Aktualisierung zurückgegeben.

#include <iostream>
#include <string>

std::string strsub(std::string stringToModify,
                   std::string charsToReplace,
                   std::string replacementChars);

int main()
{
    std::string silly_typos = "annoiiyyyng syyyllii tiipos.";

    std::cout << "Look at these " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos, "yyy", "i");
    std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos, "ii", "y");

    std::cout << "There, no more " << silly_typos << std::endl;
    return 0;
}

std::string strsub(std::string stringToModify,
                   std::string charsToReplace,
                   std::string replacementChars)
{
    std::string this_string = stringToModify;

    std::size_t this_occurrence = this_string.find(charsToReplace);
    while (this_occurrence != std::string::npos)
    {
        this_string.erase(this_occurrence, charsToReplace.size());
        this_string.insert(this_occurrence, replacementChars);
        this_occurrence = this_string.find(charsToReplace,
                                           this_occurrence + replacementChars.size());
    }

    return this_string;
}

Wenn Sie sich nicht darauf verlassen möchten, std::strings als Parameter zu verwenden, damit Sie stattdessen Zeichenfolgen im C-Stil übergeben können, sehen Sie das aktualisierte Beispiel unten:

#include <iostream>
#include <string>

std::string strsub(const char * stringToModify,
                   const char * charsToReplace,
                   const char * replacementChars,
                   uint64_t sizeOfCharsToReplace,
                   uint64_t sizeOfReplacementChars);

int main()
{
    std::string silly_typos = "annoiiyyyng syyyllii tiipos.";

    std::cout << "Look at these " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos.c_str(), "yyy", "i", 3, 1);
    std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
    silly_typos = strsub(silly_typos.c_str(), "ii", "y", 2, 1);

    std::cout << "There, no more " << silly_typos << std::endl;
    return 0;
}

std::string strsub(const char * stringToModify,
                   const char * charsToReplace,
                   const char * replacementChars,
                   uint64_t sizeOfCharsToReplace,
                   uint64_t sizeOfReplacementChars)
{
    std::string this_string = stringToModify;

    std::size_t this_occurrence = this_string.find(charsToReplace);
    while (this_occurrence != std::string::npos)
    {
        this_string.erase(this_occurrence, sizeOfCharsToReplace);
        this_string.insert(this_occurrence, replacementChars);
        this_occurrence = this_string.find(charsToReplace,
            this_occurrence + sizeOfReplacementChars);
    }

    return this_string;
}
0

Alte Schule :-)

std::string str = "H:/recursos/audio/youtube/libre/falta/"; 

for (int i = 0; i < str.size(); i++) {
    if (str[i] == '/') {
        str[i] = '\\';
    }
}

std::cout << str;

Ergebnis:

H:\recursos\audio\youtube\libre\falta \

0

Das funktioniert! Ich habe etwas Ähnliches für eine Buchhandlungs-App verwendet, in der das Inventar in einer CSV-Datei (wie einer DAT-Datei) gespeichert war. Aber im Fall eines einzelnen Zeichens, was bedeutet, dass der Ersetzer nur ein einzelnes Zeichen ist, z. B. '|', muss es in doppelten Anführungszeichen "|" stehen. um keine ungültige Konvertierung zu werfen const char.

#include <iostream>
#include <string>

using namespace std;

int main()
{
    int count = 0;  // for the number of occurences.
    // final hold variable of corrected Word up to the npos=j
    string holdWord = "";
    // a temp var in order to replace 0 to new npos
    string holdTemp = "";
    // a csv for a an entry in a book store
    string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";

    // j = npos
    for (int j = 0; j < holdLetter.length(); j++) {

        if (holdLetter[j] == ',') {

            if ( count == 0 ) 
            {           
                holdWord = holdLetter.replace(j, 1, " | ");      
            }
            else {

                string holdTemp1 = holdLetter.replace(j, 1, " | ");

                // since replacement is three positions in length,
                // must replace new replacement's 0 to npos-3, with
                // the 0 to npos - 3 of the old replacement 
                holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3); 

                holdWord = "";

                holdWord = holdTemp;

            }
            holdTemp = "";
            count++;
        }
    } 
    cout << holdWord << endl;
    return 0;
}

// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85

Ungewöhnlich verwende ich derzeit CentOS, daher ist meine Compiler-Version unten aufgeführt. Die C++ Version (g ++), C++ 98 Standard:

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0
oOpSgEo