أوامر الشرط (بُنى التحكم)
كل البرامج التي كتبناها سابقا تم تنفيذها سطراً سطراً وبالترتيب المتسلسل. ولكن قد نحتاج في بعض الأحيان الى تغيير مجريات البرنامج، وذلك اعتماداً على حالة معينة أو مجموعة من الحالات، لذلك سنتعلم عن أوامر الشرط التي يطلق عليها أيضا بُنى التحكم، حيث باستطاعتنا التحكم بسير (إجراء) تنفيذ أوامر البرنامج وذلك بحسب مُعطيات وبيانات نحصل عليها أو نحسبها خلال عمل وتشغيل البرنامج، وذلك يتم باستخدام أوامر الشرط.
أوامر الشرط (بُنى التحكم): هي أوامر تستطيع تحديد أي مقاطع من البرنامج سيتم تنفيذها وتشغيلها إذا تحقق شرط معين أو القفز عنها وعدم تنفيذها (تجاهلها) إذا لم يتحقق الشرط.
مثال:
اكتب برنامج يستقبل سرعة السيارات التي تمر أمام كاميرا مراقبة السرعة على الشارع. على البرنامج أن يُبين السيارات المُخالفة، التي سرعتها تزيد عن 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.