İteratör Kalıbı
Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 56 / 61.
Iterator deseni, bir koleksiyonun öğelerine, koleksiyonun alt yapısını ifşa etmeden sıralı bir şekilde erişmek için bir yol sağlar. Kullanıcılara bir diziye doğrudan erişim vermek yerine, onlara veriler arasında her seferinde bir öğe olacak şekilde nasıl ilerleyeceğini bilen bir nesne verirsiniz.
Bir yineleyici (iterator) genellikle iki bilgiye ihtiyaç duyar: koleksiyona bir referans ve mevcut konum. C'de, bu durumu tutmak için bir struct oluştururuz:
typedef struct {
int* data; // dizi işaretçisi
int size; // toplam eleman sayısı
int current; // mevcut konum
} IntIterator;İteratör iki ana fonksiyon sunar. has_next() okunacak daha fazla öğe olup olmadığını kontrol eder ve next() mevcut öğeyi döndürerek konumu ilerletir:
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}İteratörü kullanmak temiz görünür ve dizi detaylarını gizler:
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}Çağıranın, numbers değişkeninin bir dizi olduğunu veya indekslemenin nasıl çalıştığını bilmesine asla gerek yoktur. Bu soyutlama, temel veri yapısını daha sonra — örneğin bir diziden bağlı listeye — yineleyiciyi (iterator) kullanan kodu değiştirmeden değiştirmeyi kolaylaştırır.
Görev
KolayBir NumberList yineleyicisi (iterator) oluşturalım — bu, temel dizi yapısını açığa çıkarmadan bir tam sayı koleksiyonu üzerinde gezinmenizi sağlayan temiz bir soyutlamadır.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
iterator.h: Bir tam sayı dizisine işaretçi, koleksiyonun toplam boyutu ve mevcut konumu tutan birIntIteratoryapısı (struct) tanımlayın. Üç fonksiyon bildirin:create_iterator(bir dizi işaretçisi ve boyut alır, başlatılmış bir yineleyici döndürür),has_next(daha fazla eleman kalıp kalmadığını kontrol eder) venext(mevcut elemanı döndürür ve konumu ilerletir). Include guard'ları eklemeyi unutmayın!iterator.c: Yineleyici fonksiyonlarınızı uygulayın.create_iteratorfonksiyonu, mevcut konumu 0 olarak ayarlanmış birIntIteratordeğerini döndürmelidir.has_nextfonksiyonu, okunacak daha fazla eleman varsa 1, aksi takdirde 0 döndürür.nextfonksiyonu, mevcut konumdaki elemanı döndürür ve ardından konumu artırır.main.c: Eleman sayısını okuyun, ardından her bir tam sayı değerini bir diziye okuyun. Bu dizi için bir yineleyici oluşturun, ardından her bir elemanı kendi satırında gezinmek ve yazdırmak içinhas_nextvenextile bir while döngüsü kullanın.
Programınız şunları alacaktır:
- Dizideki eleman sayısı
- Her bir tam sayı değeri ayrı bir satırda
Tüm elemanları yazdırmak için yineleyici desenini (iterator pattern) kullanın — gezinme döngünüzde doğrudan dizi indeksleme yapmayın!
Girdiler 4, ardından 10, 20, 30, 40 olduğunda örnek çıktı:
10
20
30
40Girdiler 3, ardından -5, 0, 100 olduğunda örnek çıktı:
-5
0
100Girdiler 1, ardından 42 olduğunda örnek çıktı:
42Yineleyici, verilerin nasıl saklandığını gizler — ana döngünüz, dizi indeksleri veya bellek düzeni hakkında hiçbir şey bilmeden sadece "daha fazlası var mı?" ve "bana bir sonrakini ver" diye sorar.
Kopya kağıdı
Iterator deseni, bir koleksiyonun öğelerine, temel yapısını açığa çıkarmadan sıralı bir şekilde erişme yolu sağlar.
Bir iterator yapısı (struct), koleksiyon referansını, boyutunu ve mevcut konumunu tutar:
typedef struct {
int* data; // diziye işaretçi
int size; // toplam öğe sayısı
int current; // mevcut konum
} IntIterator;Iterator iki ana fonksiyon sunar:
int has_next(IntIterator* it) {
return it->current < it->size;
}
int next(IntIterator* it) {
return it->data[it->current++];
}Iterator kullanmak, dizi uygulama detaylarını gizler:
IntIterator it = create_iterator(numbers, 5);
while (has_next(&it)) {
printf("%d\n", next(&it));
}Bu soyutlama, istemci kodunu değiştirmeden temel veri yapısının değiştirilmesine olanak tanır.
Kendin dene
#include <stdio.h>
#include "iterator.h"
int main() {
int n;
scanf("%d", &n);
int arr[n];
// TODO: n tane tam sayı değerini diziye oku
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// TODO: Dizi için bir iterator oluştur
// TODO: Gezinmek için has_next ve next ile bir while döngüsü kullan
// ve her bir öğeyi kendi satırına yazdır
// Gezinme döngünüzde doğrudan dizi indeksleme KULLANMAYIN!
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1Modüler Programlama Temelleri
Başlık DosyalarıInclude Guard'larKaynak DosyalarıStatik FonksiyonlarÖzet: Modüler Hesap Makinesi4Kapsülleme
Opaque Pointer KavramıOpaque Struct TanımlamaGetter ve Setter MetotlarıSetter Metotlarında DoğrulamaÖzet: Gizli Kutu2Nesneler ve Metotlar
Nesne Olarak Struct'lar'Self' İşaretçisiConst Doğruluğuİşaretçi vs DeğerYardımcı MetotlarÖzet: Point Manager5Proje: Basit Banka Hesabı
Proje KurulumuHesabın Oluşturulması3Nesne Yaşam Döngüsü
Constructor DeseniDestructor DeseniStack İlklendirmeDerin KopyalamaÖzet: String Wrapper6Kompozisyon Yoluyla Kalıtım
Struct Gömmeİlk Üye KuralıÜst Üyelere ErişimUpcastingÖzet: Şekil Hiyerarşisi