2010-01-18 10 views
10

Tôi mới sử dụng C++. Tôi muốn biết làm thế nào có kinh nghiệm lập trình làm điều này.cách xóa tất cả các số nguyên ngay cả từ tập hợp <int> bằng C++

những gì tôi 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); 
} 

và dĩ nhiên, nó không hoạt động. bởi vì nó được tăng lên sau khi nó bị xóa. có nghĩa là Itr phải trỏ đến phần bắt đầu của bộ mọi lúc sau khi tôi xóa phần tử khỏi tập hợp?

Trả lời

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

    else ++itr; 
} 

STL hiệu quả bởi Scott Myers

+0

Bạn có khung phụ trong mã. – qba

+0

tại sao nó được cho phép trong chức năng xóa, nhưng không được phép ở bên ngoài? – Quincy

+5

'itr ++' được cho phép ở bên ngoài, nhưng '++ nó' là ở chung thích hợp hơn khi giá trị không được sử dụng, vì những lý do để tẻ nhạt đi vào mọi thời điểm bất cứ ai làm điều đó ;-) Trong trường hợp này, nó có thể tốt hơn bỏ qua các thực hành tốt thông thường và viết 'itr ++', chỉ vì mã đọc hơi mượt mà nếu nó giống nhau trong cả hai trường hợp. –

11

Xóa một phần tử khỏi tiêu chuẩn :: đặt chỉ làm mất hiệu lực trình vòng lặp trỏ đến phần tử đó.

Nhận trình lặp tới phần tử tiếp theo trước khi xóa phần tử mục tiêu.

8

Bạn không cần phải quay lại phần đầu. set::erase chỉ làm mất hiệu lực lặp mà tham khảo các mục bị xoá hoàn toàn, vì vậy bạn chỉ cần sao chép các iterator và increment trước khi xóa:

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

OK, tôi bỏ cuộc. Lỗi là gì? –

+1

Tôi đã sai, tôi nghĩ bạn đã bỏ qua yếu tố đầu tiên. Tôi lấy lại bình luận của tôi và downvote. –

-1

Cách tốt nhất là sử dụng sự kết hợp của remove_if và xóa

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

này sẽ rất hữu ích http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

Đồng thời tham khảo STL hiệu quả theo scott meyers

Edit: Mặc dù giải pháp của tôi sai nhưng tôi không xóa nó. Nó có thể là một học tập tốt cho một người như tôi, những người không về các vòng lặp có thể thay đổi/không thay đổi được

+6

'remove_if' yêu cầu toán tử' * trả về giá trị không phải là const. std :: set thi hành rằng nó luôn được đặt hàng; trả về một giá trị không const từ 'std :: set :: operator *' sẽ phá vỡ sự bảo đảm đó. Vì vậy 'std :: remove_if()' không có 'std :: set :: iterator' s – MSalters

+0

Cảm ơn tôi đã biết rằng –

+5

Điều đó thực sự hữu ích. Tôi đã bị mắc kẹt cố gắng để làm điều này với remove_if và điều này cho tôi biết vấn đề là gì. Cảm ơn. –