@poly Creo que también se debe haber pedido C ++, pero no puedo encontrarlo
Michael Mrozek
1
Hay una etiqueta estándar en la pregunta, pero tal vez le interesen los algoritmos de cadena de boost, que también incluyen una amplia variedad de algoritmos de reemplazo (in situ / copia, mayúsculas y minúsculas, mayúsculas / minúsculas / n-ésima )
Hay una función para encontrar una subcadena dentro de una cadena ( find), y una función para reemplazar un rango particular en una cadena con otra cadena ( replace), para que pueda combinarlas para obtener el efecto que desea:
¿Cómo lo arreglaría si la cadena original tuviera más de una instancia de "$ name" y quisiera reemplazarlos a todos?
Tom Leese
1
¿Por qué no se pasan fromy se topasan por constreferencia? ¿Cuál es su función si fromno está allí? -1de mi parte por eso.
sbi
10
@sbi Fixed, aunque podría haberlo redactado como recomendaciones en lugar de ataques: simplemente no se me ocurrió, rara vez pienso en usarlo consty si escribiera un método de utilidad como este solo lo llamaría si supiera el reemplazo eran válidas
Michael Mrozek
10
@Michael: Bien, convertí mi voto negativo en un voto positivo. Descartar constes ignorar una de las mejores herramientas de C ++. El paso por constreferencia debe ser el modo predeterminado para los parámetros de función. (FTR, sin el const, que ni siquiera podía pasar literales de cadena a su función, porque no se pueden temporales se unen a los no constreferencias Así la función ni siquiera hacer lo que fue escrito para..)
SBI
19
¿Sigue siendo la única solución en 2018? Si es así y algún comité de C ++ está leyendo esto, resuélvelo. Es vergonzoso. dividir (cadena, cadena) y reemplazar (cadena, cadena) por favor!
Estoy bastante seguro de std::regex_replaceque no acepta la cadena de Qt.
BartoszKP
1
Tienes razón. A medida que sucede, QString proporciona un método de reemplazo que acepta un QRexExp, lo que permite utilizar las propias cosas de Qt. Pero creo que la respuesta actual podría corregirse reemplazando stringcon string.toStdString().
Tom
1
O simplemente cambiando Stringa std::string, porque la pregunta no está relacionada con Qt. Por favor considere hacer eso. Con mucho gusto votaré su respuesta después.
BartoszKP
55
La cadena sin procesar permite escribir en R"(\$name)"lugar de "\\$name".
Jarod42
2
¿Cuánto será más lento que buscar / reemplazar sin considerar el tiempo de construcción de std :: regex?
jw_
18
std::stringtiene un replacemétodo, ¿es eso lo que estás buscando?
Su llamada a subject.replace en ReplaceStringInPlace () ¿realmente modifica la cadena en el lugar?
Damian
Miré brevemente la fuente y parece que usa la semántica de movimiento para mover el frente de la cadena vieja a su lugar, de modo que no se copie, pero la nueva pieza insertada se copia en la cadena vieja y la cola de la cadena vieja se copia en el búfer redimensionado de la cadena anterior. Es posible que la cadena se expanda tanto que todo el búfer subyacente se reasigne, pero si reemplaza 1 a 1 como en su ejemplo, creo que ocurre "en su lugar", o sin ninguna copia, pero si expande la cadena, solo la primera parte de la cadena anterior no se copia, y tal vez solo entonces.
Motes
6
Sí, puede hacerlo, pero debe encontrar la posición de la primera cadena con el miembro find () de la cadena y luego reemplazarla con su miembro replace ().
Llama repetidamente std::string::find()para localizar otras ocurrencias de la cadena buscada hasta std::string::find()que no encuentra nada. Porque std::string::find()devuelve el posición de la coincidencia, no tenemos el problema de invalidar iteradores.
Podría envolver esto en una función, pero esta solución de una línea parece aceptable. El problema es que esto solo cambiará la primera ocurrencia, es posible que desee recorrerlo, pero también le permite insertar varias variables en esta cadena con el mismo token ( %s)
Me gusta el estilo pero las diferentes cadenas me parecen confusas ^^str.replace(str.find("%s"), string("%s").size(), "Something");
Paul Würtz
3
Si todas las cadenas son std :: string, encontrará problemas extraños con el corte de caracteres si se usa sizeof()porque está destinado a cadenas C, no a cadenas C ++. La solución es usar el .size()método de clase de std::string.
wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";for(int i = myString.find(search); i >=0; i = myString.find(search))
myString.replace(i, search.size(), replace);
Si desea hacerlo rápidamente, puede usar un enfoque de dos escaneos. Pseudocódigo:
primer análisis encuentra cuántos caracteres coinciden.
expande la longitud de la cuerda.
segundo análisis Comience desde el final de la cadena cuando obtengamos una coincidencia que reemplazamos, de lo contrario, simplemente copiamos los caracteres de la primera cadena.
No estoy seguro de si esto puede optimizarse para algo en el lugar.
Y un ejemplo de código C ++ 11 pero solo busco un carácter.
Ahora estoy aprendiendo C ++, pero editando parte del código publicado anteriormente, probablemente usaría algo como esto. Esto le brinda la flexibilidad de reemplazar 1 o varias instancias, y también le permite especificar el punto de inicio.
Respuestas:
Hay una función para encontrar una subcadena dentro de una cadena (
find
), y una función para reemplazar un rango particular en una cadena con otra cadena (replace
), para que pueda combinarlas para obtener el efecto que desea:En respuesta a un comentario, creo
replaceAll
que probablemente se vería así:fuente
from
y seto
pasan porconst
referencia? ¿Cuál es su función sifrom
no está allí?-1
de mi parte por eso.const
y si escribiera un método de utilidad como este solo lo llamaría si supiera el reemplazo eran válidasconst
es ignorar una de las mejores herramientas de C ++. El paso porconst
referencia debe ser el modo predeterminado para los parámetros de función. (FTR, sin elconst
, que ni siquiera podía pasar literales de cadena a su función, porque no se pueden temporales se unen a los noconst
referencias Así la función ni siquiera hacer lo que fue escrito para..)Con C ++ 11 puede usar
std::regex
así:La barra invertida doble es necesaria para escapar de un personaje de escape.
fuente
std::regex_replace
que no acepta la cadena de Qt.string
constring.toStdString()
.String
astd::string
, porque la pregunta no está relacionada con Qt. Por favor considere hacer eso. Con mucho gusto votaré su respuesta después.R"(\$name)"
lugar de"\\$name"
.std::string
tiene unreplace
método, ¿es eso lo que estás buscando?Tu podrías intentar:
No lo he probado yo mismo, solo leí la documentación en
find()
yreplace()
.fuente
Para que se devuelva la nueva cadena, use esto:
Si necesita rendimiento, aquí hay una función optimizada que modifica la cadena de entrada, no crea una copia de la cadena:
Pruebas:
Salida:
fuente
Sí, puede hacerlo, pero debe encontrar la posición de la primera cadena con el miembro find () de la cadena y luego reemplazarla con su miembro replace ().
Si está planeando usar la Biblioteca estándar, debería obtener una copia del libro La biblioteca estándar de C ++ que cubre todo esto muy bien.
fuente
Generalmente uso esto:
Llama repetidamente
std::string::find()
para localizar otras ocurrencias de la cadena buscada hastastd::string::find()
que no encuentra nada. Porquestd::string::find()
devuelve el posición de la coincidencia, no tenemos el problema de invalidar iteradores.fuente
Esto suena como una opción
string.replace(string.find("%s"), string("%s").size(), "Something");
Podría envolver esto en una función, pero esta solución de una línea parece aceptable. El problema es que esto solo cambiará la primera ocurrencia, es posible que desee recorrerlo, pero también le permite insertar varias variables en esta cadena con el mismo token (
%s
)fuente
str.replace(str.find("%s"), string("%s").size(), "Something");
Si todas las cadenas son std :: string, encontrará problemas extraños con el corte de caracteres si se usa
sizeof()
porque está destinado a cadenas C, no a cadenas C ++. La solución es usar el.size()
método de clase destd::string
.Eso reemplaza a sHaystack en línea: no es necesario hacer una asignación = de nuevo en eso.
Ejemplo de uso:
fuente
fuente
Si desea hacerlo rápidamente, puede usar un enfoque de dos escaneos. Pseudocódigo:
No estoy seguro de si esto puede optimizarse para algo en el lugar.
Y un ejemplo de código C ++ 11 pero solo busco un carácter.
fuente
fuente
Mi propia implementación, teniendo en cuenta que la cadena debe redimensionarse solo una vez, luego puede reemplazarse.
El uso podría ser, por ejemplo, así:
fuente
Ahora estoy aprendiendo C ++, pero editando parte del código publicado anteriormente, probablemente usaría algo como esto. Esto le brinda la flexibilidad de reemplazar 1 o varias instancias, y también le permite especificar el punto de inicio.
fuente
Esto podría ser incluso mejor usar
fuente