1. דף הבית
  2. קורסים אונליין
  3. קורס PHP אונליין
  4. לולאות while ולולאות do-while ב-PHP

לולאות while ולולאות do-while ב-PHP

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

לולאת while ב-PHP

בפרקים הקודמים, סקרנו את לולאות for ו-foreach. כמו לולאות אלו, גם לולאת while היא מבנה בקרה המבצע רצף פעולות חוזרות בצורה סדרתית.

לולאת while ממשיכה לרוץ כל עוד תנאי שהצהרנו עליו מתקיים. היא אינה כוללת שלבי אתחול והגדלה כמו בלולאת for, כי אם תנאי בלבד. היא גם אינה עובדת על מבנה נתונים מסויים כמו לולאת foreach, כי אם מתאימה לתרחישים רחבים וכלליים יותר.

כל הרצה של בלוק הקוד בלולאת while מכונה "איטרציה".

תחביר:

while (condition) {
    // Code to execute
}

דוגמה:

<?php
$counter = 1;

while ($counter <= 5) {
    echo "Counter: $counter\n";
    $counter++;
}

// Outputs:
// Counter: 1
// Counter: 2
// Counter: 3
// Counter: 4
// Counter: 5
?>

לולאה זו רצה כל עוד מתקיים התנאי: המשתנה counter קטן או שווה ל-5.

 

לולאת while אינה חייבת לכלול משתנה לולאה. היא יכולה לבדוק תנאי דינמי שמשתנה בהתאם לריצת הקוד.

דוגמה:

<?php
$input = null;

while ($input !== "stop") {
    $input = readline("Enter a command (type 'stop' to exit): ");
    echo "You entered: $input\n";
}

echo "Loop terminated.\n";

/*
Output example:

Enter a command (type 'stop' to exit): hello
You entered: hello
Enter a command (type 'stop' to exit): world
You entered: world
Enter a command (type 'stop' to exit): stop
You entered: stop
Loop terminated.
*/
?>

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

שגיאות נפוצות עם לולאות while

שגיאה נפוצה בעבודה עם לולאת while היא מצב של לולאה אינסופית (infinite loop). מצב זה יכול לקרות אם קיים באג בקוד שמונע מהתנאי של הלולאה להפסיק להתקיים, כלומר, התנאי מתקיים תמיד.

דוגמה:

<?php
$count = 1;

while ($count <= 5) {
    echo "Count: $count\n";
    // Missing increment or update statement
}
?>

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

 

שגיאה נפוצה נוספת בעבודה עם לולאת while היא שגיאת "היסט ב-1" (off by one). שגיאה זו קורית כאשר קיימת טעות במשתנים הנבדקים בתנאי או טעות בתנאי עצמו, דבר המביא לריצה של איטרציה אחת נוספת מעל המתוכנן.

דוגמה:

<?php
$count = 0;

while ($count <= 5) { // The condition should likely be $count < 5
    echo "Count: $count\n";
    $count++;
}

// Outputs:
// Count: 0
// Count: 1
// Count: 2
// Count: 3
// Count: 4
// Count: 5
?>

בדוגמה זו, המשתנה count מתחיל בערך 0 והלולאה רצה כל עוד הוא קטן או שווה ל-5. הכוונה המקורית היתה שהלולאה תרוץ 5 פעמים, אך היא למעשה רצה 6 פעמים. תיקון הקוד יכול להעשות על ידי תיקון האתחול של המשתנה count ל-1 במקום ל-0 או על ידי תיקון התנאי שיבדוק שהמשתנה קטן ממש מ-5 במקום קטן שווה ל-5.

קינון לולאות while

ניתן לבצע קינון של לולאות while, כלומר, להריץ לולאת while אחת בתוך בלוק הקוד של לולאת while אחרת.

דוגמה:

<?php
$rows = 5; // Number of rows
$cols = 5; // Number of columns

