Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Implementacja szablonowa pojemnika vector i lista

Ostatnio zmodyfikowano 2025-06-04 00:26
Autor Wiadomość
Miquel
Temat założony przez niniejszego użytkownika
Implementacja szablonowa pojemnika vector i lista
» 2013-02-21 17:04:12
Witam,

na uczelni za zadanie na jednych laboratoriach mamy zrobic pojemnik na dowolne obiekty w implementacji wektorowej oraz listowej. Do tego nalezy zastosowac iteratory w tych pojemnikach.

Moj problem polega na tym, ze chcialbym w petlach wyswietlac zawartosc calego pojemnika wg. skladni zadanej w sekcji main.
Niestety aktualnie ostatni element jest pomijany. Jestem swiadom, ze to przez wlasciwosc petli for, narazie jedynym rozwiazaniem jakie wymyslilem jest wykonywanie polecenia w 3-ciej sekcji petli, co nie jest satysfakcjonujace. PS. iterator jest ustawiany na ten ostatni element.

Prosze o sugestie w jaki sposob zmienic zawartosc iteratorow, by uzyskac oczekiwany rezultat.
 
PS:Uprzedzajac komentarze o braku destruktorow, itp. Narazie bawilem sie w uruchomienie kodu testowego.

Kod źrodlowy:
http://wklej.org/id/962065/

P-76625
domin568
» 2013-02-21 17:18:16
Nie wiem o co ci chodzi , ale w pętli for spróbuj użyć preinkrementacji , powinna się wykonać raz jeszcze .
P-76627
Miquel
Temat założony przez niniejszego użytkownika
» 2013-02-21 17:31:33
W kodzie przeciez zostaly uzyte same preinkrementacje. Tylko co z tego jak przy warunku roznosci (!=) ostatniego elementu, nie jest ona spelniona, przez co nie wykonuje sie zawartosc.

Chce by bez modyfikacji kodu testowego wyswietlac cala zawartosc pojemnika.
P-76631
domin568
» 2013-02-21 17:37:41
Jak mamy ci pomoc jak nie znamy kodu źródłowego ??
P-76632
Miquel
Temat założony przez niniejszego użytkownika
» 2013-02-21 17:40:48
Kod byl caly czas w linku, zapomnialem opisac, ze tam trzeba sie kierowac :P
P-76633
unimator
» 2013-02-21 18:04:06
1. Serio musisz sobie komplikować życie z tymi iteratorami? Metoda, która jest wewnątrz tej klasy do wypisywania elementów jest o wiele klarowniejsza i prostsza = lepsza.
2. Pewnie się zdziwisz, ale rozwiązanie Twojego problemu jest banalne :P Wygląda mniej więcej tak:
C/C++
for( List < int >::Iterator iter = lst.begin(); iter != NULL; ++iter )
     cout << * iter << endl;

P-76635
Miquel
Temat założony przez niniejszego użytkownika
» 2013-02-21 18:33:30
Tzn. w tym przypadku rowniez nigdy, bym nie uzyl iteratora do wyswietlania wartosci;D
Ale taki kod testowy i z czystej ciekawosci chcialem wiedziec czy da sie tak zrobic.

Co do rozwiazania problemu to fajne spostrzezenie i dzieki za nie. Przynajmniej wiem, ze musze czesciej analizowac kod;)

Rozwiazanie dalej nie jest pelne, bo dla pojemnika Table jest kiszka ;D

Chyba jedynie pozostanie przedefiniowanie operatora != by mial zmienna stanu odliczajaca uzycia po spelnieniu warunku.
P-76641
termistor
» 2025-06-04 00:26:43
Witaj Miquel!  
Z Twojego opisu wynika, że problem polega na niewłaściwym zakończeniu pętli iteratorowej. W klasycznych kontenerach STL (np. `std::vector`, `std::list`) pętla wygląda tak:  
 
for (Iterator iter = begin(); iter != end(); ++iter) {  
    cout << *iter << endl;  
}  
 
Kluczowe jest porównanie `iter != end()`, gdzie `end()` zwraca iterator wskazujący **poza ostatni element**. Jeśli Twój kontener `Table` (albo `List`) zwraca `end()` jako iterator wskazujący **na ostatni element**, pętla zakończy się przed jego wypisaniem.  

### Rozwiązanie ogólne  
Upewnij się, że metoda `end()` zwraca iterator wskazujący **poza ostatni element**. Przykład dla kontenera vectorowego:  
 
template <typename T>  
class Table {  
public:  
    class Iterator {  
        // ...  
    };  
    Iterator begin() { return Iterator(data_); }  
    Iterator end() { return Iterator(data_ + size_); } // <--- kluczowy fragment  
};  
 
Jeśli `end()` zwraca `data_ + size_`, pętla `for` będzie działać poprawnie.  

### Dla kontenera listowego  
Dla listy dwukierunkowej (np. `std::list`), `end()` powinien zwracać iterator wskazujący **na NULL** (lub pusty wskaźnik). Przykład:  
 
template <typename T>  
class List {  
public:  
    class Iterator {  
        Node* current_;  
    public:  
        bool operator!=(const Iterator& other) const {  
            return current_ != other.current_;  
        }  
    };  
    Iterator begin() { return Iterator(head_); }  
    Iterator end() { return Iterator(nullptr); } // <--- kluczowy fragment  
};  
 
Wtedy pętla:  
 
for (List<int>::Iterator iter = lst.begin(); iter != lst.end(); ++iter) {  
    cout << *iter << endl;  
}  
 
przejdzie przez wszystkie elementy.  

### Jeśli `end()` wskazuje na ostatni element  
Jeśli Twój kontener `end()` zwraca iterator wskazujący **na ostatni element**, pętla zakończy się przed nim. Wtedy musisz:  
1. Zmienić `end()` tak, by wskazywał **poza ostatni element** (najlepsze rozwiązanie).  
2. Użyć pętli z warunkiem `iter != end() && ++iter != end()` (mniej eleganckie). Przykład:  
 
for (Iterator iter = begin(); iter != end(); ++iter) {  
    cout << *iter << endl;  
}  
// Ale jeśli `end()` wskazuje na ostatni element, dodaj:  
for (Iterator iter = begin(); iter != end(); ++iter) {  
    cout << *iter << endl;  
}  
// ... lub poza pętlą dodatkowo wypisz ostatni element.  
 

### Przedefiniowanie operatora `!=`  
Jeśli chcesz przedefiniować operator `!=`, musisz przechowywać stan iteratora (np. licznik). Przykład:  
 
class Iterator {  
    int count_;  
public:  
    bool operator!=(const Iterator& other) const {  
        return count_ != other.count_;  
    }  
};  
 
Jednak to komplikuje kod i nie jest standardem. Lepsze jest poprawne implementowanie `begin()` i `end()`.  

### Podsumowanie  
- Upewnij się, że `end()` zwraca iterator **poza ostatni element**.  
- Użyj standardowej pętli `for (iter = begin(); iter != end(); ++iter)`.  
- Jeśli kontener `Table` nie spełnia tych wymagań, popraw jego implementację.  

Jeśli podasz kod źródłowy kontenerów (np. `Table` i `List`), mogę wskazać konkretne miejsce do poprawki.  

Powodzenia!
P-182465
« 1 »
  Strona 1 z 1