לולאות ב-Java

[9 במרץ 2009] [37 תגובות]

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

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

System.out.println(“1”);
System.out.println(“2”);
System.out.println(“3”);
System.out.println(“4”);
System.out.println(“5”);

זוהי באמת תוכנית פשוטה, אבל מה יקרה אם נרצה לכתוב תוכנית שתדפיס את כל המספרים מ-1 ועד 1000. האם באמת נאלץ לכתוב אלף שורות קוד עבור התוכנית? יש דרך טובה יותר – לולאות.

לולאת While

המבנה הכללי של לולאת while הוא:

while (תנאי)
{
        קוד הלולאה
}

בלולאת while התנאי נבדק ו-כל עוד ערכו הוא True, הקוד שבתוך הבלוק (בין "{" ל-"}") מתבצע.  בסיום ביצוע הקוד, נבדק התנאי פעם נוספת, עד אשר התנאי יהיה שווה ל-False.

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

int x = 1;

כעת נוסיף את קוד הלולאה ואת התנאי שלה. אנו רוצים שקוד הלולאה יתבצע כאשר x הוא מספר בין 1 ל-1000, כלומר כל עוד x קטן או שווה ל-1000:

int x = 1;
while (x <= 1000){
}

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

int x = 1;
while (x <= 1000){
        System.out.println(x);
}

נסו להדר ולהריץ את התוכנית. תוכלו לראות כי התוכנית מדפיסה את המספר 1 אינסוף פעמים ולעולם לא עוצרת (ניתן לעצור אותה על ידי שילוב המקשים [Ctrl]+[C]). מדוע היא לא עוצרת? מכיוון שהערך של x אינו משתנה לאורך כל התוכנית ונשאר שווה ל-1. התנאי של הלולאה שואל האם x קטן או שווה ל-1000 ומכיוון ש-x הוא /, ו-1 קטן מ-1000: התנאי תמיד יהיה True והלולאה לעולם לא תפסיק להתבצע.

נפתור זאת על ידי קידום x באחד (הפיכת 1 ל-2, הפיכת 2 ל-3 וכדומה) וניתן לעשות זאת בשתי דרכים:

x = x + 1;

הפקודה הזאת גורמת ל-x להיות שווה לערכו הקודם בתוספת של אחד. וכך אם x היה שווה ל-5 כעת הוא יהיה שווה ל-(5+1), כלומר ל-6. הדרך השנייה יותר מקובלת:

x++;

פקודה זאת שקולה לפקודה הקודמת ומבצעת את פעולת קידום המשתנה x. כעת אתם מבינים מדוע נקראת שפת התיכנות C++ כך.

התשובה הסופית תהיה:

int x = 1;
while (x <= 1000){
        System.out.println(x);
        x++;
}

הריצו את התוכנית ובדקו האם התוצאה הרצויה התקבלה.

שאלה: אם נשנה את קוד התוכנית ל:

int x = 1;
while (x <= 1000){
        x++;
        System.out.println(x);
}

האם פלט התוכנית יהיה זהה לפלט של התוכנית הקודמת? הדרו ובידקו את תשובתכם.

לולאת For

זוהי לולאה עם מבנה שונה מלולאת While אך העיקרון דומה. זהו המבנה הכללי של לולאת For:

for (איתחול ; תנאי ; קידום){
        קוד הלולאה
}

איתחול הוא מקום שבו ניתן לבצע פעולה לפני התחלת ריצת הלולאה. תנאי הוא תנאי שנבדק לפני ביצוע קוד הלולאה בדומה ללולאות While. קידום הוא המקום לבצע פעולה שמתבצעת בסיום של ביצוע קוד הלולאה ולפני הבדיקה הבאה של התנאי.

נשכתב את התוכנית הקודמת  בעזרת לולאת For:

for (int x = 1; x <= 1000; x++){
        System.out.println(x);
}

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

שימו לב שהקוד בשימוש לולאת While דומה לקוד בשימוש בלולאת For מבחינה רעיונית, כלומר אנחנו מבצעים את אותן הפעולות למרות שהקוד נראה שונה.

מתי נשתמש ב-For ומתי ב-While?

כפי שראיתם, ניתן לפתור את אותה הבעיה עם שני סוגי הלולאות. בדרך כלל משתמשים בלולאת For כאשר רוצים לבצע את הלולאה מספר פעמים ידוע, כמו שראינו בדוגמה מקודם בה הרצנו את הלולאה 1000 פעמים.

