Usuwanie czegoś z listy obiektów - błąd, program się "wywala"

0

Mam problem z programem, który ma mi usuwać z listy osobę o szukanym ID. Jednak program się wywala, okienko CodeBlocks się zamyka i pokazuje jakiś numer błędu. Co jest źle ?

#include <list>
#include <string>
#include <iostream>

using namespace std;

class Osoba
{
    public :
        string nazwisko;
        int id;
        Osoba(int i, string n) {nazwisko = n; id = i; }
        int ID() {return id;}
        string N() {return nazwisko;}
};

int main()
{
    list<Osoba*> w;
    Osoba *o = new Osoba(23, "Jan");
    Osoba *o1 = new Osoba(37, "Karol");
    w.push_back(o);
    w.push_back(o1);

    list<Osoba*>::iterator i = w.begin();
    for( ; i!= w.end(); i++ )
        cout << (*i)->N() << " " << (*i)->ID()  << "\n";

    i = w.begin();

    int szukane = 23;
    for( ; i!= w.end(); i++ ){
        if((*i)->ID()== szukane){
          w.remove(o);
        }
    }

    i = w.begin();
    for( ; i!= w.end(); i++ )
        cout << (*i)->N() << " " << (*i)->ID()  << "\n";

    return 0;
}
0
  1. metody Osoba::ID i Osoba::N są niepotrzebne, bo odpowiednie pola i tak masz publiczne.

  2. zrób listę list<Osoba> a nie list<Osoba*>. w ten sposób nie będziesz musiał ręcznie przydzielać pamięci na obiekty. w tej chwili robisz new, ale nigdzie nie robisz delete. masz wycieki.

 w.remove(o);

usuwanie elementu z listy podczas pracy pętli powoduje unieważnienie iteratora. tak nie można.

0

Dziękuję Azarien za odpowiedź i pomoc. No właśnie ja potrzebuję w tej liście obiektów Osoba*, bo w dalszej części zadania coś tam trzeba jeszcze dopisać.

A to jak zmienilem wg Twoich wskazówek to już jest dobrze? Bo działa:

#include <list>
#include <string>
#include <iostream>

using namespace std;

class Osoba
{
    public :
        string nazwisko;
        int id;
        Osoba(int i, string n) {nazwisko = n; id = i; }
};

int main()
{
    list<Osoba*> w;
    Osoba *o = new Osoba(23, "Jan");
    Osoba *o1 = new Osoba(37, "Karol");
    w.push_back(o);
    w.push_back(o1);

    list<Osoba*>::iterator i = w.begin();
    for( ; i!= w.end(); i++ )
        cout << (*i)->nazwisko << " " << (*i)->id  << "\n";

    i = w.begin();

    int szukane = 23;
    for( ; i!= w.end(); i++ ){
        if((*i)->id == szukane){
          w.remove((*i));
          delete (*i);
          i = w.begin();
        }
    }

    cout << "po usunieciu : ========================================== \n";

    i = w.begin();
    for( ; i!= w.end(); i++ )
        cout << (*i)->nazwisko << " " << (*i)->id  << "\n";

    return 0;
}
0
 for( ; i!= w.end(); i++ ){
        if((*i)->id == szukane){
          w.remove((*i));
          delete (*i);
          i = w.begin();
        }

Tutaj jak znajdziesz dany element, to usuwasz go i.... szukasz od początku. Użyj chociaż break dla przerwania pętli :P

0

A nie widzę w http://www.cplusplus.com/reference/stl/list metody coś w stylu "exists" czy muszę ją sam napisać, aby sprawdzić, czy dane Id istnieje?

0

A, masz rację! czyli tak:

int szukane = 23;
    for( ; i!= w.end(); i++ ){
        if((*i)->id == szukane){
          w.remove((*i));
          delete (*i);
          break;
        }
    }

??

0

bo w dalszej części zadania coś tam trzeba jeszcze dopisać.
to mnie nadal nie przekonuje...

          w.remove((*i));
          delete (*i);

no nie, po remove na pewno iterator i nie jest prawidłowy, nawet jeśli jeszcze cudem działa. jeśli już to odwrotnie, i raczej z erase:

delete *i;
w.erase(i);
0

Ok, dziękuję pięknie. Źle się wyraziłem - po prostu, taka jest treść zadania i ja nie mam na to wpływu ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1