Dodaj do ulubionych

C++ STL lista usuwanie obiektów problem, help!

20.11.04, 14:21
mam programik ktory przechowuje w liscie STLowej obiekty zawierające pola prywatne obiektow roznych klas. w glownej nadklasie jest publiczne pole zawierajace nazwe. lista STL jest zdefiniowana w klasie 'listy' i przechowywana w obiekcie 'l'. teraz chcialbym usuwac z tej listy obiekty o konkretnych polach 'nazwa'. napisalem cos takiego (co intuicyjnie powinno dzialac wg mnie) :

printf("\njaki obiekt zamierzasz usunac?\n");
printf("podaj nazwe elektrowni: ");
scanf("%s",nazwaE);
list<wodne>::iterator iterW;
for (iterW = l.listawodnych.begin(); iterW != l.listawodnych.end();iterW++)
if (strcmp((*iterW).nazwa,nazwaE) == 0)
{
l.listawodnych.remove((*iterW));
return;
}

ale wyskakuje kilka bledow. raz ze nie ma dostepu do pola nazwa (przypominam ze ono jest publiczne) i drugi : no match for `wodne & == const wodne &'.

zastanawiam sie czy w ogole mozna cale obiekty usuwac, czy np trzebaby napisac usuwanie ze wszystkich klas poszczegolnych pol i dopiero pozniej likwidowac obiekt jako wskaznik..
Obserwuj wątek
    • Gość: flm Re: C++ STL lista usuwanie obiektów problem, help IP: 193.151.96.* 20.11.04, 14:41
      Po pierwsze, źle używasz metody remove kontenera list - metoda ta porównuje
      kolejne elementy listy z podaną wartością i usuwa pasujące. Dlatego kompilator
      burzy się, że nie zdefiniowałeś == dla klasy wodne. Po drugie, z tego co
      pamiętam usunięcie elementu z listy unieważnia wskazujący na niego iterator,
      więc ta pętla i tak by nie zadziałała. Gdy usuniesz element wskazywany przez
      jakiś iterator
      > l.listawodnych.remove((*iterW));
      to iterator ten traci ważność. Gdy następnie w kolejnym przebiegu pętli
      spróbujesz go zwiększyć, to będzie wskazywał na losowe miejsce w pamięci, a nie
      na kolejny element listy. Żeby usunąć z listy elementy spełniające jakiś
      warunek, to chyba najłatwiej stworzyć funkcję, która zwróci true dla pasujących
      elementów, np.
      bool porownanie (const wodne& x)
      {
      return !(strcmp(wodne.nazwa, "tekst"));
      }
      a potem po prostu piszesz:
      l.listawodnych.remove_if(porownanie);
      }
      • Gość: flm poprawka IP: 193.151.96.* 20.11.04, 14:42
        return !(strcmp(wodne.nazwa, "tekst"));
        zamiast tego powinno być oczywiście
        return !(strcmp(x.nazwa, "tekst"));
        • mastar1 Re: poprawka 20.11.04, 17:27
          ehhh to nie dziala.. poszedlem za twoim przykladem.. poza tym dopisalem funkcje get_nazwa zeby wydobyc nazwe.. i tu jest ok. mam cos takiego teraz:

          char nazwaE[20];
          int wynik = 0;

          printf("\njaki obiekt zamierzasz usunac?\n");
          printf("podaj nazwe elektrowni: ");
          scanf("%s",nazwaE);
          list<wodne>::iterator iterW;
          for (iterW = l.listawodnych.begin(); iterW != l.listawodnych.end(); iterW++)
          {
          if (strcmp((*iterW).get_nazwa(),nazwaE) == 0) wynik = 1;
          l.listawodnych.remove_if(wynik == 1); !!!!!!!!!!!
          if (wynik == 1) return;
          }

          przypominam ze w liscie są obiekty typu klasowego a nazwa to jedno z ich pól jedynie.. listawodnych to nazwa listy przechowywanej w klasie listy, wywolywanej obiektem l :) problem pojawia sie w linijce oznaczonej wykrzyknikami. chcialbym tam usuwac znaleziony po nazwie obiekt typu klasowego z listy. nie jestem pewien czy tak mozna.. czy np musialbym po kolei usuwac wszystkie pola tego obiektu..
          • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 18:17
            Spróbuj tak:
            1. Definiujesz funkcję (osobno, może być w innym miejscu programu), która
            przyjmuje jako parametr element listy i ciąg znaków. Funkcja powinna zwracać
            true, jeśli nazwa funkcji jest taka sama jak podany ciąg. Np:

            bool jakas_funkcja(const wodny& x, const char* ciag)
            {
            if (strcmp(x.nazwa, ciag) == 0)
            return true;
            else
            return false;
            }
            2. Wczytujesz nazwę elementów do usunięcia, tak jak przedtem:
            scanf("%s",nazwaE);
            3. Wywołujesz remove_if jako parametr podając wskaźnik do funkcji z punktu 1
            (czyli jej nazwę). Tyle że trzeba jako jej drugi parametr ustawić wczytany ciąg,
            co można zrobić za pomocą bindowania:
            l.listawodnych.remove_if(bind2nd(ptr_fun(jakas_funkcja),nazwaE));
            • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 18:17
              > jeśli nazwa funkcji jest taka sama jak podany ciąg.
              Ech, powinno tu być "nazwa elementu"
            • mastar1 Re: poprawka 20.11.04, 19:13
              niestety.. nie kompiluje sie nawet..
              • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 19:53
                No to bardziej skomplikowane rozwiązanie (tym razem powinno działać):
                1. Dołącz nagłówek:
                #include <functional>
                2. Zamiast funkcji definiujesz obiekt funkcyjny, np:
                class NazwaFunktora : public binary_function<wodny, char*, bool>
                {
                public:
                bool operator()(const wodny& a, const char* b) const
                {
                return !strcmp(a.nazwa, b);
                }
                };
                3. Usuwanie elementów z listy:
                l.listawodnych.remove_if(bind2nd(NazwaFunktora(),nazwaE));

                Zamiast NazwaFunktora można wpisać jakąś inną nazwę, tylko musi być taka sama w
                p. 2 i 3.
                • mastar1 Re: poprawka 20.11.04, 20:37
                  class NazwaFunktora : public binary_function<wodne, char*, bool>
                  {
                  public:
                  bool operator()(const wodne& a, const char* b) const
                  {
                  return !strcmp(a.get_nazwa, b);
                  }
                  };

                  void usun_()
                  {
                  char nazwaE[30];

                  printf("\njaki obiekt zamierzasz usunac?\n");
                  printf("podaj nazwe elektrowni: ");
                  scanf("%s",nazwaE);

                  l.listawodnych.remove_if(bind2nd(NazwaFunktora(),nazwaE));
                  }

                  tak teraz wyglada usuwanie .. get_nazwa jest tu funkcja w klasie wodne wyłuskująca pole 'nazwa' bo inaczej nie ma do niej dostepu.. teraz wyskakuje mi blad : cannot resolve overloaded function `get_nazwa' based on conversion to type `const char *'
                  nie bardzo wiem o co chodzi..
                  • mastar1 Re: poprawka 20.11.04, 20:47
                    bo tak w ogole to klasa wodne jest podklasą dziedziczącą z klas nadrzednych.. np pole nazwa jest w klasie 'elektrownie'.. i funkcja get_nazwa jest przeciązana w kazdej kolejnej klasie i w lisciu zwraca nazwe
                  • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 20:53
                    Ustaw metodę get_nazwa klasy wodne jako const. Np.
                    class wodne
                    {
                    //...
                    const char* get_nazwa() const {return nazwa;}
                    };

                    Ewentualnie zamiast
                    > bool operator()(const wodne& a, const char* b) const
                    wstaw
                    > bool operator()(wodne& a, const char* b) const
                    • mastar1 Re: poprawka 20.11.04, 21:15
                      wlasnie to nie skutkuje.. nadal ten sam blad choc niby powinno byc dobrze. ani w jedna ani w druga strone nie da rady.. a nie ma jakiejs mozliwosci zeby iteratorami jakos to zrobic? z iteratorami jest jakos tak bardziej intuicyjnie :)
                      • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 21:25
                        l.listawodnych.remove((*iterW));
                        list<wodne>::iterator it = lista.begin();
                        while (it != l.listawodnych.end())
                        {
                        if (/*Tutaj sprawdzenie, czy element spelnia warunek*/)
                        l.listawodnych.erase(it++);
                        else
                        it++;
                        }
                        • Gość: flm Re: poprawka IP: 193.151.96.* 20.11.04, 21:27
                          Znowu błąd - pierwsza linijka niepotrzebna. Powinno być:
                          > list<wodne>::iterator it = l.listawodnych.begin();
                          > while (it != l.listawodnych.end())
                          > {
                          > if (/*Tutaj sprawdzenie, czy element spelnia warunek*/)
                          > l.listawodnych.erase(it++);
                          > else
                          > it++;
                          > }
                          • mastar1 Re: poprawka 20.11.04, 21:40
                            dziala! WIEEEELKIE DZIEKI człowieku:) jesli moge sie odwdzieczyc to byłoby ok:)
      • mastar1 Re: C++ STL lista usuwanie obiektów problem, help 20.11.04, 17:51
        char nazwaE[20];

        printf("\njaki obiekt zamierzasz usunac?\n");
        printf("podaj nazwe elektrowni: ");
        scanf("%s",nazwaE);
        list<wodne>::iterator iterW;
        for (iterW = l.listawodnych.begin(); iterW != l.listawodnych.end(); iterW++)
        {
        if (strcmp((*iterW).get_nazwa(),nazwaE) == 0)
        {
        //jak to kurna usuwac
        return;
        }
        }
        • Gość: tomcio Re: C++ STL lista usuwanie obiektów problem, help IP: *.neoplus.adsl.tpnet.pl 20.11.04, 19:01
          słonko,
          przeciąż operator==, żeby sprawdzał, czy nazwa elektrowni jest równa drugiemu
          argumentowi. wtedy

          lista.erase(
          remove(lista.begin(), lista.end(), nazwa),
          lista.end()
          );

          usunie wszystko co trzeba. buziaki!
          • mastar1 Re: C++ STL lista usuwanie obiektów problem, help 20.11.04, 19:08
            oj tomcio nie tedy droga.. ;)
Inne wątki na temat:

Nie masz jeszcze konta? Zarejestruj się


Nakarm Pajacyka