ב-Online
 
 
 
 
 
 
 
לפרק את הבייט 
להיכנס ללולאה 
 
  צילום: פליקר, martial ( areyoutalkingtome ), רשיון cc by    
לפרק את הבייט |
 

לומדים לתכנת? מסתבכים עם כל עניין הלולאות? עידו גנדל יסביר לכם את התיאוריה והמימושים של הלולאה (ויסבך אתכם עוד קצת)

 
 
 
 
 
 
 
 
 
 
פליקר, A. Belani, רשיון cc by sa
 פליקר, A. Belani, רשיון cc by sa   
כשאנו רק מתחילים ללמוד מחשבים, מספרים לנו שתוכנה – או אלגוריתם ממוחשב, לצורך העניין – הם פשוט "אוסף של פקודות". זה אולי נכון, אבל נורא כוללני וחוטא לאמת, קצת כמו להגדיר את התנ"ך כ"אוסף של אותיות".

בתור התחלה, גם אם לא נתייחס כלל לפרטים של שפת תכנות ספציפית כלשהי, קל לראות שיש שתי קטגוריות שונות של פקודות. הראשונה היא פקודות "ישירות", או "מסדר ראשון", שפועלות באופן מיידי על משהו מוחשי יחסית: משנות ערך של משתנה בזיכרון, מציירות פיקסל על המסך, פותחות קובץ וכן הלאה. הקטגוריה השניה, לעומת זאת, כוללת פקודות מסדר שני שכל תפקידן הוא לנהל את הפקודות מהסדר הראשון. פקודות אלה שייכות למה שמכונה "זרימת בקרה" (Control Flow – לא לבלבל עם "בקרת זרימה" שזה משהו אחר לגמרי): הן אינן מבצעות פעולות ישירות בעצמן, אלא פשוט קובעות אילו מהפקודות מסדר ראשון יבוצעו ומתי.
 

פקודות זרימת בקרה

 
לדוגמה, אחת הפקודות הבסיסיות ביותר בכל שפת תכנות גבוהה היא פקודת "אם-אז" (If-Then). הסתכלו על הקוד הגנרי "If X then Y". פקודה זו בודקת אם התנאי X מתקיים, ואם כן, היא מפעילה את הפקודה Y. אם X לא מתקיים, Y לא תרוץ. פקודת ה-If עצמה לא משאירה, כביכול, שום עדויות: כל המשתנים בזיכרון נשארו כמות שהם, שום מידע "ממשי" לא נקרא או נכתב. הדבר היחיד שמשתנה בגללה הוא רצף הפקודות של התוכנה.

עקרונית, אפשר לכתוב תוכנה עם פקודות מסדר ראשון בלבד, אך היא תהיה מוגבלת ביותר. למשל, נניח שאנחנו רוצים תוכנה שכותבת את כל המספרים בין 1 ל-5. עם פקודות מסדר ראשון בלבד, היא עלולה להיראות כך:

כתוב "1"
כתוב "2"
כתוב "3"
כתוב "4"
כתוב "5"
סוף
 
 
מה הסיכוי שנמצא תמונות מתאימות לכתבות של עידו גנדל?
 מה הסיכוי שנמצא תמונות מתאימות לכתבות של עידו גנדל? 
 צילום: GettyImages 
 
ללא ספק, דרוש כאן משהו חכם יותר – ובמקרה זה, מדובר בפקודה של זרימת בקרה שיוצרת לולאה. למעשה, לולאה במובנה הפשוט ביותר היא לא יותר משילוב של "נקודת ציון" ברצף הפקודות ושל האפשרות "לקפוץ" לאותה נקודת ציון ממקום אחר ברצף. למשל:

