2010-01-18 3 views
10

Я новичок в C++. Я хотел бы знать, как это делают опытные кодеры.как удалить все четные целые числа из набора <int> в C++

то, что у меня есть:

set<int> s; 
s.insert(1); 
s.insert(2); 
s.insert(3); 
s.insert(4); 
s.insert(5); 

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){ 
if (!(*itr % 2)) 
    s.erase(itr); 
} 

и, конечно же, он не работает. потому что itr увеличивается после его стирания. означает ли это, что Itr должен указывать на начало набора каждый раз после стирания элемента из набора?

ответ

16
for(set<int>::iterator itr = s.begin(); itr != s.end();){ 
    if (!(*itr % 2)) 
     s.erase(itr++); 

    else ++itr; 
} 

эффективный STL Скотт Майерс

+0

У вас есть дополнительная скобка в коде. – qba

+0

Почему itr ++ допускается в функции стирания, но не снаружи? – Quincy

+5

'itr ++' разрешен снаружи, но '++ it' в целом предпочтительнее, когда значение не используется, из-за причин, из-за которых утомительно идти в каждый раз, когда кто-либо это делает ;-) В этом случае было бы лучше игнорируйте обычную хорошую практику и пишите 'itr ++', просто потому, что код читается чуть более гладко, если в обоих случаях он одинаковый. –

11

Удаление элемента из std :: set приводит к недействительности итераторов, указывающих на этот элемент.

Получить итератор к следующему элементу перед стиранием целевого элемента.

8

Вам не нужно возвращаться к началу. set::erase аннулирует только итераторы, которые относятся к элементу стиранию, поэтому вам просто нужно скопировать итератор и приращение перед удалением:

for(set<int>::iterator itr = s.begin(); itr != s.end();) 
{ 
    set<int>::iterator here = itr++; 
    if (!(*here % 2)) 
     s.erase(here); 
} 
+0

Хорошо, я сдаюсь. Какая ошибка? –

+1

Я был неправ, я думал, что вы пропустили первый элемент. Я возвращаю свой комментарий и нижний план. –

-1

Лучший способ заключается в использовании сочетание remove_if и удаления

s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end()) 

Это будет полезно http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

Также обратитесь к эффективной STL Скотт Мейерс

Edit: Несмотря на то, что мое решение не так я не удаляя его. Это может быть хорошим обучением для кого-то вроде меня, который не знает об изменяемых и неизменяемых итераторах.

+6

'remove_if' требует, чтобы' operator * 'возвращал значение non-const lvalue. std :: set устанавливает, что он всегда упорядочен; возврат не константы lvalue из 'std :: set :: operator *' нарушит эту гарантию. Поэтому 'std :: remove_if()' не принимает 'std :: set :: iterator's – MSalters

+0

Спасибо, я знаю, что –

+5

Это было действительно полезно. Я застрял, пытаясь сделать это с помощью remove_if, и это объяснило мне, в чем проблема. Благодарю. –

Смежные вопросы