$row = 1; // Outer loop initialization
while ($row <= $rows) {
    $col = 1; // Inner loop initialization
    while ($col <= $cols) {
        echo $row * $col . "\t"; // Print product of row and column
        $col++; // Increment inner loop
    }
    echo "\n"; // New line after each row
    $row++; // Increment outer loop
}

// Outputs:
// 1	2	3	4	5
// 2	4	6	8	10
// 3	6	9	12	15
// 4	8	12	16	20
// 5	10	15	20	25
?>

בדוגמה זו, בנינו את לוח הכפל עד 5X5, באמצעות 2 לולאות while מקוננות זו בתוך זו. הלולאה החיצונית אחראית על השורות (rows) ורצה 5 פעמים. בכל איטרציה של הלולאה החיצונית, הלולאה הפנימית שאחראית על האיברים בשורה (cols) עושה 5 איטרציות. הלולאה הפנימית רצה בסך הכל 25 פעמים.

 

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

כמו כן, ניתן שלב קינון של לולאות מסוגים שונים: for, foreach, while.

הצהרות break ו-continue בלולאות while

הצהרת continue מסיימת את ביצוע האיטרציה הנוכחית ומתחילה את ביצוע האיטרציה הבאה בלולאה.

דוגמה:

<?php
$count = 1;

while ($count <= 10) {
    if ($count % 2 === 0) {
        $count++; // Increment to avoid an infinite loop
        continue; // Skip even numbers
    }
    echo "Count: $count\n";
    $count++;
}

// Outputs:
// Count: 1
// Count: 3
// Count: 5
// Count: 7
// Count: 9
?>

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

 

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

 

הצהרת break מסיימת את ביצוע הלולאה ויוצאת ממנה.

דוגמה:

<?php
$count = 1;

while ($count <= 10) {
    if ($count === 5) {
        echo "Breaking the loop at count = $count\n";
        break; // Exit the loop when $count equals 5
    }
    echo "Count: $count\n";
    $count++;
}

// Outputs:
// Count: 1
// Count: 2
// Count: 3
// Count: 4
// Breaking the loop at count = 5
?>

בדוגמה זו, המשתנה count מאותחל לערך 1 וגדל בכל איטרציה. הלולאה רצה כל עוד ערכו של count קטן שווה ל-10. ברגע שערכו של count הוא 5, הלולאה מבצעת break ומסתיימת.

 

ניתן לשלב הצהרות break ו-continue באותה הלולאה.

דוגמה:

<?php
$count = 1;

while ($count <= 10) {
    if ($count === 7) {
        echo "Exiting the loop at count = $count\n";
        break; // Exit the loop when $count equals 7
    }

    if ($count % 2 === 0) {
        $count++; // Increment to avoid an infinite loop
        continue; // Skip even numbers
    }

    echo "Count: $count\n";
    $count++;
}

// Outputs:
// Count: 1
// Count: 3
// Count: 5
// Exiting the loop at count = 7
?>

 

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

דוגמה:

<?php
$i = 1;
while ($i <= 5) {
    $j = 1;
    while ($j <= 5) {
        if ($i * $j > 10) {
            break 2; // Exit both loops when the product exceeds 10
        }
        echo "$i x $j = " . ($i * $j) . "\n";
        $j++;
    }
    $i++;
}

// Outputs:
// 1 x 1 = 1
// 1 x 2 = 2
// 1 x 3 = 3
// 1 x 4 = 4
// 1 x 5 = 5
// 2 x 1 = 2
// 2 x 2 = 4
// 2 x 3 = 6
// 2 x 4 = 8
// 2 x 5 = 10
?>

בדוגמה זו, הצהרת break 2 מסיימת את 2 הלולאות ולא רק את הפנימית.

 

דוגמה נוספת:

<?php
$i = 1;

while ($i <= 3) {
    $j = 1;
    while ($j <= 3) {
        $k = 1;
        while ($k <= 3) {
            if ($i + $j + $k === 6) {
                echo "Skipping to the next iteration of the outermost loop at i = $i, j = $j, k = $k\n";
                $k++; // To avoid infinite loop in the innermost loop
                continue 3; // Skip to the next iteration of the outermost loop
            }
            echo "i = $i, j = $j, k = $k\n";
            $k++;
        }
        $j++;
    }
    $i++;
}