הכנס ל-X את הערך 0
[נקודת ציון א']
הוסף 1 ל-X
כתוב את הערך שב-X
קפוץ לנקודת ציון א'
סוף
 
קוד חכם יותר
 קוד חכם יותר 
 צילום: GettyImages 
 
בצורה כזו, הפקודות שבין נקודת הציון לבין הקפיצה (פקודות "הוסף" ו-"כתוב") מבוצעות שוב ושוב. לרוע המזל, מכיוון שאין מה שיעצור את הלולאה, היא תימשך עד אינסוף והמחשב ימשיך להציג מספרים עד שננתק אותו מהחשמל. האלמנט החיוני הנוסף הוא תנאי עצירה, אותו קל לממש בעזרת פקודת If שהזכרנו. לדוגמה, נחליף את השורה הלפני-אחרונה ב:

אם X קטן מ-5, קפוץ לנקודת ציון א'

כך, כאשר הערך של X יגיע ל-5 ויוצג, פקודת ה-If תמנע את ביצוע הקפיצה והתוכנית תמשיך לרוץ לפי הסדר – כלומר תגיע לפקודה "סוף". למעשה, כל הלולאות בכל התוכנות בעולם ניתנות למימוש על ידי נקודת ציון, קפיצה ותנאי עצירה. בפועל, מטעמים של נוחות כתיבה ושל הגיינת הקוד, שפות התכנות הגבוהות מציעות מבחר רחב של מימושי לולאות משוכללים.
 

While... Do... While

בשפות פסקל ודלפי, הלולאה הקרובה ביותר לזו שהצגנו היא לולאת Repeat ... Until (בשפות C ו-C++ היא נקראת do ... while). המילה Repeat משמשת כנקודת הציון, וה-Until ומה שמצורף לו הם תנאי העצירה. הדוגמה הפשטנית הבאה בדלפי זהה, למעשה, ללולאה התיאורטית שהצגנו קודם:


X := 0;
Repeat
X := X + 1;
Writeln(X);
Until X = 5;
 
GettyImages
 GettyImages 
 
הבעיה עם לולאות כאלה היא שתנאי העצירה נמצא בסוף: כל הקוד שבינו לבין נקודת הציון יבוצע בכל מקרה פעם אחת לפחות, ולפעמים אנחנו לא מעוניינים בכך. למשל, נניח שאנו כותבים תוכנה שמקבלת מהמשתמש מספר (X) וסופרת ממנו לאחור עד לאפס. בעיקרון, הקוד שבתוך הלולאה צריך להפחית 1 מ-X ולהדפיס את התוצאה, ואילו תנאי העצירה יהיה X = 0. אבל מה אם המשתמש מזין מספר שלילי, כגון מינוס 2? הקוד ידפיס "3-" פעם אחת, ואם ניסחנו תנאי עצירה זהיר הוא יעצור, אחרת ימשיך בלולאה אינסופית משום ש-X ימשיך לרדת ולא יגיע ל-0 לעולם. אפשר למנוע את זה באמצעות תנאי עצירה נוסף, עוד לפני נקודת הציון, ואפשר להשתמש בלולאה מסוג אחר: לולאת While ... Do (בדלפי, ואילו ב-C ו-C++ היא מכונה While). בלולאה זו, המיקום של התנאי ושל הקוד הפנימי פשוט מתחלף:


While (X > 0) do
Begin
X := X – 1;
Writeln(X);
End;
 

לולאת For

פליקר, Nat W
 פליקר, Nat W   
אבל גם שתי לולאות אלה לא מספיקות, מכיוון שאחת המטלות הנפוצות ביותר בתכנות היא לעבור על רצפים מספריים – ציר המספרים, אינדקסים של משתנים במערך, מקומות של תווים במחרוזת – ובלולאות שהזכרנו, הדבר ידרוש מהמתכנת להוסיף בעצמו את כל הטיפול במשתנה האינדקס. לשם כך נועדה הלולאה השלישית, לולאת For. בעוד שבשפת C הפכו אותה למין יצור אמורפי כל-יכול, שניתן אפילו לכלול בו פקודות בלי שום קשר ללולאה עצמה, הרי שבפסקל הלכו לקיצוניות השניה ויצרו לולאה עם מבנה קשוח מאד. נניח שיש לנו משתנה X, הנה לולאה שמעניקה לו לפי הסדר את הערכים 1 עד 10 ומבצעת בכל פעם את הפקודה Y. שימו לב שתנאי העצירה כאן הוא סמוי, ובא לידי ביטוי בפשטות כאשר הערך האחרון שננקב מיצה את עצמו:

For X := 1 to 10 do Y;

לולאה זו בנויה לערכים עולים בלבד. אם היינו כותבים "10 to 1", הפקודה Y לא הייתה מתבצעת כלל. עבור ערכים יורדים הומצאה הלולאה התאומה, שנכתבת כך:

For X := 10 downto 1 do Y;

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

צא לי מהלולאה

Eat That!
 Eat That! 
 צילום: GettyImages 
 
הצורך בפשטות ובאלגנטיות הוליד עוד שני סוגים של זרימת בקרה שקשורים ללולאות – למעשה, פקודות מסדר שלישי ששולטות בפקודות הלולאה שהן בעצמן, כאמור, מסדר שני. פקודות אלה מיועדות למקרים בהם אנו מגיעים לתוך הקוד שבלולאה, אבל מסיבה כלשהי מעוניינים לצאת ממנו לפני שהסתיים. לדוגמה, נניח שאנו כותבים תוכנה לפס ייצור, שעוברת בעזרת לולאה על כל שלבי הייצור ומפעילה עבור כל אחד מהם את הרובוט המתאים בתורו. מה יקרה אם אחד הרובוטים יחזיר הודעת שגיאה? הרי אין טעם להמשיך בלולאה ולהפעיל את הרובוטים הבאים, כי התהליך כולו נתקע. כמובן שאפשר לפתור זאת בעזרת כתיבת תנאי If בתוך הקוד, אבל זה מגושם. בשביל זה הומצאה הפקודה Break, שיוצאת מהלולאה באופן מיידי, בלי להתחשב בהמשך הקוד או בתנאי העצירה הרגיל. לעומת זאת, אם לא צריך לעצור את הכל אלא רק לדלג על הפקודות הבאות בקוד ולהגיע ישירות אל הסיבוב הבא בלולאה, הפקודה Continue תקפיץ את התוכנה ישירות אל תנאי העצירה של הלולאה.

כל העסק הזה של פקודות ששולטות ומפקחות על פקודות אחרות יכול להסתבך מאד, ובדיוק בגלל זה הוא מעניק למתכנתים עולם עצום של אפשרויות ויכולות שנובע כל-כולו מהמעבד הפשוט של המחשב, שלא עושה הרבה יותר מפעולות חשבוניות בסיסיות והעברות של נתונים מפה לשם. עם זאת, בשבוע הבא נדבר על סוג נוסף של פקודות, שנמצא בבירור הרחק מעל כל האחרים: הנחיות מהדר (Compiler Directives).
 
לטורי תכנות נוספים במסגרת 'לפרק את הבייט'
 
 
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
@@@@@@@@@@@@@@@@@@@ ilan @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
 
תגובות
הוסף תגובה0 תגובות
הוספת תגובה
מאת
 
נושא
 
תוכן
 
 
 
 
תודה! תגובתך התקבלה.
התגובה תתפרסם בכפוף לתנאי האתר.
 
 
 
 
 

כל הזכויות שמורות 2011 © נענע 10 בע"מ
 
 
 
 
כל הזכויות שמורות © Nana10 בע"מ
Video powered by