פקודות תנאי (מבני בקרה)
כל התוכניות שכתבנו עד כה בוצעו שורה אחר שורה ובסדר רציף. אבל לפעמים נצטרך לשנות את מהלך התוכנית, בהתאם למצב מסוים או לקבוצת מצבים, ולכן נלמד על פקודות התנאי, הנקראות גם מבני בקרה. בעזרתן אפשר לשלוט במהלך הביצוע של פקודות התוכנית לפי נתונים שאנו מקבלים או מחשבים במהלך עבודת התוכנית והרצתה, וזאת באמצעות פקודות התנאי.
פקודות תנאי (מבני בקרה): הן פקודות שיכולות לקבוע אילו קטעים בתוכנית יבוצעו וירוצו אם מתקיים תנאי מסוים, או שידלגו עליהם ולא יבצעו אותם (יתעלמו מהם) אם התנאי אינו מתקיים.
דוגמה:
כתוב תוכנית שקולטת את מהירות המכוניות שעוברות מול מצלמת מהירות בכביש. על התוכנית לציין את המכוניות העבריינות, שמהירותן עולה על 100, ולהדפיס את ההודעה הבאה: "אזהרה! עברת את המהירות המותרת".
לפי דוגמה זו, התוכנית יכולה לבצע את פקודה 3 ויכולה שלא לבצע אותה, בהתאם לערך שאנו קולטים במהלך התוכנית ושומרים במשתנה v, המבטא את המהירות. לפי פקודת הבקרה (התנאי) 2, אם התשובה לשאלה היא כן (התנאי מתקיים) נבצע את פקודה 3, ואילו אם התוצאה של פקודת הבקרה (התנאי) היא לא (התנאי אינו מתקיים) לא נבצע את פקודה 3 ונתעלם ממנה.
אפשר לבצע את פקודה (3) ואפשר שלא לבצע אותה, בהתאם לערך שאנו קולטים במהלך עבודת התוכנית, שאנו מקבלים מן המשתמש ושומרים בתוך המשתנה mark.
גם את פקודה (4) אפשר לבצע ואפשר שלא לבצע, בהתאם לערך שאנו קולטים מן המשתמש.
4.1 צורות (מקרים) של מבני הבקרה
(1) המקרה הראשון (הצורה הראשונה): תנאי if הבסיסי (הפשוט):
if (התנאי)
{
פקודה (או פקודות) שמתבצעת רק אם התנאי מתקיים
}
המשך התוכניתהסבר:
- הפקודה המותנית 1 (או הפקודות המותנות 1) מתבצעת רק אם התנאי שבתוך if מתקיים, כלומר אם תוצאת התנאי היא true (כן).
- הפקודות 2 (המשך התוכנית) הן פקודות לא מותנות, והן מתבצעות תמיד, בין שהתנאי מתקיים ובין שאינו מתקיים.
- על הסוגריים המסולסלים { } שמקיפים את הפקודות המותנות אפשר לוותר אם הפקודות המותנות (פקודות מספר 1) הן פקודה אחת בלבד, אבל אסור לוותר על הסוגריים האלה אם הפקודות המותנות הן יותר מפקודה אחת.
static void Main(string[] args)
{
double num;
Console.Write("Insert a number: ");
num = double.Parse(Console.ReadLine());
if(num<0)
{
num = -1 * num;
}
Console.WriteLine("|num| = {0}",num);
}כמה תוצאות של הרצת התוכנית:
Insert a number: 5 |num| = 5
Insert a number: -9.2 |num| = 9.2
(2) המקרה השני (הצורה השנייה): תנאי if .. else (התנאי והיפוכו):
if ( תנאי )
{
פקודה (או פקודות) שמתבצעת אם התנאי מתקיים
}
else
{
פקודה (או פקודות) שמתבצעת אם התנאי אינו מתקיים
}
המשך התוכניתאם מתקיים התנאי *, התוכנית מבצעת את קבוצת הפקודות 1, אבל מדלגת על הפקודות 2 שנמצאות בתוך else (אינה מבצעת אותן).
ואם אינו מתקיים התנאי *, התוכנית מדלגת על קבוצת הפקודות מספר 1 (אינה מבצעת אותן), אבל מבצעת את הפקודות 2 שנמצאות בתוך else.
לא ייתכן לבצע את הפקודות 1 ו-2 יחד: התוכנית מבצעת או את הפקודות מספר 1 או את הפקודות מספר 2.
הפקודות 3 מתבצעות תמיד, ללא קשר לתוצאת התנאי, והן פקודות המשך התכנות.
static void Main(string[] args)
{
double n;
Console.Write("Insert a non zero number: ");
n = double.Parse(Console.ReadLine());
if (n > 0)
{
Console.WriteLine("Positive");
}
else
{
Console.WriteLine("Negative");
}
}כמה תוצאות של הרצת התוכנית:
Insert a non zero number: -8 Negative
Insert a non zero number: 13.8 Positive
החשיבות של שימוש ב-else:
למדנו קודם שאפשר לכתוב פקודת תנאי בעזרת הצורה הראשונה הפשוטה if.
אפשר להשתמש בצורה זו בלבד, בלי צורך ב-else, אבל יש חשיבות לשימוש ב-else, ונלמד אותה על סמך הדוגמה הקודמת (דוגמה 4.3).
בדוגמה הקודמת (דוגמה 4.3) השתמשנו ב-else, אבל יכולנו לפתור אותה כך:
(בשימוש ב-if בלבד, בלי צורך ב-else)
static void Main(string[] args)
{
double n;
Console.WriteLine("insert a non zero number:");
n = double.Parse(Console.ReadLine());
if(n>0)
Console.WriteLine("Positive");
if(n<0)
Console.WriteLine("Negative");
}וזה יהיה במבנה הבא:
בתוכנית זו השתמשנו בשתי בדיקות, if(n>0) ו-if(n<0), כך שהמחשב בודק פעמיים גם אם אין בכך צורך. למשל, אם המספר שקלטנו חיובי, כלומר התנאי הראשון ( n>0 ) מתקיים והדפסנו Positive על המסך, אין צורך לבדוק אם n<0. אבל בגלל הפקודה if(n<0) התוכנית תבדוק פעם נוספת אם המספר שלילי.
ואילו אם נציב במקום if(n<0) את הפקודה else, אז אם התנאי הראשון מתקיים התוכנית תדלג ישירות על מה שבתוך ה-else, בלי צורך לבדוק פעם נוספת.
סיכום ההערות החשובות:
1. אם הפקודות המותנות לביצוע הן פקודה אחת בלבד בתוך if, אפשר לוותר על הסוגריים המסולסלים { }, וכך גם לגבי else.
if(n>0)
Console.WriteLine("+");
else
Console.WriteLine("-");
Console.WriteLine("The End");פקודה מספר 2 היא פקודה מותנית ששייכת לתנאי if, והיא מתבצעת רק אם n>0.
פקודה מספר 4 היא גם פקודה מותנית ששייכת ל-else, והיא מתבצעת אם התנאי n>0 אינו מתקיים.
פקודה מספר 5 היא פקודה לא מותנית (המשך התכנות), והיא מתבצעת בכל מקרה.
2. אפשר לוותר על השימוש ב-else אם נכתוב את התנאי בתוך if, ובנוסף נכתוב את שלילתו בתוך if אחרת, אבל זה יקטין את יעילות התוכנית, כי התוכנית תבדוק כל תנאי ששייך לכל if, ואילו אם היה else לא היה צורך לבדוק פעם נוספת.
3. נזכור תמיד שלא כדאי לשים ; מיד אחרי התנאי בלי שיהיו פקודות מותנות, כלומר לא כדאי לכתוב:
if ( תנאי ) ;
(3) המקרה השלישי (הצורה השלישית): תנאים מקוננים וחוזרים (if מקוננת):
- אלה תנאים שנמצאים בתוך תנאים אחרים.
- לכל else חייבת להיות if, כלומר else חייב להיות שייך ל-if מסוימת, והיא ה-if הקרובה ביותר מעליו, אך תוך התחשבות בסוגריים.
- בתנאים מקוננים אנו משתמשים ב-else if, ואז עלינו להקפיד לשים לו תנאי, והוא תנאי ה-if שנמצא בתחום ה-else
- במקרים אלה צריך לשים לב לסוגריים המסולסלים, כך שלכל סוגר פותח יהיה סוגר שסוגר אותו.
- + אם המספר חיובי.
- - אם המספר שלילי.
- 0 אם המספר אפס.
פתרון:
static void Main(string[] args)
{
double num;
Console.Write("Insert a number: ");
num = double.Parse(Console.ReadLine());
if(num>0)
Console.WriteLine("+");
else if (num<0)
Console.WriteLine("-");
else
Console.WriteLine("0");
}4.2 תנאים מורכבים
בתוך הסוגריים של מבני הבקרה if מופיע התנאי. תנאי זה מורכב מהשוואה מן המקרים הבאים:
| התנאי (השוואה) | הסבר | דוגמה והערות |
|---|---|---|
> | אם גדול | if (a>b) אם a גדול מ-b |
< | אם קטן | if (a<b) אם a קטן מ-b |
== | אם שווה | if (a==b) אם a שווה ל-b |
!= | אם לא שווה | if (a!=b) אם a לא שווה ל-b |
>= | אם גדול או שווה | if (a>=b) אם a גדול או שווה ל-b |
<= | אם קטן או שווה | if (a<=b) אם a קטן או שווה ל-b |
שים לב שהסימן == פירושו אם שווה (האם שווה?), ואילו הסימן = פירושו הצבה.
כדי שנוכל להבין את נושא התנאים המורכבים עלינו ללמוד על טיפוס נתונים חשוב בתנאים, והוא bool
טיפוס הנתונים bool:
כפי שלמדנו קודם על טיפוסי הנתונים int, double, char, יש טיפוס נתונים חשוב לפקודות התנאי, והוא bool, שיכול להכיל שני ערכים בלבד: true (אמת) ו-false (שקר).
משתנה מטיפוס bool מוכרז בדרך הבאה:
bool שם_משתנה ;
למשל, נרצה להגדיר משתנה בשם flag מטיפוס bool:
bool flag;
אפשר לתת למשתנה ערך התחלתי (אחד הערכים האפשריים, true או false) כך:
bool flag=true; bool a=false;
קליטת נתון מן המשתמש לתוך משתנה מטיפוס bool נעשית בעזרת הפקודה הבאה:
שם המשתנה = bool.Parse(Console.ReadLine());
הנתון שאנו קולטים חייב להיות המילה true או המילה false.
הדפסת הערך של משתנה בשם a מטיפוס bool נעשית בעזרת Console.Write, כמקובל. למשל:
Console.WriteLine("the value of a is: {0}",a);או בעזרת פעולת שרשור המחרוזות +:
Console.WriteLine("the value of a is: "+a);הטיפוס של התנאי הוא bool, וערכו הוא true (אם התנאי מתקיים) או false (אם התנאי אינו מתקיים).
אפשר לכתוב if(true), ובמקרה זה התנאי מתקיים תמיד.
אפשר לכתוב if(false), ואז התנאי לעולם אינו מתקיים.
int a = 4, b = 5;
bool x;
x = a > b;
if(x)
Console.WriteLine("A");כאן הערך של x הוא false, ולכן לא יודפס דבר על המסך.
int a = 8, b = 5;
bool x;
x = a > b;
if(x)
Console.WriteLine("A");כאן הערך של x יהיה true, ולכן תודפס האות A על המסך.
אפשר לשלב פעולות השוואה ולוגיקה בעזרת הפעולות הלוגיות הבאות:
| הפעולה | הסבר |
|---|---|
&& | וגם (and) |
|| | או (or) |
! | היפוך לוגי (שלילה) (Not) |
x <= 100 && x >= 0
זה יכול להיות ציון של תלמיד. כלומר:
bool a, b, c ; bool x = true; a = !x; b = x && a; c = b || a;
a = false; b = false; c = false;
טבלאות הפעולות הבוליאניות הלוגיות:
נסמן את הערך false באות f, ואת הערך true באות t.
| טבלת && (And) |
|---|
| f && f = f |
| f && t = f |
| t && f = f |
| t && t = t |
| טבלת || (Or) |
|---|
| f || f = f |
| f || t = t |
| t || f = t |
| t || t = t |
| טבלת ! (Not) |
|---|
| !f = t |
| !t = f |
- אם המספר אינו מתאים לציון של תלמיד (למשל גדול מ-100 או שלילי), על התוכנית להדפיס על המסך It`s not a mark!
- אם הציון של התלמיד גדול או שווה ל-90, היא מדפיסה Excellent.
- אם הציון של התלמיד בין 55 ל-89 כולל הקצוות, היא מדפיסה Pass.
- אם הציון של התלמיד נמוך מ-55, היא מדפיסה Failed.
פתרון:
static void Main(string[] args)
{
int mark;
Console.Write("Insert a mark: ");
mark = int.Parse(Console.ReadLine());
if(mark>100 || mark<0)
Console.WriteLine("It`s not a mark!");
else
{
if (mark >= 90)
Console.WriteLine("Excellent.");
else
{
if (mark >= 55 && mark <= 89)
Console.WriteLine("Pass.");
else
Console.WriteLine("Failed.");
}
}
}כמה תוצאות של הרצת התוכנית עבור קלטים שונים:
Insert a mark: 55 Pass.
Insert a mark: 90 Excellent.
Insert a mark: 48 Failed.
Insert a mark: -4 It`s not a mark!
4.3 טבלת מעקב עם פקודות תנאי
טבלת המעקב מורכבת משורות ומעמודות בדיוק כפי שלמדנו קודם, אבל עלינו להוסיף עמודה לתנאי בין עמודות הטבלה ולמלא אותה בערך של ביטוי התנאי (true או false) כשאנו מגיעים לפקודת התנאי ומבצעים אותה. כמובן, תוצאת ביטוי התנאי תשפיע על טבלת המעקב, שכן לפי הערך של ביטוי התנאי ייקבע אילו פקודות התוכנית צריכה לבצע ועל אילו פקודות היא תדלג (לא תבצע אותן).
static void Main(string[] args)
{
int num;
Console.Write("Insert a number: ");
num = int.Parse(Console.ReadLine());
if(num==0)
Console.WriteLine("Even.");
else
{
if (num%2 == 0)
Console.WriteLine("Even.");
else
Console.WriteLine("Odd.");
}
}| מספר הפקודה | num | num == 0 | num%2 ==0 | המסך |
|---|---|---|---|---|
| 1 | ||||
| 2 | Insert a number: 207 | |||
| 3 | 207 | |||
| 4 | 207 | false | ||
| 6 | 207 | |||
| 7 | 207 | |||
| 8 | 207 | false | ||
| 10 | 207 | |||
| 11 | 207 | Odd. | ||
| 12 | 207 | |||
| 13 | 207 |
- They are equal – אם שלושת המספרים שווים.
- Two of them are equal – אם רק שניים מהם שווים.
- They are different – אם שלושת המספרים שונים.
פתרון:
static void Main(string[] args)
{
int num1, num2, num3;
Console.Write("Insert the first number: ");
num1 = int.Parse(Console.ReadLine());
Console.Write("Insert the second number: ");
num2 = int.Parse(Console.ReadLine());
Console.Write("Insert the third number: ");
num3 = int.Parse(Console.ReadLine());
if(num1==num2 && num2==num3)
Console.WriteLine("They are equal");
else
{
if (num1 == num2 || num2 == num3 || num1 == num3)
Console.WriteLine("Two of them are equal.");
else
Console.WriteLine("They are different numbers");
}
}נשים לב שכאן איננו יכולים לוותר על else בקלות, כי התנאים יהיו מורכבים יותר.
ראה גם שב-if הראשונה הסתפקנו בתנאי מורכב משני איברים בלבד, שביניהם הקשר "וגם" And, ולא משלושה איברים, כלומר אין צורך לכתוב: num1==num2 && num2==num3 && num1==num3
כמה מתוצאות הרצת התוכנית:
Insert the first number: 91 Insert the second number: 91 Insert the third number: 91 They are equal
Insert the first number: -4 Insert the second number: 16 Insert the third number: 0 They are different numbers
Insert the first number: -8 Insert the second number: 7 Insert the third number: -8 Two of them are equal.