В C ++ нет встроенной функции для этого. Если вы хотите заменить все экземпляры одной подстроки другой, вы можете сделать это, смешав вызовы string::findи string::replace. Например:
size_t index = 0;
while (true) {
/* Locate the substring to replace. */
index = str.find("abc", index);
if (index == std::string::npos) break;
/* Make the replacement. */
str.replace(index, 3, "def");
/* Advance index forward so the next iteration doesn't pick it up as well. */
index += 3;
}
В последней строке этого кода я увеличил indexдлину строки, вставленной в строку. В данном конкретном примере - замена "abc"на "def"- в этом нет необходимости. Однако в более общих настройках важно пропустить строку, которая только что была заменена. Например, если вы хотите заменить"abc" на "abcabc", не пропуская только что замененный сегмент строки, этот код будет постоянно заменять части вновь замененных строк, пока память не будет исчерпана. Независимо от этого, в любом случае может быть немного быстрее пропустить эти новые символы, поскольку это экономит время и усилия для string::findфункции.
Я не верю, что вам нужно будет увеличивать индекс, потому что вы уже заменили данные, поэтому он все равно их не заберет.
rossb83 04
1
@Aidiakapi Если его превратить в функцию общего назначения, он не застрянет в бесконечном цикле, потому что он продвигает позицию поиска ( index) за часть замененной части строки.
Тим Р.
1
@TimR. Вы правы, я отвечал rossb83, который заявил, что в увеличении индекса нет необходимости. Просто пытался предотвратить дезинформацию. Так что для всех остальных: Увеличение индекса по длине заменяемой строки (в данном случае 3) необходимо . Не удаляйте его из образца кода.
Aidiakapi
@FrozenKiwi Я удивлен это слышать. Вы уверены, что это так?
templatetypedef
1
@JulianCienfuegos Я только что обновил ответ, чтобы решить эту проблему - спасибо, что указали на это! (Кроме того, Айдиакапи - это кто-то другой ... не уверен, кто это.)
Я думаю, что все решения потерпят неудачу, если длина заменяемой строки отличается от длины заменяемой строки. (найдите «abc» и замените на «xxxxxx») Общий подход может быть следующим:
Я предлагаю убедиться, что результат str.find (str2) не равен std :: string :: npos auto found = str.find (str2); если (найдено! = std :: string :: npos) str.replace (found, str2.length (), str3);
Джефф Ленч
1
Я не собирался писать все приложение с этим, но без каких-либо проверок ввода есть случаи, когда это не определено ....
нужно добавить проверку, if (search.empty()) { return; }чтобы избежать бесконечного цикла при пустом поиске.
iOS-программист
Пробовал функцию ReplaceString - не сработало. Но ответьте ниже: str.replace (str.find (str2), str2.length (), str3); просто и хорошо работает.
KAMIKAZE
5
usingstd::string;
stringstring_replace( string src, stringconst& target, stringconst& repl){
// handle error situations/trivial casesif (target.length() == 0) {
// searching for a match to the empty string will result in // an infinite loop// it might make sense to throw an exception for this casereturn src;
}
if (src.length() == 0) {
return src; // nothing to match against
}
size_t idx = 0;
for (;;) {
idx = src.find( target, idx);
if (idx == string::npos) break;
src.replace( idx, target.length(), repl);
idx += repl.length();
}
return src;
}
Поскольку он не является членом stringкласса, он не позволяет использовать такой хороший синтаксис, как в вашем примере, но следующее будет делать эквивалент:
test = string_replace( string_replace( test, "abc", "hij"), "def", "klm")
Обобщая ответ rotmax, вот полное решение для поиска и замены всех экземпляров в строке. Если обе подстроки имеют разный размер, подстрока заменяется с помощью string :: erase и string :: insert., В противном случае используется более быстрая строка :: replace.
voidFindReplace(string& line, string& oldString, string& newString){
constsize_t oldSize = oldString.length();
// do nothing if line is shorter than the string to findif( oldSize > line.length() ) return;
constsize_t newSize = newString.length();
for( size_t pos = 0; ; pos += newSize ) {
// Locate the substring to replace
pos = line.find( oldString, pos );
if( pos == string::npos ) return;
if( oldSize == newSize ) {
// if they're same size, use std::string::replace
line.replace( pos, oldSize, newString );
} else {
// if not same size, replace by erasing and inserting
line.erase( pos, oldSize );
line.insert( pos, newString );
}
}
}
Вот решение с использованием рекурсии, которое заменяет все вхождения подстроки другой подстрокой. Это работает независимо от размера струн.
std::stringReplaceString(conststd::string source_string, conststd::string old_substring, conststd::string new_substring){
// Can't replace nothing.if (old_substring.empty())
return source_string;
// Find the first occurrence of the substring we want to replace.size_t substring_position = source_string.find(old_substring);
// If not found, there is nothing to replace.if (substring_position == std::string::npos)
return source_string;
// Return the part of the source string until the first occurance of the old substring + the new replacement substring + the result of the same function on the remainder.return source_string.substr(0,substring_position) + new_substring + ReplaceString(source_string.substr(substring_position + old_substring.length(),source_string.length() - (substring_position + old_substring.length())), old_substring, new_substring);
}
Пример использования:
std::string my_cpp_string = "This string is unmodified. You heard me right, it's unmodified.";
std::cout << "The original C++ string is:\n" << my_cpp_string << std::endl;
my_cpp_string = ReplaceString(my_cpp_string, "unmodified", "modified");
std::cout << "The final C++ string is:\n" << my_cpp_string << std::endl;
Ответы:
В C ++ нет встроенной функции для этого. Если вы хотите заменить все экземпляры одной подстроки другой, вы можете сделать это, смешав вызовы
string::find
иstring::replace
. Например:size_t index = 0; while (true) { /* Locate the substring to replace. */ index = str.find("abc", index); if (index == std::string::npos) break; /* Make the replacement. */ str.replace(index, 3, "def"); /* Advance index forward so the next iteration doesn't pick it up as well. */ index += 3; }
В последней строке этого кода я увеличил
index
длину строки, вставленной в строку. В данном конкретном примере - замена"abc"
на"def"
- в этом нет необходимости. Однако в более общих настройках важно пропустить строку, которая только что была заменена. Например, если вы хотите заменить"abc"
на"abcabc"
, не пропуская только что замененный сегмент строки, этот код будет постоянно заменять части вновь замененных строк, пока память не будет исчерпана. Независимо от этого, в любом случае может быть немного быстрее пропустить эти новые символы, поскольку это экономит время и усилия дляstring::find
функции.Надеюсь это поможет!
источник
index
) за часть замененной части строки.Библиотека алгоритмов Boost String :
#include <boost/algorithm/string/replace.hpp> { // 1. string test = "abc def abc def"; boost::replace_all(test, "abc", "hij"); boost::replace_all(test, "def", "klm"); } { // 2. string test = boost::replace_all_copy ( boost::replace_all_copy<string>("abc def abc def", "abc", "hij") , "def" , "klm" ); }
источник
В c ++ 11, вы можете использовать
std::regex_replace
:#include <string> #include <regex> std::string test = "abc def abc def"; test = std::regex_replace(test, std::regex("def"), "klm");
источник
Я думаю, что все решения потерпят неудачу, если длина заменяемой строки отличается от длины заменяемой строки. (найдите «abc» и замените на «xxxxxx») Общий подход может быть следующим:
void replaceAll( string &s, const string &search, const string &replace ) { for( size_t pos = 0; ; pos += replace.length() ) { // Locate the substring to replace pos = s.find( search, pos ); if( pos == string::npos ) break; // Replace by erasing and inserting s.erase( pos, search.length() ); s.insert( pos, replace ); } }
источник
куда
str
это базовая строкаstr2
это подстрока, которую нужно найтиstr3
подстрока заменыисточник
Замена подстрок не должна быть такой сложной.
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 changed: " << 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
источник
if (search.empty()) { return; }
чтобы избежать бесконечного цикла при пустом поиске.using std::string; string string_replace( string src, string const& target, string const& repl) { // handle error situations/trivial cases if (target.length() == 0) { // searching for a match to the empty string will result in // an infinite loop // it might make sense to throw an exception for this case return src; } if (src.length() == 0) { return src; // nothing to match against } size_t idx = 0; for (;;) { idx = src.find( target, idx); if (idx == string::npos) break; src.replace( idx, target.length(), repl); idx += repl.length(); } return src; }
Поскольку он не является членом
string
класса, он не позволяет использовать такой хороший синтаксис, как в вашем примере, но следующее будет делать эквивалент:test = string_replace( string_replace( test, "abc", "hij"), "def", "klm")
источник
Обобщая ответ rotmax, вот полное решение для поиска и замены всех экземпляров в строке. Если обе подстроки имеют разный размер, подстрока заменяется с помощью string :: erase и string :: insert., В противном случае используется более быстрая строка :: replace.
void FindReplace(string& line, string& oldString, string& newString) { const size_t oldSize = oldString.length(); // do nothing if line is shorter than the string to find if( oldSize > line.length() ) return; const size_t newSize = newString.length(); for( size_t pos = 0; ; pos += newSize ) { // Locate the substring to replace pos = line.find( oldString, pos ); if( pos == string::npos ) return; if( oldSize == newSize ) { // if they're same size, use std::string::replace line.replace( pos, oldSize, newString ); } else { // if not same size, replace by erasing and inserting line.erase( pos, oldSize ); line.insert( pos, newString ); } } }
источник
Если вы уверены, что требуемая подстрока присутствует в строке, то это заменит первое появление
"abc"
на"hij"
test.replace( test.find("abc"), 3, "hij");
Он выйдет из строя, если в тесте нет "abc", поэтому используйте его с осторожностью.
источник
Вот решение, которое я написал, используя тактику строителя:
#include <string> #include <sstream> using std::string; using std::stringstream; string stringReplace (const string& source, const string& toReplace, const string& replaceWith) { size_t pos = 0; size_t cursor = 0; int repLen = toReplace.length(); stringstream builder; do { pos = source.find(toReplace, cursor); if (string::npos != pos) { //copy up to the match, then append the replacement builder << source.substr(cursor, pos - cursor); builder << replaceWith; // skip past the match cursor = pos + repLen; } } while (string::npos != pos); //copy the remainder builder << source.substr(cursor); return (builder.str()); }
Тесты:
void addTestResult (const string&& testId, bool pass) { ... } void testStringReplace() { string source = "123456789012345678901234567890"; string toReplace = "567"; string replaceWith = "abcd"; string result = stringReplace (source, toReplace, replaceWith); string expected = "1234abcd8901234abcd8901234abcd890"; bool pass = (0 == result.compare(expected)); addTestResult("567", pass); source = "123456789012345678901234567890"; toReplace = "123"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "-4567890-4567890-4567890"; pass = (0 == result.compare(expected)); addTestResult("start", pass); source = "123456789012345678901234567890"; toReplace = "0"; replaceWith = ""; result = stringReplace(source, toReplace, replaceWith); expected = "123456789123456789123456789"; pass = (0 == result.compare(expected)); addTestResult("end", pass); source = "123123456789012345678901234567890"; toReplace = "123"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "--4567890-4567890-4567890"; pass = (0 == result.compare(expected)); addTestResult("concat", pass); source = "1232323323123456789012345678901234567890"; toReplace = "323"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "12-23-123456789012345678901234567890"; pass = (0 == result.compare(expected)); addTestResult("interleaved", pass); source = "1232323323123456789012345678901234567890"; toReplace = "==="; replaceWith = "-"; result = utils_stringReplace(source, toReplace, replaceWith); expected = source; pass = (0 == result.compare(expected)); addTestResult("no match", pass); }
источник
string & replace(string & subj, string old, string neu) { size_t uiui = subj.find(old); if (uiui != string::npos) { subj.erase(uiui, old.size()); subj.insert(uiui, neu); } return subj; }
Я думаю, что это соответствует вашим требованиям с небольшим количеством кода!
источник
улучшенная версия @Czarek Tomczak.
разрешить оба
std::string
иstd::wstring
.template <typename charType> void ReplaceSubstring(std::basic_string<charType>& subject, const std::basic_string<charType>& search, const std::basic_string<charType>& replace) { if (search.empty()) { return; } typename std::basic_string<charType>::size_type pos = 0; while((pos = subject.find(search, pos)) != std::basic_string<charType>::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } }
источник
std::string replace(const std::string & in , const std::string & from , const std::string & to){ if(from.size() == 0 ) return in; std::string out = ""; std::string tmp = ""; for(int i = 0, ii = -1; i < in.size(); ++i) { // change ii if ( ii < 0 && from[0] == in[i] ) { ii = 0; tmp = from[0]; } else if( ii >= 0 && ii < from.size()-1 ) { ii ++ ; tmp = tmp + in[i]; if(from[ii] == in[i]) { } else { out = out + tmp; tmp = ""; ii = -1; } } else { out = out + in[i]; } if( tmp == from ) { out = out + to; tmp = ""; ii = -1; } } return out; };
источник
Вот решение с использованием рекурсии, которое заменяет все вхождения подстроки другой подстрокой. Это работает независимо от размера струн.
std::string ReplaceString(const std::string source_string, const std::string old_substring, const std::string new_substring) { // Can't replace nothing. if (old_substring.empty()) return source_string; // Find the first occurrence of the substring we want to replace. size_t substring_position = source_string.find(old_substring); // If not found, there is nothing to replace. if (substring_position == std::string::npos) return source_string; // Return the part of the source string until the first occurance of the old substring + the new replacement substring + the result of the same function on the remainder. return source_string.substr(0,substring_position) + new_substring + ReplaceString(source_string.substr(substring_position + old_substring.length(),source_string.length() - (substring_position + old_substring.length())), old_substring, new_substring); }
Пример использования:
std::string my_cpp_string = "This string is unmodified. You heard me right, it's unmodified."; std::cout << "The original C++ string is:\n" << my_cpp_string << std::endl; my_cpp_string = ReplaceString(my_cpp_string, "unmodified", "modified"); std::cout << "The final C++ string is:\n" << my_cpp_string << std::endl;
источник
std::string replace(std::string str, std::string substr1, std::string substr2) { for (size_t index = str.find(substr1, 0); index != std::string::npos && substr1.length(); index = str.find(substr1, index + substr2.length() ) ) str.replace(index, substr1.length(), substr2); return str; }
Краткое решение, когда вам не нужны дополнительные библиотеки.
источник
std::string replace(std::string str, const std::string& sub1, const std::string& sub2) { if (sub1.empty()) return str; std::size_t pos; while ((pos = str.find(sub1)) != std::string::npos) str.replace(pos, sub1.size(), sub2); return str; }
источник