לולאת ה-While שימושית כאשר אנחנו לא יודעים מתי התנאי של הלולאה יהפוך מ-True ל-False ואין לדעת כמה פעמים תרוץ הלולאה. שימו לב לבעיה הבאה:

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

int x = -1;
while (x!=0){
        x = console.nextInt();
}

שימו לב: אנו משתמשים באובייקט console מסוג Scanner. הזכרו בשיעור קלט ופלט והוסיפו את הגדרת האובייקט והוספת חבילת ההרחבה.

כאשר קוד הלולאה מתבצע, המשתמש מזין את ערכו החדש של x ולאחר מכן תנאי הלולאה נבדק. אם המשתמש הזין מספר שאינו 0, הוא יתבקש להזין מספר נוסף עד אשר הערך של x יהיה שווה ל-0, ואז תסתיים הלולאה.

לולאת Do-While

זוהי לולאה נוספת שדומה מאוד באופיה ללולאת While. ההבדל היחיד בין הלולאות הוא:

  • בלולאת While, קודם כל נבדק התנאי של הלולאה ורק אז מתבצע הקוד (אם התנאי היה True). מתאים לנו אם קוד הלולאה לא חייב להתבצע אפילו לא פעם אחת.
  • בלולאת Do-While, קודם כל מתבצע הקוד של הלולאה ורק לאחר מכן התנאי נבדק (אם התנאי יהיה True נבצע את הקוד שוב). מתאים לנו אם חובה שקוד הלולאה יתבצע לפחות פעם אחת.

מבנה לולאת Do-While נראה כך:

do
{
        קוד הלולאה
} while (תנאי);

נביט בדוגמה הקודמת בה נקלטים מספרים עד שהמשתמש מזין את המספר 0. ראינו כי x מאותחל לערך (1-) על מנת שקוד הלולאה יתבצע לפחות פעם אחת (אם היינו מאתחלים אותו ל-0, התנאי היה False והמשתמש לא היה יכול להזין מספרים). למעשה יכולנו לאתחל אותו לכל ערך פרט לערך -0.

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

int x;
do {
        x = console.nextInt();
} while (x!=0);

כעת אין צורך לאתחל את x ועדיין הלולאה תתבצע לפחות פעם אחת.

תרגיל

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

יש לכם את כל הכלים לפתור שאלה זו. מספר טיפים:

  1. התחילו מקובץ תבנית ריק, כמו זה שמוצג בשיעור תוכנית ראשונה ב-Java.
  2. התחילו בתוכנית שמטרתה קליטת מספרים לפי הכללים (עד המספר 0 ולא יותר מ-10 מספרים).
  3. המשיכוו בספירת כמות המספרים שנקלטו והציגו ערך זה.
  4. מכאן המשיכו לחישוב הסכום והממוצע.

פיתרון: פתרון לתרגיל הלולאות - כאן תמצאו פתרון מלא ומפורט - שלב אחר שלב.

סיכום

למדנו על לולאות While, Do-While ולולאת For ומתי כדאי להשתמש בכל אחת. אל תוותרו על פתירת התרגיל מכיוון שמקריאה בלבד לא ניתן ללמוד לתכנת.

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

