Как заменить все экземпляры строки на другую строку?
Я нашел это на другом стеке вопроса:
//http://stackoverflow.com/info/3418231/c-replace-part-of-a-string-with-another-string
//
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
size_t end_pos = start_pos + from.length();
str.replace(start_pos, end_pos, to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
и мой метод:
string convert_FANN_array_to_binary(string fann_array)
{
string result = fann_array;
cout << result << "\n";
replaceAll(result, "-1 ", "0");
cout << result << "\n";
replaceAll(result, "1 ", "1");
return result;
}
который для этого ввода:
cout << convert_FANN_array_to_binary("1 1 -1 -1 1 1 ");
теперь выход должен быть "110011"
здесь выводится метод:
1 1 -1 -1 1 1 // original
1 1 0 1 // replacing -1 with 0's
11 1 // result, as it was returned from convert_FANN_array_to_binary()
Я смотрю на код replaceAll, и я действительно не уверен, почему он заменяет последовательный -1 одним 0, а затем не возвращает никаких 0 (и некоторых 1) в конечном результате. =\
Ответы
Ответ 1
Ошибка находится в str.replace(start_pos, end_pos, to);
Из документа std::string doc в http://www.cplusplus.com/reference/string/string/replace/
string& replace ( size_t pos1, size_t n1, const string& str );
Вы используете конечную позицию, а функция ожидает длину.
Итак, измените на:
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // ...
}
Примечание: непроверенный.
Ответ 2
Полный код:
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 changed: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def
Ответ 3
Это будет включено в мой список ответов "просто используйте библиотеку Boost", но здесь все равно:
Вы считали Boost.String? Он имеет больше возможностей, чем стандартная библиотека, и где функции перекрываются, Boost.String имеет гораздо более естественный синтаксис, на мой взгляд.
Ответ 4
С++ 11 теперь включает заголовок <regex>
, который имеет функции регулярного выражения. Из docs:
// regex_replace example
#include <iostream>
#include <string>
#include <regex>
#include <iterator>
int main ()
{
std::string s ("there is a subsequence in the string\n");
std::regex e ("\\b(sub)([^ ]*)"); // matches words beginning by "sub"
// using string/c-string (3) version:
std::cout << std::regex_replace (s,e,"sub-$2");
std::cout << std::endl;
return 0;
}
Конечно, теперь у вас есть две проблемы.
Ответ 5
Я нашел функции замены, приведенные в предыдущих ответах, используя внутренний вызов str.replace() внутри, очень медленно при работе со строкой длиной около 2 МБ. В частности, я назвал что-то вроде ReplaceAll (str, "\ r", ""), и на моем конкретном устройстве с текстовым файлом, содержащим много строк новой строки, потребовалось около 27 секунд. Затем я заменил его функцией, просто конкатенируя подстроки в новой копии, и потребовалось всего около 1 секунды. Вот моя версия ReplaceAll():
void replaceAll(string& str, const string& from, const string& to) {
if(from.empty())
return;
string wsRet;
wsRet.reserve(str.length());
size_t start_pos = 0, pos;
while((pos = str.find(from, start_pos)) != string::npos) {
wsRet += str.substr(start_pos, pos - start_pos);
wsRet += to;
pos += from.length();
start_pos = pos;
}
wsRet += str.substr(start_pos);
str.swap(wsRet); // faster than str = wsRet;
}
Грег
Ответ 6
Попробуйте следующее:
#include <string>
string replace_str(string & str, const string & from, const string & to)
{
while(str.find(from) != string::npos)
str.replace(str.find(from), from.length(), to);
return str;
}
Ответ 7
Другое решение - использовать boost (уже опубликованный в другом месте в stackoverflow) fooobar.com/info/19539/...