פרק 4ב' - הרחבת תחביר לולאת for


לולאות for — תחביר גמיש ויצירתי

בקצרה: לולאת for בשפת #C מאפשרת תחביר גמיש במיוחד, וניתן להשתמש באלמנטים לא שגרתיים כדי לפתור בעיות בצורה יצירתית. בפרק זה נחקור תבניות מתקדמות ונדגים שימושים בעזרת דוגמאות קצרות.

שמירה על ערך האינדקס לאחר הלולאה

בתחביר הרגיל משתנה הלולאה מאבד את התוקף שלו לאחר הלולאה (לא רק את ערכו - הוא כלל אינו קיים!). ניתן לשנות את הכתיבה כך שמשתנה הלולאה ישמור את תוקפו וערכו גם לאחר סיום הלולאה.

int i;
for (i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}
Console.WriteLine("Index after loop: " + i);
שאלה: מה יודפס?

תשובה:

0
1
2
3
4
Index after loop: 5

חשוב לדעת שתוקף של משתנה (scope) מוגבל לבלוק {...} שבתוכו הוכרז. בדרך כלל מכריזים על משתנים בתחילת התכנית אך לא תמיד. במקרה של לולאה, כברירת מחדל, משתנה האינדקס מוכרז כחלק מתחביר הלולאה ולכן אינו בתוקף מחוצה לה.

אתחול מרובה בלולאה אחת:

ניתן לאתחל כמה משתנים יחד בתחילת הלולאה.

for (int i = 0, j = 10; i < j; i++, j--)
{
    Console.WriteLine($"i = {i}, j = {j}");
}

שרשור מחרוזות: בלולאה זו השתמשנו ב-$ כתחביר מומלץ ונח לשירשור מחרוזות (string concatenation). תחביר דומה משמש גם בפייתון כאשר משתמשים בתחילית ‘f לפני המחרוזת. לא קיים ב-JAVA

תנאים מרובים ועדכונים מרובים:

ניתן לכתוב תנאי הפסקה מורכב יותר, כולל פעולות רבות בכל שלב.

int a = 0, b = 10;
for (; a < 5 && b > 5; a++, b -= 2)
{
    Console.WriteLine($"a={a}, b={b}");
}

דילוג על האתחול בלולאה:

כאשר משתנה האינדקס מאותחל קודם, ניתן לדלג על שלב האתחול:

int i = 3;
for (; i < 6; i++)
{
    Console.WriteLine(i);
}

דילוג על שלב ההוספה:

ניתן לשים את עדכון האינדקס בתוך גוף הלולאה:

for (int i = 0; i < 3;)
{
    Console.WriteLine(i);
    i++; // העדכון בתוך הגוף
}

שינוי ערך i בתוך הלולאה כדי “להאריך” אותה:

שימוש בטריק זה נפוץ כאשר רוצים לחזור על אינפוט שנכשל בבדיקה.

for (int i = 0; i < 3; i++)
{
    Console.Write("Enter a positive number: ");
    int n = int.Parse(Console.ReadLine());
    if (n <= 0)
    {
        Console.WriteLine("Invalid input, try again.");
        i--; // מבטל את הסבב הנוכחי
    }
}

שימוש ב-continue כדי לדלג על שאר הקוד בלולאה

for (int i = 0; i < 5; i++)
{
    if (i % 2 == 0)
        continue; // קפיצה לסיבוב הבא. דילוג על מספרים זוגיים

    Console.WriteLine(i); // יודפסו רק אי-זוגיים
}

הדוגמא לעיל היא רק לצורך הסבר על תפקיד המילה continue. ניתן לא ללמד את התלמידים את המילה continue, ועדיף לצמצם את השימוש בה מפני שהיא עלולה ליצור קוד מטעה. כאן כמובן עדיף “למצוא” את האי-זוגיים בצורה דטרמיניסטית (בדרך מוכוונת, להלן):

for (int i = 1; i < 5; i += 2) // 2 -קידום מונה הלולאה ב
    Console.WriteLine(i); // יודפסו רק אי-זוגיים

הקיצור forr⟶⟶: לולאה יורדת (מהסוף להתחלה):

זהו קיצור שימושי ב-Visual Studio ללולאה הפוכה:

for (int i = 3 - 1; i >= 0; i--) // חשוב לזכור תחביר וקיצור זה לקורס הבא
{
    Console.WriteLine(i);
}
מה התוצאה של לולאה כזו?

תשובה:

2
1
0

טבלת סיכום

תחביר תיאור
for (int i = 0, j = 2; ...) הכרזה ואיתחול של משתנים מרובים
for (; i < 10;) אסור: דילוג על האתחול ועל קידום מונה הלולאה
for (int i = 0;; i++) אסור: לולאה אינסופית (השמטת תנאי עצירה)
i-- כשמופיע בתוך הלולאה: אסור: הרחבת הלולאה במקרה חריג
continue רק במקרים חריגים: דילוג על המשך גוף הלולאה עד למחזור הבא

טיפ: תבניות אלו מתקמפלות ועובדות. אף על פי כן בחלקן יש לאסור שימוש. הסיבה היא שתחביר כזה פוגע ב-code intent. בכתיבת קוד יש דברים מסויימים שהקורא מצפה להם כשהוא מסתכל על הקוד. בין היתר לתחביר סטנדרטי מפני שכך ניתן להסיק בקלות מה אמור לקרות בתוך הלולאה מבלי שיהיו הפתעות. במילים אחרות התחביר אמור לשקף עד כמה שניתן את מה שהולך לקרות ולא להסוות את מה שהולך לקרות. חלק חשוב בכתיבת קוד הוא כתיבת קוד קריא! MISRA C:2012 Rule 14.2: A for loop shall be well-formed

תרגול

⬅ עבור לתרגול 4.1 - לולאות for: שארית חלוקה

⬅ עבור לתרגול 4.2 - לולאות for: מונה, צובר, מינימום ומקסימום

⬅ עבור לתרגול 4.3 לולאות for: מינימום מקסימום ספירה צבירה ושארית חלוקה

סרטונים

סרטוני פרק 6: לולאות for