מבוא לתכנות ולמדעי המחשב בשפת C/לולאות while, do while, break, continue
כל תוכניות המחשב שראינו עד כה בוצעו כסדרה סופית של פקודות ללא חזרה. במקרים רבים נרצה להגיד למחשב לחזור על סדרה של פעולות שוב ושוב עד שיתקיים תנאי מסויים. המנגנון שמאפשר זאת בשפות תכנות נקרא לולאה (loop). שימוש בלולאות מאפשר כתיבת תוכניות המסוגלות לבצע משימות הרבה יותר מעניינות.
לולאת while
[עריכה]לולאת while היא סדרת פקודות (בלוק קוד) שמבוצעת שוב ושוב כל עוד תנאי מסויים מתקיים. לדוגמה:
#include <stdio.h>
int main() {
int i = 0;
while(i < 10) {
i = i+2; // same as i += 2
printf("i=%d\n",i);
}
return 0;
}
פלט:
i=2
i=4
i=6
i=8
i=10
הסבר: שורה 6 היא השורה בה מתחילה הלולאה. המילה השמורה while פותחת סדרת פקודות שיתבצעו שוב ושוב כל עוד התנאי שבתוך ה while מתקיים, במקרה זה כל עוד ערך המשתנה i קטן מ 10.
גוף הלולאה כולל שתי פקודות. הפקודה הראשונה בשורה 8 גורמת להגדלה של ערך המשתנה i ב שתיים. השורה השניה (9) מדפיסה את הערך של i על המסך. לפני הכניסה ללולאה מאותחל ערך המשתנה i להיות 0 (שורה 5). בפעם השראשונה שגוף הלולאה מתבצע, הערך של i עולה ל 2 ואז מודפס על המסך. מכיוון שערך זה עדיין קטן מ 10 הלולאה מתבצעת שוב, הערך גודל ל 4 ומודפס. התהליך חוזר על עצמו עד שהערך מגיע ל 10 ומודפס. בשלב זה הערך של i איננו קטן מ 10 (הוא בדיוק 10), תנאי הלולאה לא מתקיים ולכן היא לא ממשיכה להתבצע.
הדוגמה הבאה משתמשת בלולאת while לחישוב עצרת:
#include <stdio.h>
int main() {
int n,f=1;
printf("Please enter the value of n: "); scanf("%d",&n);
while(n>0) {
f *= n;
--n;
}
printf("n! = %d\n",f);
return 0;
}
פלט:
Please enter the value of n: 5
n! = 120
בלולאת while הדבר הראשון שקורה הוא בדיקת התנאי ליציאה מהלולאה. לאחר מכן מתבצעות הפקודות בסדר מעגלי. כמתכנתים יש לנו יכולת לקבוע את נקודת הכניסה למעגל הזה ע"י רוטציה של הפקודות בגוף הלולאה. למרות החופש לקבוע את נקודת הכניסה, תמיד יבדק תנאי היציאה לפני ביצוע הפקודות.
האיור הבא מדגים זאת:
לולאת do while
[עריכה]לולאת do while דומה לולאת while בהבדל אחד: תנאי היציאה נבדק רק לאחר השלמת סבב אחד של הפקודות בגוף הלולאה.
הדוגמה הבאה משתמשת בסוג כזה של לולאה על מנת למצוא את האיבר הראשון בסדרת הסכומים החלקיים של סדרת הטבעיים שגדול מ 100:
#include <stdio.h>
int main() {
int i = 1, s = 0;
do {
s += i;
printf("%d, ",s);
++i;
} while (s <= 100);
printf("\ni=%d, s=%d \n",i,s);
return 0;
}
פלט:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105,
i=15, s=105
במקרה זה היה הגיון להשתמש בסוג זה של לולאה מכיוון שרק אחרי פעם אחד שגוף הלולאה מבוצע, יש משמעות לתנאי היציאה.
האיור הבא מדגים את היחס בין נקודת הכניסה ללולאה לבין בדיקת תנאי היציאה:
break
[עריכה]הפקודה break מאפשרת לצאת מגוף הלולאה מהמקום בו היא מופיעה. בעזרת פקודה זו אפשר למקם את נקודת היציאה בכל מקום במעגל הלולאות. ניתן גם למקם מספר נקודות יציאה.
הדוגמה הבאה משתמשת ב break על מנת לצאת מלולאה אין סופית. ב C כל ערך השונה מ 0 נחשב "אמת" כאשר הוא נבחן כתנאי והערך 0 נחשב כ "שקר". לכן לולאה שתנאי הקיום שלה הוא 1 היא לולאה שתמשך לנצח אם לא תופסק באמצעות break בגופה.
#include <stdio.h>
int main() {
int n;
while (1) {
printf("Please enter 17 to stop or any other number to continue\n");
scanf("%d",&n);
if(n==17)
break;
printf("Ok, you have entered %d so we continue..\n",n);
}
printf("Well, that's about it\n");
return 0;
}
פלט:
Please enter 17 to stop or any other number to continue
2
Ok, you have entered 2 so we continue..
Please enter 17 to stop or any other number to continue
129
Ok, you have entered 129 so we continue..
Please enter 17 to stop or any other number to continue
17
Well, that's about it
האיור הבא מדגים לולאה עם שתי יציאות באמצעות break:
לולאה אין סופית עם נקודת (או נקודות) break היא בעצם הלולאה הכללית ביותר, זאת שמאפשרת לנו כמתכנתים חופש מוחלט היכן אנו מעוניינים להכנס למעגל הפקודות והיכן לצאת ממנו. יש הרואים בשימוש בלולאה כזו, סגנון תכנות לקוי מכיוון שלא תמיד ברור לקורא מתי לולאה כזו מסתיימת וכמה פעמים היא תעבוד. לעיתים נמנעים משימוש בלולאה אין סופית ע"י שכפול קוד. לדוגמה, את הדוגמה האחרונה, ניתן לכתוב גם כך:
#include <stdio.h>
int main() {
int n;
printf("Please enter 17 to stop or any other number to continue\n");
scanf("%d",&n);
while (n != 17) {
printf("Ok, you have entered %d so we continue..\n",n);
printf("Please enter 17 to stop or any other number to continue\n");
scanf("%d",&n);
}
printf("Well, that's about it\n");
return 0;
}
החלק האחראי על קליטת הנתון מהמשתמש שוכפל וכך הצלחנו לייצר מצב שנקודת הכניסה ללולאה נמצאת במקום שונה מנקודת היציאה. בדרך כלל שיכפול קוד אינו רעיון טוב. הבעיה העקרית בו היא קושי בתחזוקה. כל פעם שנרצה לשנות אותוף נצטרך לזכור לשנות אותו בשני המקומות. אם נשכח, נקבל קוד לא עקבי. במקרה זה ניתן להמנע משכפול הקוד ע"י שימוש בפונקציות (נלמד בהמשך).
באופן אישי, אינני חושב ששימוש בלולאות אין סופיות עם תנאי יציאה הם בהכרח סגנון תכנות לקוי. לדעתי, אם כותבים קוד נקי וברור, אפשר ואף רצוי להשתמש בהן לעיתים.
continue
[עריכה]במקרים מסויימים אנו רוצים להמשיך לאיטרציה הבאה של הלולאה בלי לסיים את זו שבה אנו נמצאים. עבור מקרים כאלה קיימת הפקודה continue שמעותה "המשך לאיטרציה הבאה". לדוגמה:
#include <stdio.h>
int main() {
int i=0;
while(i<7) {
if(i == 4) {
printf("Hey, it's four!\n");
++i;
continue;
}
printf("i=%d\n",i);
++i;
}
return 0;
}
פלט:
i=0
i=1
i=2
i=3
Hey, it's four!
i=5
i=6