Wzorzec iteratora
Część sekcji Programowanie obiektowe ścieżki C w Coddy. Lekcja 56 z 61.
Wzorzec iteratora zapewnia sposób sekwencyjnego dostępu do elementów kolekcji bez ujawniania jej wewnętrznej struktury. Zamiast zapewniać użytkownikom bezpośredni dostęp do tablicy, dajesz im obiekt, który wie, jak przechodzić przez dane po jednym elemencie naraz.
Iterator zazwyczaj potrzebuje dwóch informacji: odwołania do kolekcji i bieżącej pozycji. W C tworzymy strukturę, która przechowuje ten stan:
typedef struct {
int* data; // wskaźnik do tablicy
int size; // całkowita liczba elementów
int current; // bieżąca pozycja
} IntIterator;Iterator udostępnia dwie kluczowe funkcje. has_next() sprawdza, czy są jeszcze elementy do odczytania, a next() zwraca bieżący element i przesuwa pozycję:
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}Korzystanie z iteratora wygląda przejrzyście i ukrywa szczegóły dotyczące tablicy:
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}Wywołujący nigdy nie musi wiedzieć, że numbers jest tablicą ani jak działa indeksowanie. Ta abstrakcja ułatwia późniejszą zmianę bazowej struktury danych, na przykład z tablicy na listę wiązaną, bez zmieniania kodu, który korzysta z iteratora.
Wyzwanie
ŁatwyZbudujmy iterator NumberList: przejrzystą abstrakcję, która pozwala przechodzić przez kolekcję liczb całkowitych bez ujawniania struktury bazowej tablicy.
Rozmieścisz swój kod w trzech plikach:
iterator.h: Zdefiniuj strukturęIntIterator, która przechowuje wskaźnik do tablicy liczb całkowitych, całkowity rozmiar kolekcji oraz bieżącą pozycję. Zadeklaruj trzy funkcje:create_iterator(przyjmuje wskaźnik do tablicy i jej rozmiar, zwraca zainicjalizowany iterator),has_next(sprawdza, czy pozostały jeszcze elementy) inext(zwraca bieżący element i przesuwa pozycję). Nie zapomnij o strażnikach nagłówka!iterator.c: Zaimplementuj funkcje iteratora. Funkcjacreate_iteratorpowinna zwracać strukturęIntIteratorprzez wartość, z bieżącą pozycją ustawioną na 0. Funkcjahas_nextzwraca 1, jeśli są jeszcze elementy do odczytania, a w przeciwnym razie 0. Funkcjanextzwraca element z bieżącej pozycji, a następnie ją zwiększa.main.c: Wczytaj liczbę elementów, a następnie wczytaj każdą liczbę całkowitą do tablicy. Utwórz iterator dla tej tablicy, a następnie użyj pętli while z funkcjamihas_nextinext, aby przejść przez elementy i wypisać każdy w osobnym wierszu.
Twój program otrzyma:
- Liczbę elementów w tablicy
- Każdą liczbę całkowitą w osobnym wierszu
Użyj wzorca iteratora, aby wypisać wszystkie elementy: w pętli przechodzącej przez elementy nie używaj bezpośredniego indeksowania tablicy!
Przykładowe wyjście dla danych wejściowych 4, a następnie 10, 20, 30, 40:
10
20
30
40Przykładowe wyjście dla danych wejściowych 3, a następnie -5, 0, 100:
-5
0
100Przykładowe wyjście dla danych wejściowych 1, a następnie 42:
42Iterator ukrywa sposób przechowywania danych. Twoja główna pętla po prostu pyta „czy są jeszcze jakieś?” i „daj mi następny element”, nie wiedząc nic o indeksach tablicy ani układzie pamięci.
Spróbuj swoich sił
#include <stdio.h>
#include "iterator.h"
int main() {
int n;
scanf("%d", &n);
int arr[n];
// TODO: Wczytaj n liczb całkowitych do tablicy
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// TODO: Utwórz iterator dla tablicy
// TODO: Użyj pętli while oraz has_next i next, aby przejść przez tablicę
// i wypisz każdy element w osobnym wierszu
// NIE używaj bezpośredniego indeksowania tablicy w pętli przechodzącej przez tablicę!
return 0;
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania modularnego
Pliki nagłówkoweZabezpieczenia przed wielokrotnym dołączeniemPliki źródłoweFunkcje statycznePodsumowanie: kalkulator modularny4Enkapsulacja
Koncepcja niejawnych wskaźnikówDefiniowanie niejawnych strukturGettery i setteryWalidacja w setterachPowtórka: tajemnicze pudełko2Obiekty i metody
Struktury jako obiektyWskaźnik „self”Poprawność constWskaźnik czy wartośćMetody pomocniczePodsumowanie: menedżer punktów5Projekt: Proste konto bankowe
Konfiguracja projektuImplementacja konta8Polimorfizm
Wskaźniki do funkcji w strukturachSymulowanie metodKoncepcja interfejsuImplementowanie interfejsówIteracja polimorficznaPodsumowanie: Greeter11Wzorce projektowe w C
Wzorzec SingletonWzorzec fabrykiWzorzec iteratoraPodsumowanie: fabryka loggera3Cykl życia obiektu
Wzorzec konstruktoraWzorzec destruktoraInicjalizacja na stosieKopia głębokaPodsumowanie: klasa opakowująca ciąg znaków6Dziedziczenie przez kompozycję
Osadzanie strukturZasada pierwszego elementuDostęp do elementów klasy nadrzędnejKonwersja w górę hierarchiiPodsumowanie: hierarchia kształtów9Projekt: Rysownik kształtów
Przegląd projektuImplementacja kołaImplementacja prostokątaZastosowanie polimorfizmuKontener kształtówPoćwicz samodzielnie: Kompilator C online