Menu
Coddy logo textTech

Iterator-Muster

Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 56 von 61.

Das Iterator-Muster bietet eine Möglichkeit, nacheinander auf die Elemente einer Sammlung zuzugreifen, ohne deren zugrunde liegende Struktur offenzulegen. Anstatt den Benutzern direkten Zugriff auf ein Array zu geben, geben Sie ihnen ein Objekt, das weiß, wie man die Daten Element für Element durchläuft.

Ein Iterator benötigt normalerweise zwei Informationen: eine Referenz auf die Sammlung und die aktuelle Position. In C erstellen wir ein struct, um diesen Zustand zu speichern:

typedef struct {
    int* data;      // Zeiger auf das Array
    int size;       // Gesamtzahl der Elemente
    int current;    // aktuelle Position
} IntIterator;

Der Iterator stellt zwei wichtige Funktionen bereit. has_next() prüft, ob weitere Elemente zum Lesen vorhanden sind, und next() gibt das aktuelle Element zurück und rückt die Position vor:

int has_next(IntIterator* it) {
    return it->current < it->size;
}

int next(IntIterator* it) {
    return it->data[it->current++];
}

Die Verwendung des Iterators sieht sauber aus und verbirgt die Details des Arrays:

IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
    printf("%d\n", next(&it));
}

Der Aufrufer muss nie wissen, dass numbers ein Array ist oder wie die Indizierung funktioniert. Diese Abstraktion macht es einfach, die zugrunde liegende Datenstruktur später zu ändern – zum Beispiel von einem Array zu einer verketteten Liste –, ohne den Code zu ändern, der den Iterator verwendet.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen NumberList-Iterator bauen — eine saubere Abstraktion, die es Ihnen ermöglicht, eine Sammlung von Ganzzahlen zu durchlaufen, ohne die zugrunde liegende Array-Struktur offenzulegen.

Sie werden Ihren Code in drei Dateien organisieren:

  • iterator.h: Definieren Sie ein IntIterator-Struct, das einen Zeiger auf ein Integer-Array, die Gesamtgröße der Sammlung und die aktuelle Position enthält. Deklarieren Sie drei Funktionen: create_iterator (nimmt einen Array-Zeiger und die Größe entgegen, gibt einen initialisierten Iterator zurück), has_next (prüft, ob weitere Elemente vorhanden sind) und next (gibt das aktuelle Element zurück und rückt die Position vor). Vergessen Sie die Include-Guards nicht!
  • iterator.c: Implementieren Sie Ihre Iterator-Funktionen. Die Funktion create_iterator sollte einen IntIterator als Wert zurückgeben, wobei die aktuelle Position auf 0 gesetzt ist. Die Funktion has_next gibt 1 zurück, wenn noch mehr Elemente zu lesen sind, andernfalls 0. Die Funktion next gibt das Element an der aktuellen Position zurück und erhöht dann die Position.
  • main.c: Lesen Sie die Anzahl der Elemente ein und lesen Sie dann jeden Integer-Wert in ein Array ein. Erstellen Sie einen Iterator für dieses Array und verwenden Sie dann eine while-Schleife mit has_next und next, um jedes Element zu durchlaufen und in einer eigenen Zeile auszugeben.

Ihr Programm erhält:

  1. Die Anzahl der Elemente im Array
  2. Jeden Integer-Wert in einer separaten Zeile

Verwenden Sie das Iterator-Muster, um alle Elemente auszugeben — keine direkte Array-Indizierung in Ihrer Traversierungsschleife!

Beispielhafte Ausgabe, wenn die Eingaben 4, dann 10, 20, 30, 40 sind:

10
20
30
40

Beispielhafte Ausgabe, wenn die Eingaben 3, dann -5, 0, 100 sind:

-5
0
100

Beispielhafte Ausgabe, wenn die Eingaben 1, dann 42 sind:

42

Der Iterator verbirgt, wie die Daten gespeichert sind — Ihre Hauptschleife fragt einfach "gibt es mehr?" und "gib mir das nächste", ohne etwas über Array-Indizes oder das Speicherlayout zu wissen.

Spickzettel

Das Iterator-Muster bietet eine Möglichkeit, sequenziell auf Elemente einer Sammlung zuzugreifen, ohne deren zugrunde liegende Struktur offenzulegen.

Ein Iterator-Struct enthält die Referenz auf die Sammlung, die Größe und die aktuelle Position:

typedef struct {
    int* data;      // Zeiger auf das Array
    int size;       // Gesamtzahl der Elemente
    int current;    // aktuelle Position
} IntIterator;

Der Iterator stellt zwei Schlüsselfunktionen bereit:

int has_next(IntIterator* it) {
    return it->current < it->size;
}

int next(IntIterator* it) {
    return it->data[it->current++];
}

Die Verwendung des Iterators verbirgt die Implementierungsdetails des Arrays:

IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
    printf("%d\n", next(&it));
}

Diese Abstraktion ermöglicht es, die zugrunde liegende Datenstruktur zu ändern, ohne den Client-Code modifizieren zu müssen.

Probier es selbst

#include <stdio.h>
#include "iterator.h"

int main() {
    int n;
    scanf("%d", &n);
    
    int arr[n];
    
    // TODO: Lies n ganzzahlige Werte in das Array ein
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    // TODO: Erstelle einen Iterator für das Array
    
    // TODO: Verwende eine while-Schleife mit has_next und next zum Durchlaufen
    // und gib jedes Element in einer eigenen Zeile aus
    // Verwende KEINE direkte Array-Indizierung in deiner Durchlaufschleife!
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Object Oriented Programming