¿Cómo reemplazar todas las apariciones de un personaje en una cadena?

¿Cuál es la forma efectiva de reemplazar todas las apariciones de un personaje con otro en std::string ?

std::string no contiene dicha función, pero puede usar la función de replace independiente del encabezado del algorithm .

 #include  #include  void some_func() { std::string s = "example string"; std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y' } 

Pensé que lanzaría la solución de impulso también:

 #include  // 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, "#", "@"); 

La pregunta se centra en el reemplazo de character , pero, como encontré esta página muy útil (especialmente la observación de Konrad ), me gustaría compartir esta implementación más generalizada, que también permite tratar las 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; 

Productos:

Number_Of_Beans

XXjXugtXty

hhjhugthty


EDITAR:

Lo anterior se puede implementar de una manera más adecuada, en caso de que las actuaciones sean de su interés, devolviendo nada ( void ) y realizando los cambios directamente en la cadena str dada como argumento, pasada por dirección en lugar de por valor . Esto evitaría una copia inútil y costosa de la cadena original, mientras devuelve el resultado. Tu llamada, entonces ...

Código:

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

Espero que esto sea útil para otros ...

Imagina un gran blob binario donde todos los octetos 0x00 se sustituirán por “\ 1 \ x30” y todos los bytes 0x01 por “\ 1 \ x31” porque el protocolo de transporte no permite \ 0-bytes.

En casos donde:

  • la cadena de reemplazo y la cadena reemplazada tienen longitudes diferentes,
  • hay muchas ocurrencias de la cadena reemplazada en la cadena fuente y
  • la cadena fuente es grande,

las soluciones proporcionadas no se pueden aplicar (porque reemplazan solo caracteres individuales) o tienen un problema de rendimiento, ya que llamarían a string :: replace varias veces, lo que genera copias del tamaño del blob una y otra vez. (No sé la solución de impulso, tal vez está bien desde esa perspectiva)

Éste recorre todas las ocurrencias en la cadena fuente y construye la nueva cuerda pieza por pieza una vez :

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

Un simple hallazgo y reemplazo para un solo personaje sería algo así como:

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

Para hacer esto para toda la cadena, lo más fácil sería hacer un bucle hasta que su s.find inicie regresando npos . Supongo que también range_error coger range_error para salir del loop, pero eso es feo.

Como Kirill sugirió, use el método de reemplazo o itere a lo largo de la cadena reemplazando cada char de forma independiente.

Alternativamente, puede usar el método find o find_first_of dependiendo de lo que necesite hacer. Ninguna de estas soluciones hará el trabajo de una vez, pero con unas pocas líneas adicionales de código, debe hacer que funcionen para usted. 🙂

Si está buscando reemplazar más de un solo caracter, y solo trata con std::string , este fragmento funcionaría, reemplazando sNeedle en sHaystack con sReplace, y sNeedle y sReplace no necesitan ser del mismo tamaño. Esta rutina usa el ciclo while para reemplazar todas las ocurrencias, en lugar de solo la primera que se encuentra de izquierda a derecha.

 while(sHaystack.find(sNeedle) != std::string::npos) { sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace); } 
 #include  #include  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<  

¡Esto funciona! Usé algo similar a esto para una aplicación de librería, donde el inventario se almacenaba en un archivo CSV (como un archivo .dat). Pero en el caso de un único carácter, lo que significa que el sustituto es solo un carácter, por ejemplo, ‘|’, debe estar entre comillas dobles “|” para no lanzar una conversión inválida const char.

 #include  #include  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 

Por costumbre, estoy usando CentOS actualmente, así que mi versión del comstackdor está debajo. La versión de C ++ (g ++), C ++ 98 por defecto:

 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. 

Si está dispuesto a usar std::string s, puede usar la función strsub esta aplicación de strsub tal como está o actualizarla si desea que tome un tipo o conjunto de parámetros diferente para lograr aproximadamente el mismo objective. Básicamente, utiliza las propiedades y funcionalidades de std::string para borrar rápidamente el conjunto de caracteres correspondiente e insertar los caracteres deseados directamente dentro de std::string . Cada vez que realiza esta operación de reemplazo, el desplazamiento se actualiza si todavía puede encontrar caracteres coincidentes para reemplazar, y si no puede reemplazarse por nada más, devuelve la cadena en su estado desde la última actualización.

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

Si no quiere confiar en el uso de std::string s como sus parámetros para que pueda pasar cadenas tipo C en su lugar, puede ver el ejemplo actualizado a continuación:

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

Para situaciones simples, esto funciona bastante bien sin usar ninguna otra biblioteca, luego std :: string (que ya está en uso).

Reemplaza todas las ocurrencias del carácter a con el carácter b en some_string :

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

Si la cadena es grande o hay varias llamadas para reemplazar, puede aplicar la técnica mencionada en esta respuesta: https://stackoverflow.com/a/29752943/3622300

Vieja escuela 🙂

  string pth = "H:/recursos/audio/youtube/libre/falta/"; for(int i=0 ;i< =pth.size(); i++) if(pth[i]=='/') pth[i]='\\'; cout< 

Resultado: "H: \ recursos \ audio \ youtube \ libre \ falta \";