Если s
является std::string
, то существует ли функция, подобная следующей?
s.replace("text to replace", "new text");
Если s
является std::string
, то существует ли функция, подобная следующей?
s.replace("text to replace", "new text");
Попробуйте комбинацию std::string::find
и std::string::replace
.
Это получает позицию:
std::string s;
std::string toReplace("text to replace");
size_t pos = s.find(toReplace);
И это заменяет первое появление:
s.replace(pos, toReplace.length(), "new text");
Теперь вы можете просто создать функцию для вашего удобства:
std::string replaceFirstOccurrence(
std::string& s,
const std::string& toReplace,
const std::string& replaceWith)
{
std::size_t pos = s.find(toReplace);
if (pos == std::string::npos) return s;
return s.replace(pos, toReplace.length(), replaceWith);
}
Да: replace_all
является одним из алгоритмов форсированной строки:
Хотя это не стандартная библиотека, в стандартной библиотеке есть несколько вещей:
replace_all
, вложенные внутри trim
). Это немного более важно для стандартных функций библиотеки.Нам действительно нужна библиотека Boost для кажущейся такой простой задачи?
Чтобы заменить все вхождения подстроки, используйте эту функцию:
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;
}
Если вам нужна производительность, вот оптимизированная функция, которая изменяет входную строку, она не создает копию строки:
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();
}
}
Тесты:
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;
Вывод:
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
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str("one three two four");
string str2("three");
str.replace(str.find(str2),str2.length(),"five");
cout << str << endl;
return 0;
}
one five two four
как говорят некоторые boost:: replace_all
здесь фиктивный пример:
#include <boost/algorithm/string/replace.hpp>
std::string path("file.gz");
boost::replace_all(path, ".gz", ".zip");
Не совсем то, но std::string
имеет много replace
перегруженных функций.
Пройдите эту ссылку, чтобы увидеть объяснение каждого, с примерами того, как они используются.
Кроме того, существует несколько версий string::find
функций (перечисленных ниже), которые вы можете использовать в сочетании с string::replace
.
Также обратите внимание, что существует несколько версий replace
функций, доступных из <algorithm>
, которые вы также можете использовать (вместо string::replace
):
// replaced text will be in buffer.
void Replace(char* buffer, const char* source, const char* oldStr, const char* newStr)
{
if(buffer==NULL || source == NULL || oldStr == NULL || newStr == NULL) return;
int slen = strlen(source);
int olen = strlen(oldStr);
int nlen = strlen(newStr);
if(olen>slen) return;
int ix=0;
for(int i=0;i<slen;i++)
{
if(oldStr[0] == source[i])
{
bool found = true;
for(int j=1;j<olen;j++)
{
if(source[i+j]!=oldStr[j])
{
found = false;
break;
}
}
if(found)
{
for(int j=0;j<nlen;j++)
buffer[ix++] = newStr[j];
i+=(olen-1);
}
else
{
buffer[ix++] = source[i];
}
}
else
{
buffer[ix++] = source[i];
}
}
}
В этой версии я написал запись, которая заменяет все экземпляры целевой строки в заданной строке. Работает с любым типом строки.
template <typename T, typename U>
T &replace (
T &str,
const U &from,
const U &to)
{
size_t pos;
size_t offset = 0;
const size_t increment = to.size();
while ((pos = str.find(from, offset)) != T::npos)
{
str.replace(pos, from.size(), to);
offset = pos + increment;
}
return str;
}
Пример:
auto foo = "this is a test"s;
replace(foo, "is"s, "wis"s);
cout << foo;
Вывод:
thwis wis a test
Обратите внимание, что даже если строка поиска появляется в заменяющей строке, это работает правильно.
void replace(char *str, char *strFnd, char *strRep)
{
for (int i = 0; i < strlen(str); i++)
{
int npos = -1, j, k;
if (str[i] == strFnd[0])
{
for (j = 1, k = i+1; j < strlen(strFnd); j++)
if (str[k++] != strFnd[j])
break;
npos = i;
}
if (npos != -1)
for (j = 0, k = npos; j < strlen(strRep); j++)
str[k++] = strRep[j];
}
}
int main()
{
char pst1[] = "There is a wrong message";
char pfnd[] = "wrong";
char prep[] = "right";
cout << "\nintial:" << pst1;
replace(pst1, pfnd, prep);
cout << "\nfinal : " << pst1;
return 0;
}