// Outputs:
// i = 1, j = 1, k = 1
// i = 1, j = 1, k = 2
// i = 1, j = 1, k = 3
// i = 1, j = 2, k = 1
// i = 1, j = 2, k = 2
// Skipping to the next iteration of the outermost loop at i = 1, j = 2, k = 3
// i = 2, j = 1, k = 1
// i = 2, j = 1, k = 2
// i = 2, j = 1, k = 3
// i = 2, j = 2, k = 1
// i = 2, j = 2, k = 2
// Skipping to the next iteration of the outermost loop at i = 2, j = 2, k = 3
// i = 3, j = 1, k = 1
// i = 3, j = 1, k = 2
// i = 3, j = 1, k = 3
// i = 3, j = 2, k = 1
// i = 3, j = 2, k = 2
// Skipping to the next iteration of the outermost loop at i = 3, j = 2, k = 3
?>

בדוגמה זו, קיים קינון בעומק 3 של לולאות while. הצהרת continue 3 ממשיכה לאיטרציה הבאה של הלולאה העוטפת. אם היינו רושמים רק contine (ללא הספרה 3), היינו ממשיכים לאיטרציה הבאה באותה לולאה בה מופיעה הצהרת ה-continue, כלומר בלולאה הפנימית.

 

נמליץ להמנע מקוד שעמוס בהצהרות break ו-continue, שכן הצהרות אלו מקשות על קריאות הקוד. כמו כן, מומלץ להכניס הערה בצמידות לכל הצהרת break או continue, המסבירה מדוע נעשה שימוש בהצהרה זו.

לולאת for לעומת לולאת while

לולאות for ו-while ניתנות להמרה האחת לשניה. לולאת for כוללת אתחול, תנאי והגדלה. מנגד, לולאת while כוללת תנאי בלבד.

כדי להמיר לולאת for ללולאת while, נוכל להוסיף אתחול מיד לפני תחילת הלולאה ולהכניס הגדלה כשורה אחרונה בבלוק הקוד.

דוגמה:

<?php
// Using for loop
for ($i = 1; $i <= 5; $i++) {
    echo "Number: $i\n";
}

// Using while loop
$i = 1;
while ($i <= 5) {
    echo "Number: $i\n";
    $i++;
}
?>

בדוגמה זו, המרנו לולאת for ללולאת while. לשם כך, הוצאנו את האתחול של i לשורה מחוץ ללולאה, ואת ההגדלה של i הכנסנו כשורה אחרונה בבלוק הקוד.

 

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

דוגמה:

<?php
// Using while loop
$queue = [5, 10, 15, 20];

while (!empty($queue)) {
    $value = array_shift($queue); // Removes the first element and assigns it to $value
    echo "Processed value: " . $value . "\n";
}

// Using for loop
$queue = [5, 10, 15, 20];

for (; !empty($queue); ) {
    $value = array_shift($queue); // Removes the first element and assigns it to $value
    echo "Processed value: " . $value . "\n";
}
?>

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

 

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

לולאת do-while

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

תחביר:

do {
    // Code to be executed
} while (condition);

דוגמה:

<?php
// Initialize a counter variable
$counter = 5;

do {
    echo "Counter value: $counter\n";
    $counter++;
} while ($counter <= 7);


// Outputs:
// Counter value: 5
// Counter value: 6
// Counter value: 7
?>

בדוגמה זו, המשתנה counter מאותחל לערך 5. הלולאה רצה כל עוד ערך המשתנה קטן שווה ל-7.

 

שימוש נפוץ ללולאת do-while הוא במקרים של קלט מהמשתמש: הכנסת ערך, מילוי טופס, בחירת בתפריט וכיו"ב.

דוגמה:

<?php
do {
    $input = readline("Enter a positive number: ");
} while (!is_numeric($input) || $input <= 0);

echo "You entered a valid number: $input\n";
?>

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

 

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

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