Menu
Coddy logo textTech

תבנית Iterator

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C של Coddy. שיעור 56 מתוך 61.

תבנית האיטרטור מספקת דרך לגשת ברצף לאיברים של אוסף בלי לחשוף את המבנה הפנימי שלו. במקום לתת למשתמשים גישה ישירה למערך, נותנים להם אובייקט שיודע לעבור על הנתונים, איבר אחד בכל פעם.

איטרטור זקוק בדרך כלל לשני פרטי מידע: הפניה לאוסף והמיקום הנוכחי. ב־C, ניצור מבנה כדי לאחסן את המצב הזה:

typedef struct {
    int* data;      // מצביע למערך
    int size;       // מספר האיברים הכולל
    int current;    // המיקום הנוכחי
} IntIterator;

האיטרטור חושף שתי פונקציות מרכזיות. has_next() בודקת אם יש עוד איברים לקרוא, ו-next() מחזירה את האיבר הנוכחי ומקדמת את המיקום:

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

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

השימוש באיטרטור נראה נקי ומסתיר את פרטי המערך:

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

הקוד שקורא לפונקציה אף פעם לא צריך לדעת ש־numbers הוא מערך או איך פועל האינדוקס. ההפשטה הזאת מקלה על שינוי מבנה הנתונים הבסיסי בהמשך, ממערך לרשימה מקושרת, למשל, בלי לשנות את הקוד שמשתמש באיטרטור.

challenge icon

אתגר

קל

בואו נבנה איטרטור NumberList: הפשטה נקייה שמאפשרת לך לעבור על אוסף של מספרים שלמים בלי לחשוף את מבנה המערך שמתחתיו.

תארגן את הקוד שלך בשלושה קבצים:

  • iterator.h: הגדר מבנה IntIterator שמכיל מצביע למערך של מספרים שלמים, את הגודל הכולל של האוסף ואת המיקום הנוכחי. הכרז על שלוש פונקציות: create_iterator (מקבלת מצביע למערך ואת הגודל, ומחזירה איטרטור מאותחל), has_next (בודקת אם נותרו איברים נוספים) ו-next (מחזירה את האיבר הנוכחי ומקדמת את המיקום). אל תשכח guards למניעת הכללה כפולה!
  • iterator.c: ממש את פונקציות האיטרטור שלך. הפונקציה create_iterator צריכה להחזיר IntIterator לפי ערך, כשהמיקום הנוכחי מוגדר ל-0. הפונקציה has_next מחזירה 1 אם יש איברים נוספים לקריאה, ואחרת 0. הפונקציה next מחזירה את האיבר במיקום הנוכחי ואז מקדמת את המיקום.
  • main.c: קרא את מספר האיברים, ואז קרא כל ערך של מספר שלם לתוך מערך. צור איטרטור עבור המערך הזה, ואז השתמש בלולאת while עם has_next ו-next כדי לעבור על האיברים ולהדפיס כל אחד בשורה משלו.

התוכנית שלך תקבל:

  1. את מספר האיברים במערך
  2. כל ערך של מספר שלם בשורה נפרדת

השתמש בתבנית האיטרטור כדי להדפיס את כל האיברים: אל תיגש ישירות למערך באמצעות אינדקסים בלולאת המעבר!

דוגמת פלט כשהקלטים הם 4, ואז 10, 20, 30, 40:

10
20
30
40

דוגמת פלט כשהקלטים הם 3, ואז -5, 0, 100:

-5
0
100

דוגמת פלט כשהקלטים הם 1, ואז 42:

42

האיטרטור מסתיר את אופן אחסון הנתונים. הלולאה הראשית שלך פשוט שואלת "האם יש עוד?" ו"תן לי את הבא" בלי לדעת דבר על אינדקסים של מערך או על מבנה הזיכרון.

נסו בעצמכם

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

int main() {
    int n;
    scanf("%d", &n);
    
    int arr[n];
    
    // TODO: קראו n ערכים שלמים לתוך המערך
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    // TODO: צרו איטרטור עבור המערך
    
    // TODO: השתמשו בלולאת while עם has_next ו-next כדי לעבור על המערך
    // והדפיסו כל איבר בשורה נפרדת
    // אל תשתמשו בגישה ישירה לאיברי המערך באמצעות אינדקס בלולאת המעבר!
    
    return 0;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C אונליין