37 תגובות

  1. david | 6/30/2009 12:55:50 AM

    תודה....

    תשתמשו בnetbeans תוכנה טובה מאוד היא מהדרת בעמה ואומרת לך אם יש לך בעיות ומיחדת לJAVA

  2. david | 6/30/2009 12:56:28 AM
    *עצמה
  3. טל | 6/30/2009 2:51:43 PM

    מנסיון שלי, ה-netbeans קצת מסובך מדיי למתחילים ולכן אני תמיד ממליץ על JCreator (התקנת JCreator). בהמשך שווה לעבור ל-Eclipse או NetBeans.

  4. מרב | 7/22/2009 4:00:35 AM

    כל הכבוד על ההסברים המעולים

    תוכל להציג את התשובה לתרגיל בנושא הלולאות? 

  5. טל | 7/24/2009 4:45:08 AM
    תודה מרב :) בקרוב אני אפרסם פיתרון מלא, מפורק לשלבים.
  6. נדב | 7/27/2009 12:47:04 PM

    תגיד טל בקוד הראשון:

    System.out.println("1");

    וככה עד חמש...

    אז למה ניסיתי להעתיק את זה לפנקס רשימות והכל וזה לא עובד ואז שאני כותב את זה לבד זה עובד, למה זה?

  7. טל | 7/27/2009 1:07:25 PM

    @נדב, כנראה שיש לך מגע של קסם...

    מעל כל קטע קוד ישנן אפשרויות. בחר ב-view plain אז תעתיק את הקוד מהחלון שנפתח (שים לב שהדפדפן לא חוסם את זה). זה כנראה כבר יעבוד לך.

  8. נדב | 7/27/2009 2:14:38 PM

    תגיד לי אחי טל למה בתרגיל בקטע של "מתי נשתמש ב-For ומתי ב-While?

    עשיתי את הקוד הזה:

    import java.util.Scanner;
    public class tirgul
    {  
        public static void main(String[] args){   
        int x = -1;  
        while (x!=0){     
        Scanner console = new Scanner(System.in); 
        x = console.nextInt();
        console.close();  

        }  

    ועוד שאלה מתי משתמשים בזה: import packagename?

    כי לא ראיתי בדוגמאות שהשתמשת בזה...

  9. נדב | 7/28/2009 3:30:45 AM

    הסתדרתי אחי לא משנה הבנתי...

    רק אתה יכול לענות לי למה בדוגמאות לא השתמשת ב-Import packagename? מתי כאילו צריך להשתמש בזה...

  10. טל | 7/28/2009 11:02:24 AM

    הבסיס של Java מכיל המון פקודות ומחלקות כבר מההתחלה (יצירת משתנים, לולאות, תנאי IF ועוד המון). עם זאת, לפעמים רוצים להרחיב את היכולות הבסיסיות של Java בעזרת חבילות (Packages). למשל חבילות שיודעות לבצע פעולות מתמטיות או חבילה שמאפשר לצייר אובייקטים בתלת מימד.

    כאשר רוצים להוסיף את היכולות של חבילה מסויימת לתוכנית שלנו, נשמתמש ב import packagename. כבר ראינו שימוש בחבילת java.util.Scanner על מנת לקרוא קלט מהמשתמש.

    דרך אגב, כל הדוגמאות שרואים במדריך הזה הן לא תוכניות שלמות. את הקוד שרואים כאן ניתן לשלב בתוכניות שונות.

     

  11. נדב | 7/28/2009 1:06:34 PM
  12. נדב | 7/28/2009 1:07:02 PM
    אחי תעלה תשובה לתרגיל...
  13. נדב | 8/1/2009 7:49:24 AM
    מה עם פיתרון???
  14. טל | 8/1/2009 8:53:03 AM

    @נדב, אני שמח שאתה מצפה לפיתרון.

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

  15. נדב | 8/1/2009 1:17:23 PM

    ותגיד יהיו עוד מדריכים ב-Java???

     

  16. טל | 8/8/2009 4:23:23 AM

    הפתרון המלא לתרגיל פורסם כאן: פתרון לתרגיל הלולאות.

    האם יהיו עוד מדריכים? זה תלוי אם יהיה ביקוש להמשך או לא מצד הגולשים ובזמן הפנוי שיהיה לי.

     

  17. חן | 9/11/2009 9:46:25 AM

    טל....

    איך הייתי יכול לפתור את התרגיל בלולאות אם לא לימדת עדיין counters ???

    הסתכלתי על הבעיה ואמרתי "הא?! צריך פה  counter..."

    אתה עושה עבודת קודש...

  18. טל | 9/12/2009 7:05:41 AM

    תמיד יש שיקול בין ללמד את הכל לבין לתת ללומדים לנסות להמציא את מה שצריך. אני לא חושב שזה שלב מוקדם מדי כדי שמישהו "ימציא" מונה (counter).

    אם אני טועה, תגידו לי ואני אכניס את זה כטיפ לפתרון התרגיל.

  19. שירן | 11/6/2009 3:47:36 AM

    הי רציתי לדעת,האם מותר לשים ; בסוף לולאות תנאי ?

     

  20. טל | 11/6/2009 7:49:32 AM

    @שירן, מותר לשים נקודה-פסיק בסוף לולאת תנאי. למעשה, מותר לשים נקודה-פסיק בסופה של כל פקודה אחרת וזה יעבוד.

    זה עובד כי נקודה-פסיק מסמלת סוף של פקודה. ב-Java מותר גם שיהיו פקודות ריקות ולכן מותר להוסיף לקוד שורה כזאת וזה יעבוד:

    ;;;;;;;;;;;;;;;;

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

    הנקודה פסיק בסוף הלולאה היא פשוט פקודה ריקה אחרי הלולאה (כאילו ירדת שורה(

  21. אפי | 12/9/2009 2:32:01 PM

    טל בבקשה עוד מדריכים

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

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

     

    פליזזזז עוד מדריכים !!!! 

     

     

  22. טל | 12/11/2009 7:53:22 AM

    אפי, אני שמח שאתה נהנה מהמדריכים. אני אשתדל לכתוב עוד כאלו ברגע שיהיה לי יותר זמן פנוי.

    בקשר לתרגיל, זה מצויין שאתה משקיע ועושה אותו לבד. הפתקון פורסם למקרה שאתה נתקע בשלב מסויים, זה לא בושה להציץ בפתרון :)

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

     

  23. יותם | 3/1/2010 12:10:40 AM
  24. יותם | 3/1/2010 12:12:03 AM
    טל יש לי שאלה קטנה... כשעושים את הפקודה x++; זאת אומרת שזה מוסיף ב-1 אבל מכוון שזה בלולאה זה חוזר על עצמו עד שהערך הוא False נכון? אז מה יקרה אם אני אכתוב את זה "x+++" זה יוסיף כל פעם 2?
  25. אלכס | 6/3/2010 8:31:14 AM

    איני יודע אם אתה פעיל או לא, בקיצור

     בחלק של לולאת while אז בדוף הבאתה איך זה אמור להראות בסוף, העתקתי והדרתי וזה עושה מלא שגיאות

    זה בידיוק מה שכתבתי , למה לא עובד לי

     int x = 1;

    while (x <= 1000){

            System.out.println(x);

            x++;

    }

     

  26. אלרוי | 6/7/2010 11:00:49 AM

    תודה רבה לך אבל יש לי שאלה ...

    לא ממש הבנתי את ה - do .. טיפה בילבל אותי .

    int x;  
    do {  
            x = console.nextInt();  
    while (x!=0); 

     לא הבנתי מזא"ת console.nextInt();

    ומה שה while עושה .. אשמח לתשובה :D

  27. טל | 6/9/2010 1:46:21 PM

    צריך להתחיל ללמוד מההתחלה. השיעור קלט ופלט ב-java מסביר על console.nextint ואז אולי השיעור הזה יהיה ברור יותר.

    אם עדיין לא, אני אשמח לעזור. 

  28. הדר | 10/23/2011 5:23:20 AM

    היי טל,

    למה הפסקת? למדתי המון בעזרת הפוסטים האלה.

    מה השלב הבא שכדאי ללמוד לדעתך?

  29. הדר | 10/23/2011 5:23:21 AM

    היי טל,

    למה הפסקת? למדתי המון בעזרת הפוסטים האלה.

    מה השלב הבא שכדאי ללמוד לדעתך?

  30. אריאל | 10/23/2011 2:14:06 PM

    יופי של הסברים,

    כתוב בצורה ברורה וחסרת אגו מיותר. 

    תודה רבה!

  31. th,h | 4/13/2012 10:17:35 AM
    אתה תמשיך את המדריך?
  32. תומר | 6/12/2013 5:38:29 AM
    באמת אחלה מדריך, יהיה המשך?
  33. עידן | 8/11/2013 6:05:59 PM

    טל אתה יכול להסביר לי את הפקודה .length?

  34. עידן | 1/4/2014 3:49:23 AM
    טל אתה עושה עוד מדריכים אחרי הלולאות?

  35. טל | 1/4/2014 2:28:50 PM

    לא, אני סיימתי עם זה ב-2009.

    אני בטוח שיש מקומות לימוד Java טובים יותר היום באינטרנט (לא יכול להמליץ על משהו ספציפי).

  36. מתן | 2/9/2017 5:53:09 PM

    טל תודה רבה על כל המדריכים שעשית!

    אני רואה שפרשת כבר ב2009 אבל הכל פה מאוד רלוונטי גם ל2017 חח (:

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

    נתת לי הרבה מוטיבציה ובעיקר ידיעה שללמוד תכנות יכול להיות אחלה!

    תודה (:

  37. טל | 2/12/2017 3:22:37 AM
    תודה מתן

התגובות נעולות