c++ - violin - Reemplazar parte de una cuerda con otra cuerda
que hilo se usa para yoyo (12)
¿Es posible en C ++ reemplazar parte de una cadena con otra cadena?
Básicamente, me gustaría hacer esto:
QString string("hello $name");
string.replace("$name", "Somename");
Pero me gustaría utilizar las bibliotecas Standard C ++.
Ahora mismo estoy aprendiendo C ++, pero editando parte del código publicado anteriormente, probablemente usaría algo como esto. Esto le da la flexibilidad de reemplazar 1 o varias instancias, y también le permite especificar el punto de inicio.
using namespace std;
// returns number of replacements made in string
long strReplace(string& str, const string& from, const string& to, size_t start = 0, long count = -1) {
if (from.empty()) return 0;
size_t startpos = str.find(from, start);
long replaceCount = 0;
while (startpos != string::npos){
str.replace(startpos, from.length(), to);
startpos += to.length();
replaceCount++;
if (count > 0 && replaceCount >= count) break;
startpos = str.find(from, startpos);
}
return replaceCount;
}
Con C ++ 11 puede usar std::regex
manera:
std::string string("hello $name");
string = std::regex_replace(string, std::regex("//$name"), "Somename");
La doble barra diagonal inversa es necesaria para escapar de un carácter de escape.
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 cambiará la primera ocurrencia solamente, es posible que desee recorrerlo, pero también le permite insertar varias variables en esta cadena con el mismo token ( %s
)
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:
bool replace(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = str.find(from);
if(start_pos == std::string::npos)
return false;
str.replace(start_pos, from.length(), to);
return true;
}
std::string string("hello $name");
replace(string, "$name", "Somename");
En respuesta a un comentario, creo que replaceAll
probablemente se vería así:
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
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(); // In case ''to'' contains ''from'', like replacing ''x'' with ''yx''
}
}
Para tener la nueva cadena devuelta use esto:
std::string ReplaceString(std::string subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
Si necesita rendimiento, aquí hay una función optimizada que modifica la cadena de entrada, no crea una copia de la cadena:
void ReplaceStringInPlace(std::string& subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
}
Pruebas:
std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;
std::cout << "ReplaceString() return value: "
<< ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not modified: "
<< input << std::endl;
ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: "
<< input << std::endl;
Salida:
Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
Sí, puedes hacerlo, pero debes encontrar la posición de la primera cadena con el miembro find () de string y luego reemplazarlo con su miembro replace ().
string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
s.replace( pos, 5, "somename" ); // 5 = length( $name )
}
Si planea utilizar la Biblioteca estándar, debería obtener una copia del libro La biblioteca estándar de C ++ que cubre todo esto muy bien.
Si desea hacerlo rápidamente, puede usar un enfoque de dos escaneos. Pseudo código:
- primer análisis. encuentre cuántos caracteres coincidentes.
- expanda la longitud de la cuerda.
- segundo análisis. Comienza desde el final de la cadena cuando obtenemos una coincidencia que reemplazamos, de lo contrario solo copiamos los caracteres de la primera cadena.
No estoy seguro de si esto puede ser optimizado para algo in situ.
Y un ejemplo de código C ++ 11 pero solo busco un char.
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
void ReplaceString(string& subject, char search, const string& replace)
{
size_t initSize = subject.size();
int count = 0;
for (auto c : subject) {
if (c == search) ++count;
}
size_t idx = subject.size()-1 + count * replace.size()-1;
subject.resize(idx + 1, ''/0'');
string reverseReplace{ replace };
reverse(reverseReplace.begin(), reverseReplace.end());
char *end_ptr = &subject[initSize - 1];
while (end_ptr >= &subject[0])
{
if (*end_ptr == search) {
for (auto c : reverseReplace) {
subject[idx - 1] = c;
--idx;
}
}
else {
subject[idx - 1] = *end_ptr;
--idx;
}
--end_ptr;
}
}
int main()
{
string s{ "Mr John Smith" };
ReplaceString(s, '' '', "%20");
cout << s << "/n";
}
Si todas las cadenas son std :: string, encontrará problemas extraños con el corte de caracteres si usa sizeof()
porque está destinado a cadenas C, no a cadenas C ++. La solución es usar el método de clase .size()
de std::string
.
sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);
Eso reemplaza a sHaystack en línea - no hay necesidad de hacer una = asignación en eso.
Ejemplo de uso:
std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;
Yo uso generalmente esto:
std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
if(!from.empty())
for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
s.replace(pos, from.size(), to);
return s;
}
Llama repetidamente a std::string::find()
para localizar otras ocurrencias de la cadena buscada hasta que std::string::find()
no encuentre nada. Como std::string::find()
devuelve la posición de la coincidencia, no tenemos el problema de invalidar iteradores.
std::string
tiene un método de replace
, ¿es eso lo que estás buscando?
Tu podrías intentar:
s.replace(s.find("$name"), sizeof("Somename")-1, "Somename");
No me he probado, solo lea la documentación en find()
y replace()
.
std::string replace(std::string base, const std::string from, const std::string to) {
std::string SecureCopy = base;
for (size_t start_pos = SecureCopy.find(from); start_pos != std::string::npos; start_pos = SecureCopy.find(from,start_pos))
{
SecureCopy.replace(start_pos, from.length(), to);
}
return SecureCopy;
}
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);