6.6. Операции с последовательными контейнерами
6.6. Операции с последовательными контейнерами
Функция-член push_back() позволяет добавить единственный элемент в конец контейнера. Но как вставить элемент в произвольную позицию? А целую последовательность элементов? Для этих случаев существуют более общие операции.
Например, для вставки элемента в начало контейнера можно использовать:
vector string svec;
list string slist;
string spouse( "Beth" );
slist.insert( slist.begin(), spouse );
svec.insert( svec.begin(), spouse );
Первый параметр функции-члена insert() (итератор, адресующий некоторый элемент контейнера) задает позицию, а второй – вставляемое перед этой позицией значение. В примере выше элемент добавляется в начало контейнера. А так можно реализовать вставку в произвольную позицию:
string son( "Danny" );
liststring::iterator iter;
iter = find( slist.begin(), slist.end(), son );
slist.insert( iter, spouse );
Здесь find() возвращает позицию элемента в контейнере, если элемент найден, либо итератор end(), если ничего не найдено. (Мы вернемся к функции find() в конце следующего раздела.) Как можно догадаться, push_back() эквивалентен следующей записи:
// эквивалентный вызов: slist.push_back( value );
slist.insert( slist.end(), value );
Вторая форма функции-члена insert() позволяет вставить указанное количество одинаковых элементов, начиная с определенной позиции. Например, если мы хотим добавить десять элементов Anna в начало вектора, то должны написать:
vectorstring svec;
string anna( "Anna" );
svec.insert( svec.begin(), 10, anna );
insert() имеет и третью форму, помогающую вставить в контейнер несколько элементов. Допустим, имеется следующий массив:
string sarray[4] = { "quasi", "simba", "frollo", "scar" };
Мы можем добавить все его элементы или только некоторый диапазон в наш вектор строк:
svec.insert( svec.begin(), sarray, sarray+4 );
svec.insert( svec.begin() + svec.size()/2,
sarray+2, sarray+4 );
Такой диапазон отмечается и с помощью пары итераторов
// вставляем элементы svec
// в середину svec_two
svec_two.insert( svec_two.begin() + svec_two.size()/2,
svec.begin(), svec.end() );
или любого контейнера, содержащего строки:
list string slist;
// ...
// вставляем элементы svec
// перед элементом, содержащим stringVal
list string ::iterator iter =
find( slist.begin(), slist.end(), stringVal );
slist.insert( iter, svec.begin(), svec.end() );
6.6.1. Удаление
В общем случае удаление осуществляется двумя формами функции-члена erase(). Первая форма удаляет единственный элемент, вторая – диапазон, отмеченный парой итераторов. Для последнего элемента можно воспользоваться функцией-членом pop_back().
При вызове erase() параметром является итератор, указывающий на нужный элемент. В следующем фрагменте кода мы воспользуемся обобщенным алгоритмом find() для нахождения элемента и, если он найден, передадим его адрес функции-члену erase().
string searchValue( "Quasimodo" );
list string ::iterator iter =
find( slist.begin(), slist.end(), searchValue );
if ( iter != slist.end() )
slist.erase( iter );
Для удаления всех элементов контейнера или некоторого диапазона можно написать следующее:
// удаляем все элементы контейнера
slist.erase( slist.begin(), slist.end() );
// удаляем элементы, помеченные итераторами
list string ::iterator first, last;
first = find( slist. begin(), slist.end(), vail );
last = find( slist.begin(), slist.end(), va12 );
// ... проверка first и last
slist.erase( first, last );
Парной по отношению к push_back() является функция-член pop_back(), удаляющая из контейнера последний элемент, не возвращая его значения:
vector string ::iterator iter = buffer.begin();
for ( ; iter != buffer.end(), iter++ )
{
slist.push_back( *iter );
if ( ! do_something( slist ))
slist.pop_back();
}