¿Hay alguna forma de reemplazar todas las apariciones de una subcadena con otra cadena std::string
?
Por ejemplo:
void SomeFunction(std::string& str)
{
str = str.replace("hello", "world"); //< I'm looking for something nice like this
}
¿Hay alguna forma de reemplazar todas las apariciones de una subcadena con otra cadena std::string
?
Por ejemplo:
void SomeFunction(std::string& str)
{
str = str.replace("hello", "world"); //< I'm looking for something nice like this
}
Respuestas:
¿Por qué no implementar su propio reemplazo?
void myReplace(std::string& str,
const std::string& oldStr,
const std::string& newStr)
{
std::string::size_type pos = 0u;
while((pos = str.find(oldStr, pos)) != std::string::npos){
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
}
#include <boost/algorithm/string.hpp> // include Boost, a C++ library
...
std::string target("Would you like a foo of chocolate. Two foos of chocolate?");
boost::replace_all(target, "foo", "bar");
Aquí está la documentación oficial sobre replace_all.
replace_all
se producirá un error de segmentación para las versiones de boost> 1.43 en Sun Studio para cualquier versión <12.3
boost
aumenta considerablemente el tiempo de compilación en dispositivos integrados. Incluso ARMv7 de cuatro núcleos. Se compilan 100 líneas de código en 2 minutos, sin impulso, 2 segundos.
En C ++ 11, puede hacer esto como una línea con una llamada a regex_replace
:
#include <string>
#include <regex>
using std::string;
string do_replace( string const & in, string const & from, string const & to )
{
return std::regex_replace( in, std::regex(from), to );
}
string test = "Remove all spaces";
std::cout << do_replace(test, " ", "") << std::endl;
salida:
Removeallspaces
from
puede ser una expresión regular, por lo que puede utilizar criterios de coincidencia más sofisticados si es necesario. Lo que no veo es cómo hacer esto sin aplicar alguna forma de análisis de expresiones regulares, en lugar de usar solo una interpretación directa de los from
caracteres.
¿Por qué no devolver una cadena modificada?
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 changed: "
<< 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
Mi búsqueda y reemplazo en línea en el lugar con plantilla:
template<class T>
int inline findAndReplace(T& source, const T& find, const T& replace)
{
int num=0;
typename T::size_t fLen = find.size();
typename T::size_t rLen = replace.size();
for (T::size_t pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
{
num++;
source.replace(pos, fLen, replace);
}
return num;
}
Devuelve un recuento del número de elementos sustituidos (para usar si desea ejecutar esto sucesivamente, etc.). Para usarlo:
std::string str = "one two three";
int n = findAndReplace(str, "one", "1");
La forma más fácil (ofreciendo algo parecido a lo que escribió) es usar Boost.Regex , específicamente regex_replace .
std :: string tiene incorporados los métodos find () y replace (), pero es más complicado trabajar con ellos ya que requieren lidiar con índices y longitudes de cadenas.
Creo que esto funcionaría. Toma const char * como parámetro.
//params find and replace cannot be NULL
void FindAndReplace( std::string& source, const char* find, const char* replace )
{
//ASSERT(find != NULL);
//ASSERT(replace != NULL);
size_t findLen = strlen(find);
size_t replaceLen = strlen(replace);
size_t pos = 0;
//search for the next occurrence of find within source
while ((pos = source.find(find, pos)) != std::string::npos)
{
//replace the found string with the replacement
source.replace( pos, findLen, replace );
//the next line keeps you from searching your replace string,
//so your could replace "hello" with "hello world"
//and not have it blow chunks.
pos += replaceLen;
}
}
size_type
para una cadena es unsigned
, su >=
verificación en la condición de bucle siempre será true
. Tienes que usarlo std::string::npos
allí.
roll_down_window
// Replace all occurrences of searchStr in str with replacer
// Each match is replaced only once to prevent an infinite loop
// The algorithm iterates once over the input and only concatenates
// to the output, so it should be reasonably efficient
std::string replace(const std::string& str, const std::string& searchStr,
const std::string& replacer)
{
// Prevent an infinite loop if the input is empty
if (searchStr == "") {
return str;
}
std::string result = "";
size_t pos = 0;
size_t pos2 = str.find(searchStr, pos);
while (pos2 != std::string::npos) {
result += str.substr(pos, pos2-pos) + replacer;
pos = pos2 + searchStr.length();
pos2 = str.find(searchStr, pos);
}
result += str.substr(pos, str.length()-pos);
return result;
}
#include <string>
using std::string;
void myReplace(string& str,
const string& oldStr,
const string& newStr) {
if (oldStr.empty()) {
return;
}
for (size_t pos = 0; (pos = str.find(oldStr, pos)) != string::npos;) {
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
}
La comprobación de que oldStr esté vacía es importante. Si por alguna razón ese parámetro está vacío, se quedará atascado en un bucle infinito.
Pero sí, use la solución probada C ++ 11 o Boost si puede.