Respuestas:
std::string
no contiene dicha función, pero podría usar la replace
función independiente del algorithm
encabezado.
#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()
lugar de std::replace()
! 'x' ( char
) se convierte implícitamente en size_t
[valor 120], por lo que toda la cadena o parte de ella se rellenará con 120 copias de 'y'.
Pensé en tirar el solución de impulso :
#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
indicadores para su compilador para que pueda encontrar las bibliotecas Boost en su sistema. Quizás necesite incluso instalarlo primero.
La pregunta se centra en el character
reemplazo, pero, como encontré esta página muy útil (especialmente el comentario de Konrad ), me gustaría compartir esta implementación más generalizada, que también permite tratar 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;
Salidas:
Number_Of_Beans
XXjXugtXty
hhjhugthty
EDITAR:
Lo anterior se puede implementar de una manera más adecuada, en caso de que el rendimiento sea de su interés, devolviendo nada ( void
) y realizando los cambios directamente en la cadena str
dada como argumento, pasado por dirección en lugar de por valor . Esto evitaría una copia inútil y costosa de la cadena original, al tiempo que 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 ...
from
cadena está vacía, de lo contrario se producirá un bucle sin fin.
Imagine un blob binario grande donde todos los 0x00 bytes serán reemplazados por "\ 1 \ x30" y todos los 0x01 bytes por "\ 1 \ x31" porque el protocolo de transporte no permite \ 0-bytes.
En casos donde:
las soluciones proporcionadas no pueden aplicarse (porque reemplazan solo caracteres individuales) o tienen un problema de rendimiento, porque llamarían a string :: replace varias veces, lo que genera copias del tamaño del blob una y otra vez. (No conozco la solución de impulso, tal vez esté bien desde esa perspectiva)
Éste recorre todas las ocurrencias en la cadena de origen y construye la nueva cadena 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 buscar y reemplazar 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 s.find
comience a regresar npos
. Supongo que también podrías atraparlo range_error
para salir del bucle, pero eso es un poco feo.
{
personaje. No sé qué es un "doble corsé". Tal vez tienes algún tipo de problema de fuente?
Si está buscando reemplazar más de un solo personaje, y está tratando solo con std::string
, entonces 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);
}
find
llamada dos veces. Considere hacer de ese resultado una variable temporal.
Como sugirió Kirill, use el método de reemplazo o itere a lo largo de la cadena reemplazando cada carácter de forma independiente.
Alternativamente, puede usar el find
método 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. :-)
#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
es largo, puede haber mucha sobrecarga al llamar a la función. Puede optimizar esta pasando word
, target
y replacement
como const referencias.
¿Qué pasa con Abseil StrReplaceAll ? Desde el archivo de encabezado:
// 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, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
Vieja escuela :-)
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;
Resultado:
H: \ recursos \ audio \ youtube \ libre \ falta \
¡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 solo 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 <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
De manera poco habitual, estoy usando CentOS actualmente, por lo que mi versión del compilador está a continuación. La versión C ++ (g ++), C ++ 98 predeterminada:
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 de esta aplicación de muestra strsub
tal cual o actualizarla si desea que tome un tipo diferente o un conjunto de parámetros para lograr aproximadamente el mismo objetivo. Básicamente, utiliza las propiedades y funcionalidades de std::string
para borrar rápidamente el conjunto de caracteres coincidentes e insertar los caracteres deseados directamente dentro del std::string
. Cada vez que realiza esta operación de reemplazo, el desplazamiento se actualiza si aún puede encontrar caracteres coincidentes para reemplazar, y si no puede debido a nada más para reemplazar, devuelve la cadena en su estado desde la última actualización.
#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;
}
Si no desea confiar en usar std::string
s como sus parámetros para poder pasar cadenas de estilo C en su lugar, puede ver la muestra actualizada a continuación:
#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;
}
Para situaciones simples, esto funciona bastante bien sin usar ninguna otra biblioteca que luego std :: string (que ya está en uso).
Reemplace todas las ocurrencias del carácter a con el carácter b en alguna_cadena :
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 varias llamadas para reemplazar es un problema, puede aplicar la técnica mencionada en esta respuesta: https://stackoverflow.com/a/29752943/3622300
Aquí hay una solución que hice, en un espíritu DRI máximo. buscará sNeedle en sHaystack y lo reemplazará por sReplace, nTimes si no es 0, de lo contrario, todas las ocurrencias de sNeedle. no buscará nuevamente en el texto reemplazado.
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
es un contenedor específicamente diseñado para operar con secuencias de caracteres. enlace