Wie kann man alle Vorkommen eines Zeichens durch ein anderes Zeichen in std::string
?
Antworten
Zu viele Anzeigen?Die Frage konzentriert sich auf character
Ersatz, aber da ich diese Seite sehr nützlich fand (insbesondere Konrad Bemerkung), möchte ich diese verallgemeinerte Implementierung vorstellen, die es ermöglicht, mit substrings
auch:
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;
}
Uso:
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
EDITAR:
Das obige kann auf eine geeignetere Weise implementiert werden, falls Sie Wert auf Leistung legen, indem Sie nichts zurückgeben ( void
) und die Änderungen direkt an der Zeichenkette vornehmen str
als Argument angegeben, übergeben nach Adresse 代わりに nach Wert . Dies würde ein unnötiges und kostspieliges Kopieren der ursprünglichen Zeichenkette vermeiden, während das Ergebnis zurückgegeben wird. Ihr Aufruf, dann...
Code:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Ich hoffe, dass dies für einige andere hilfreich ist...
Ich dachte, ich werfe die Boost-Lösung auch:
#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, "#", "@");
Stellen Sie sich einen großen binären Blob vor, bei dem alle 0x00-Bytes durch "" ersetzt werden sollen. \1\x30 " und alle 0x01-Bytes durch " \1\x31 ", da das Transportprotokoll keine \0 -bytes.
In Fällen, in denen:
- die ersetzende und die zu ersetzende Zeichenfolge haben unterschiedliche Längen,
- die zu ersetzende Zeichenfolge in der Quellzeichenfolge mehrfach vorkommt und
- die Quellzeichenkette ist groß,
die angebotenen 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, was immer wieder Kopien der Größe des Blob erzeugt. (Ich kenne die boost-Lösung nicht, vielleicht ist sie aus dieser Perspektive OK)
Dieser geht alle Vorkommen in der Quellzeichenkette durch und baut die neue Zeichenkette Stück für Stück auf 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);
}
Ein einfaches Suchen und Ersetzen für ein einzelnes Zeichen würde etwa so aussehen:
s.replace(s.find("x"), 1, "y")
Um dies für die gesamte Zeichenkette zu tun, wäre es einfach, eine Schleife zu machen, bis Ihre s.find
beginnt zurückzukehren npos
. Ich nehme an, Sie könnten auch die range_error
um die Schleife zu verlassen, aber das ist irgendwie hässlich.
- See previous answers
- Weitere Antworten anzeigen