Risposte:
std::string
non contiene tale funzione ma è possibile utilizzare la replace
funzione autonoma dall'intestazione algorithm
.
#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'
}
std::string::replace()
invece di std::replace()
! 'x' ( char
) viene implicitamente inserito in size_t
[valore 120], quindi l'intera stringa o parte di essa verrà riempita con 120 copie di 'y'.
Ho pensato di aggiungere anche la soluzione boost :
#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, "#", "@");
-I
flag per il tuo compilatore in modo che possa trovare le librerie Boost sul tuo sistema. Forse devi prima installarlo.
La domanda è centrata sulla character
sostituzione, ma, poiché ho trovato questa pagina molto utile (in particolare l'osservazione di Konrad ), vorrei condividere questa implementazione più generalizzata, che consente anche di affrontare 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;
}
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;
Uscite:
Number_Of_Beans
XXjXugtXty
hhjhugthty
MODIFICARE:
Quanto sopra può essere implementato in un modo più adatto, nel caso in cui le prestazioni siano di tuo interesse, restituendo nulla ( void
) ed eseguendo le modifiche direttamente sulla stringa str
fornita come argomento, passata per indirizzo anziché per valore . Ciò eviterebbe la copia inutile e costosa della stringa originale, restituendo il risultato. La tua chiamata, quindi ...
Codice :
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Spero che questo possa essere utile per alcuni altri ...
from
stringa è vuota, altrimenti si verificherà un ciclo infinito.
Immagina un grande BLOB binario in cui tutti gli 0x00 byte devono essere sostituiti da "\ 1 \ x30" e tutti gli 0x01 byte da "\ 1 \ x31" perché il protocollo di trasporto non consente \ 0 byte.
Nei casi in cui:
le soluzioni fornite non possono essere applicate (perché sostituiscono solo caratteri singoli) o hanno un problema di prestazioni, perché chiamerebbero string :: replace diverse volte che genera ripetutamente copie delle dimensioni del BLOB. (Non conosco la soluzione boost, forse è OK da quella prospettiva)
Questo cammina lungo tutte le occorrenze nella stringa sorgente e costruisce la nuova stringa pezzo per pezzo una volta :
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);
}
Una semplice ricerca e sostituzione per un singolo personaggio sarebbe simile a:
s.replace(s.find("x"), 1, "y")
Per fare questo per l'intera stringa, la cosa facile da fare sarebbe fare un ciclo fino a quando non s.find
inizi a tornare npos
. Suppongo che potresti anche prendere range_error
per uscire dal ciclo, ma è un po 'brutto.
{
personaggio. Non so cosa sia un "doppio tutore". Forse hai qualche tipo di problema con i caratteri?
Se stai cercando di sostituire più di un singolo carattere e hai a che fare solo con std::string
, allora questo snippet funzionerebbe, sostituendo sNeedle in sHaystack con sReplace, e sNeedle e sReplace non devono avere le stesse dimensioni. Questa routine utilizza il ciclo while per sostituire tutte le occorrenze, anziché solo la prima trovata da sinistra a destra.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
find
chiamata due volte. Considera di rendere quel risultato una variabile temporanea.
Come suggerito da Kirill, utilizzare il metodo di sostituzione o iterare lungo la stringa sostituendo ogni carattere in modo indipendente.
In alternativa puoi usare il find
metodo o in find_first_of
base a cosa devi fare. Nessuna di queste soluzioni farà il lavoro in una volta sola, ma con alcune righe di codice in più dovresti farle funzionare per te. :-)
#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;
}
word
è lungo, potrebbe esserci molto overhead durante la chiamata della funzione. È possibile ottimizzare questo passando word
, target
e replacement
come const riferimenti.
Che dire di Abseil StrReplaceAll ? Dal file di intestazione:
// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
Vecchia scuola :-)
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;
Risultato:
H: \ Recursos \ audio \ youtube \ libre \ falta \
Questo funziona! Ho usato qualcosa di simile a questo per un'app di libreria, in cui l'inventario è stato archiviato in un CSV (come un file .dat). Ma nel caso di un singolo carattere, il che significa che il sostituto è solo un singolo carattere, ad esempio '|', deve essere racchiuso tra virgolette "|" per non generare un carattere const di conversione non valido.
#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
Al momento non sto usando CentOS, quindi la mia versione del compilatore è sotto. La versione C ++ (g ++), impostazione predefinita C ++ 98:
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.
Se sei disposto a usare std::string
s, puoi usare la funzione di questa app di strsub
esempio così com'è o aggiornarla se vuoi che prenda un tipo o un set di parametri diversi per raggiungere approssimativamente lo stesso obiettivo. Fondamentalmente, utilizza le proprietà e le funzionalità di std::string
per cancellare rapidamente il set di caratteri corrispondente e inserire i caratteri desiderati direttamente all'interno di std::string
. Ogni volta che esegue questa operazione di sostituzione, l'offset si aggiorna se riesce ancora a trovare i caratteri corrispondenti da sostituire e, se non è più possibile sostituirlo, restituisce la stringa nel suo stato dall'ultimo aggiornamento.
#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;
}
Se non vuoi fare affidamento sull'uso di std::string
s come parametri in modo da poter invece passare stringhe in stile C, puoi vedere l'esempio aggiornato di seguito:
#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;
}
Per situazioni semplici questo funziona abbastanza bene senza usare altre librerie quindi std :: string (che è già in uso).
Sostituisci tutte le occorrenze del carattere a con il carattere 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");
}
}
Se la stringa è grande o più chiamate da sostituire è un problema, puoi applicare la tecnica menzionata in questa risposta: https://stackoverflow.com/a/29752943/3622300
ecco una soluzione che ho lanciato, in uno spirito DRI massimo. cercherà sNeedle in sHaystack e lo sostituirà con sReplace, nTimes se non 0, altrimenti tutte le occorrenze di sNeedle. non cercherà più nel testo sostituito.
std::string str_replace(
std::string sHaystack, std::string sNeedle, std::string sReplace,
size_t nTimes=0)
{
size_t found = 0, pos = 0, c = 0;
size_t len = sNeedle.size();
size_t replen = sReplace.size();
std::string input(sHaystack);
do {
found = input.find(sNeedle, pos);
if (found == std::string::npos) {
break;
}
input.replace(found, len, sReplace);
pos = found + replen;
++c;
} while(!nTimes || c < nTimes);
return input;
}
std::string
è un contenitore appositamente progettato per funzionare con sequenze di caratteri. link