Как заменить все экземпляры строки другой строкой? - PullRequest
41 голосов
/ 17 марта 2011

Я нашел это в другом вопросе стека:

///2625749/zamenit-chast-stroki-drugoi-strokoi
//
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's with 0's
11 1  // result, as it was returned from convert_FANN_array_to_binary()

Я смотрел на код replaceAll, и я действительно не уверен, почему он заменяет последовательные -1 на 0, а затем не возвращает 0 (и некоторые 1) в конечном результате. = \

Ответы [ 6 ]

53 голосов
/ 04 февраля 2013

Полный код:

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
18 голосов
/ 17 марта 2011

Ошибка в str.replace(start_pos, end_pos, to);

Из документа std :: string в 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(); // ...
}

Примечание: не проверено.

11 голосов
/ 17 марта 2011

Это будет в моем списке ответов «просто используйте библиотеку Boost», но здесь все равно:

Рассматривали ли вы Boost.String ? Он имеет больше возможностей, чем стандартная библиотека, и там, где функции перекрываются, Boost.String имеет гораздо более естественный синтаксис, на мой взгляд.

7 голосов
/ 24 октября 2013

C ++ 11 теперь включает заголовок <regex>, который имеет функцию регулярного выражения. Из документов :

// 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;
}

Конечно, теперь у вас две проблемы .

6 голосов
/ 12 июля 2013

Я нашел функции замены, приведенные в предыдущих ответах, все они используют внутренний вызов 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;
}

Грег

1 голос
/ 19 февраля 2017

Попробуйте это:

#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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...