# תנאים ולולאות📖 שיעור

## מה זה?

עד עכשיו כל שורת קוד רצה בדיוק פעם אחת, מלמעלה למטה. אבל תוכנית אמיתית צריכה "להחליט" — האם המשתמש בגיר? האם הסיסמה נכונה? — ולפעמים "לחזור על עצמה" — הדפסת כל הפריטים ברשימה, ולא רק את הראשון. תנאים (`if`/`else`/`switch`) פותרים את ה"החלטה"; לולאות (`for`/`while`/`foreach`) פותרות את ה"חזרה".

## מילות מפתח שחשוב לזכור

• `if` / `else if` / `else` — מריצים קטע קוד רק אם תנאי מתקיים (או האלטרנטיבה שלו)

• `switch` — בוחר בין כמה מקרים אפשריים לפי ערך אחד, נוח כשיש הרבה חלופות לאותו משתנה

• `for` — לולאה עם מספר איטרציות ידוע מראש (למשל "10 פעמים")

• `while` — לולאה שרצה כל עוד תנאי מתקיים, גם אם לא ידוע מראש כמה פעמים

• `foreach` — לולאה שעוברת על כל איבר באוסף (מערך, List וכו') בלי לנהל אינדקס ידנית

```csharp
int age = 20;
if (age >= 18)
{
    Console.WriteLine("Adult");
}
else
{
    Console.WriteLine("Minor");
}
```

```csharp
// switch — cleaner than multiple if/else when there are many cases for the same variable
int day = 3;
string dayName = day switch
{
    1 => "Sunday",
    2 => "Monday",
    3 => "Tuesday",
    _ => "Unknown"   // default
};
Console.WriteLine(dayName);
```

```csharp
// for — when you know in advance how many times to repeat
for (int i = 1; i <= 5; i++)
{
    Console.WriteLine($"Iteration {i}");
}

// while — when you don't know in advance, only the stopping condition
int attempts = 0;
while (attempts < 3)
{
    Console.WriteLine($"Attempt {attempts + 1}");
    attempts++;
}
```

```mermaid
flowchart TD
    A["Start"] --> B{"age >= 18?"}
    B -->|"Yes"| C["Print: Adult"]
    B -->|"No"| D["Print: Minor"]
```

## הסבר עיקרי

מתי `switch` עדיף על `if`/`else if` שרשרת — כש-**אותו** משתנה נבדק מול כמה ערכים אפשריים (כמו יום בשבוע, קוד סטטוס), `switch` קריא בהרבה מרצף `if (day == 1) ... else if (day == 2) ...`. אם התנאים מורכבים או בודקים משתנים שונים כל פעם, `if`/`else` עדיין הבחירה הנכונה.

`for` מול `while` — הכלל המעשי: אם ידוע **מראש** בדיוק כמה פעמים לחזור (למשל "על כל איבר במערך"), `for` הוא הבחירה הטבעית — יש בו מונה מובנה. אם העצירה תלויה בתנאי שיכול להשתנות באמצע (כמו "עד שהמשתמש מקליד 'exit'"), `while` מתאים יותר כי אין מספר איטרציות ידוע מראש.

`foreach` הוא `for` בלי ניהול אינדקס — כשרוצים פשוט "לעבור על כל איבר" באוסף, `foreach (var item in collection)` חוסך את הסיכון לטעויות off-by-one (כמו `i <= length` במקום `i < length`) שקורות בקלות בלולאת `for` עם אינדקס ידני.

## יתרונות

תנאים ולולאות הופכים תוכנית מרצף קשיח ל"חכמה" — יכולה להתאים את עצמה לנתונים; `switch` עם ביטוי (`switch expression`) קצר וקריא במיוחד לבחירה בין הרבה חלופות; `foreach` מונע שגיאות אינדקס נפוצות בלולאות ידניות.

## חסרונות

קינון עמוק מדי של `if` בתוך `if` בתוך `if` הופך קוד לקשה לקריאה ("Arrow Code"); לולאת `while` עם תנאי שגוי עלולה ליצור לולאה אינסופית שתוקעת את התוכנית.

## נקודות חשובות

• `switch` מתאים לבדיקת **אותו** משתנה מול כמה ערכים; `if`/`else` לתנאים כלליים יותר

• `for` — מספר איטרציות ידוע מראש; `while` — תלוי בתנאי דינמי

• `foreach` עדיף על `for` עם אינדקס כשפשוט עוברים על כל איברי אוסף

• לולאת `while (true)` בלי תנאי עצירה פנימי (`break`) יוצרת לולאה אינסופית

## טעויות נפוצות

• קינון `if` עמוק מדי במקום לפרק ללוגיקה ברורה יותר או להשתמש ב-`switch`

• שכחת `i++` בלולאת `while` — יוצרת לולאה אינסופית בטעות

• שימוש ב-`for (int i = 0; i <= array.Length; i++)` (עם `<=` במקום `<`) — גורם ל-IndexOutOfRangeException

## סיכום

`if`/`else`/`switch` מאפשרים לתוכנית "להחליט" בין אפשרויות; `for`/`while`/`foreach` מאפשרים לה "לחזור" על פעולה. הבחירה הנכונה בין `for` ל-`while` תלויה בשאלה אם מספר האיטרציות ידוע מראש, ו-`foreach` הוא הבחירה הבטוחה והקריאה ביותר כשפשוט עוברים על כל איברי אוסף.

## דוקומנטציה רשמית

[Microsoft Learn — Selection statements (if, switch)](https://learn.microsoft.com/dotnet/csharp/language-reference/statements/selection-statements)

[Microsoft Learn — Iteration statements (for, while, foreach)](https://learn.microsoft.com/dotnet/csharp/language-reference/statements/iteration-statements)

---

## תרגילים

### תרגיל 1 — בדיקת זוגי/אי-זוגי

**המשימה:** כתבו לולאת `for` שעוברת על המספרים 1 עד 20, ומדפיסה ליד כל מספר האם הוא זוגי או אי-זוגי (`%` לבדיקת שארית).

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

### תרגיל 2 — switch על ציון

**המשימה:** כתבו `switch expression` שמקבל ציון מספרי (0-100) ומחזיר אות: 90+ → "A", 80-89 → "B", 70-79 → "C", מתחת → "F".

**בדיקה:** קלט `95` מחזיר `"A"`; קלט `65` מחזיר `"F"`.

---

## פרויקט מסכם

**המשימה:** כתבו תוכנית "ניחוש מספר" — התוכנית "חושבת" על מספר קבוע (למשל `42`), והמשתמש מנסה לנחש אותו בלולאה עד שהוא צודק.

**דרישות:**
1. לולאת `while` שרצה עד שהניחוש נכון
2. בכל ניסיון — קלט מהמשתמש (`Console.ReadLine` + `int.TryParse`), והדפסת רמז: "גבוה מדי" / "נמוך מדי" / "נכון!"
3. ספירת מספר הניסיונות עם משתנה מונה, והדפסתה בסיום

**בדיקה:** ניחוש נכון מדפיס "נכון!" ומספר הניסיונות שנדרשו, ועוצר את הלולאה; ניחושים שגויים ממשיכים לתת רמזים עד שמצליחים.

## מה בפרק הבא

בפרק הבא — **מערכים מול List&lt;T&gt;**: איך שומרים כמה ערכים יחד, וההבדל בין אוסף בגודל קבוע (מערך) לאוסף שיכול לגדול ולהתכווץ (`List<T>`).
