Замена элементов в векторе с помощью стирания и вставки

void replace(vector<string> my_vector_2, string old, string replacement){

    vector<string>::iterator it;
    for (it = my_vector_2.begin(); it != my_vector_2.end(); ++it){

        if (*it==old){
            my_vector_2.erase(it);
            my_vector_2.insert(it,replacement);

        }
    }

}

Итак, я бы хотел, чтобы эта функция заменяла все вхождения старой строки в векторе заменой строки. Но при вызове этой функции она просто вообще не меняет вектор. Я не уверен, правильно ли я использую функции стирания и вставки. Любые идеи?


person Nikolai Stiksrud    schedule 14.04.2013    source источник
comment
Разве вы не должны передавать вектор как ссылку?   -  person Shimon Rachlenko    schedule 14.04.2013
comment
Ах, чувак, я чувствую себя таким глупым прямо сейчас.... Спасибо!   -  person Nikolai Stiksrud    schedule 14.04.2013
comment
Вам не нужно стирать и вставлять. Просто назначьте: *it = replacement;. Это устраняет любые проблемы, связанные с аннулированием итератора, и устраняет кучу взбалтывания, чтобы удалить элемент, а затем открыть дыру для вставки там, где раньше был этот элемент.   -  person Pete Becker    schedule 14.04.2013


Ответы (3)


Сначала вам нужно передать вектор по ссылке, а не по значению.

void replace(vector<string>& my_vector_2, string old, string replacement){

Второе стирание и вставка аннулирует его, вам нужно обновить его с помощью нового итератора, возвращаемого стиранием

it = my_vector_2.erase(it);  
it = my_vector_2.insert(it,replacement);
person alexrider    schedule 14.04.2013
comment
Это не УБ? Упоминание it после звонка erase является UB, и вы упоминаете it в своем звонке insert. Я думаю, вам нужно использовать обходной путь с std::distance. - person Enn Michael; 06.11.2016
comment
@Enn - разве вы не заметили, что it присваивается результат erase()? Нельзя использовать недействительный итератор, поскольку it теперь содержит допустимый итератор; то же самое верно и для следующей строки insert(). - person Toby Speight; 02.05.2017

Для вашей проблемы есть готовый алгоритм:

#include <algorithm>
#include <string>
#include <vector>

std::vector<std::string> v;  // populate

std::replace(v.begin(), v.end(), "old", "new");
person Kerrek SB    schedule 14.04.2013
comment
Может быть, стоит отметить, а может и не стоит, что это выводит T в replace как char[4]. Операции, которые смешивают string и const char*, должны быть эффективными, поэтому я не думаю, что в данном случае это имеет значение, но если вы хотите передавать строковые литералы разной длины, вам нужно преобразование. - person Steve Jessop; 14.04.2013

Вы передаете std::vector в качестве значения. Чтобы изменить std::vector, который вы передаете функции, объявите его как ссылку

void replace(vector<string>& my_vector_2, string old, string replacement){ }

& означает, что вы передаете std::vector по ссылке, и поэтому вы можете получить доступ к объекту, который вы передали.

И не стирайте элемент, просто замените его.

person bash.d    schedule 14.04.2013