اذهب إلى المحتوى

اتخاذ القرار: العبارات الشرطية والحلقات التكرارية في البرمجة


أحمد عصام النجار

يُعَدّ اتخاذ القرار أحد المواضيع الأهم في هندسة البرمجيات، إذ يُستخدَم بصورة دائمة وضرورية في أيّ برنامج، في حين تُستخدَم جمل اتخاذ القرار لطرح سؤال ما، عبر المعامِلات التي تُستخدَم للموازنة التي ذكرناها في المقال السابق أنواع البيانات والعمليات الأساسية في لغة بايثون من هذه السلسلة ومن ثم اتخاذ قرار بتنفيذ أسطر معيّنة بناءً على تحقق شرط من عدمه.

العبارات الشرطية

العبارات الشرطية في البرمجة

يوضِّح المخطط السابق آلية عمل البرنامج عند وجود جملة شرطية فيه فقد افترضنا في المخطط السابق وجود برنامج فيه جملة شرطية واحدة فإذا كانت نعم أو True، فستُنفَّذ كتلة شيفرة معيّنة ثم يُنهى البرنامج؛ أما في حالة الإجابة بلا أو False، فستُنفَّذ كتلة شيفرة أخرى ثم يُنهى البرنامج، فالمُراد فهمه عند تلك النقطة، هو أنّ اتخاذ القرار في هذه الحالة يعني تنفيذ كتلة شيفرة وتجاهل كتلة شيفرة أخرى بناءً على شرط.

يمكن كتابة الجمل الشرطية في بايثون ومحاكاة المخطط السابق عبر تعليمة if بالشكل التالي:

x = 5
if x == 5:
    print ('X equals five')
else:
    print ("X doesn't equal five")

عرّفنا في المثال السابق متغيرًا يحتوي على القيمة العددية 5، ثم طرحنا سؤالًا في السطر الذي يليه على اللغة وهو: هل المتغير x يساوي العدد 5؟ بالطبع الإجابة نعم، وبناءً على ذلك ستُنفِّذ كتلة الشيفرة المندرِجة تحت هذا الشرط عند تحققه، أي ستُطبع X equals five، وقد استخدمنا في المثال السابق قاعدة if else، وهي ما يوضحها المخطط السابق إذ توجد كتلتان من الشيفرة، بحيث تُنفَّذ إحداهما فقط بناءً على نتيجة الجملة الشرطية.

سنوضح في المخطط الآتي فسنوضح استخدام قاعدة if فقط، بحيث تُنفَّذ كتلة شيفرة عند تحقق الشرط، ولا يُنفَّذ أيّ شيء عند عدم تحققه.

استخدام الجمل الشرطية في البرمجة

المثال المكافئ للمخطط بلغة بايثون يُكتب كما يلي:

x = 5
if x > 3:
    print ("X is bigger than 3")

يكون المتغير x في هذه الحالة أكبر من الرقم بالطبع، وبالتالي ستُنفَّذ كتلة الشيفرة المندرجة تحت هذا الشرط، وتُطبَع العبارة X is bigger than 3؛ أما في المثال التالي فسنغيِّر معامِل الموازنة في الجملة الشرطية، وبالتالي فلن تُنفَّذ أيّ كتلة شيفرة لعدم استخدام قاعدة if else.

x = 5
if x <= 3:
    print ("X is less than 3 or equals to 3")

ما حدث في المثال يوضحه المخطط المخطط التالي الذي يعرض مسار تنفيذ البرنامج بالسهم الأسود العريض.

مسار تنفيذ البرنامج

أوردنا في الصفحات القليلة الماضية استخدام قاعدة if وقاعدة if else، لكن ذلك ليس نهاية الأمر في اتخاذ القرار، إذ توجد قاعدة أكثر ديناميكيةً وقوةً، كما تُستخدَم لوضع سلسلة من الشروط، إذ يتحقق المفسر من الشرط إذا لم يتحقق الشرط السابق له، وهي قاعدة if elif أو if elif else.

قواعد تحقق المفسر من الشرط إذا لم يتحقق الشرط السابق له

نحاكي في المخطط السابق خريطة تدفق برنامج بسيط يحتوي على ثلاث جمل شرطية، أولها كُتبت باستخدام if، وثانيها وثالثها كُتِب باستخدام elif، كما من الضروري معرفة التالي:

  • يجب أن تبدأ الجمل الشرطية بجملة if أولًا.
  • لا حدود لجُمل elif، إذ يمكن أن يمتد المخطط السابق إلى عدد غير محدود من الجمل الشرطية الأخرى.
  • يمكن إضافة جملة else مرةً واحدةً فـي الجمل الشرطية، وهي تُستخدَم كآخر حل بعد عدم تحقق جميع الشروط السابقة لها، أي if و elif.

فيما يلي محاكاة للمخطط السابق في بايثون، إذ سيسلك التنفيذ مسارًا يتحقق فيه من أول شرط فيجده خاطئًا، وبعدها يتجه إلى الشرط الثاني الموجود في elif فيجده خاطئًا أيضًا، ثم يتجه إلى الشرط الثالث فيجده صحيحًا، وعندها ينفِّذ كتلة الشيفرة الموجودة بداخله.

name = "Adam"
if name == "Noah":
    print ("The name is Noah")
elif name == "Jacob":
    print ("The name is Jacob")
elif name == "Adam":
    print ("The name is Adam")
>> The name is Adam

نضيف إلى ذلك إمكانية استخدام جملة else في نهاية الشيفرة كي تُنفَّذ شيفرة ما إضافية في حالة عدم تحقق أيّ شرط من الشروط التي وُضعت، لذا نستطيع تغيير المثال السابق بتعديل قيمة المتغير كما يلي:

name = "Yusuf"
if name == "Noah":
    print ("The name is Noah")
elif name == "Jacob":
    print ("The name is Jacob")
elif name == "Adam":
    print ("The name is Adam")
else:
    print ("We don't know the name")
>> We don't know the name

بناءً على كل ما سبق، فإنه يمكن إضافة عدد غير محدود من جمل التحقق أو الشروط باستخدام ما ذُكِر من قواعد، كما يمكن كتابة تلك الشروط بصورة متداخلة أيضًا، وتُعَدّ تلك التعابير الشرطية conditional expression مهمةً للغاية، وتُستخدَم في كل البرامج تقريبًا، إذ أنه لا استغناء عن التحقق من المدخَلات والبيانات في كل البرامج الذكية.

حلقات التكرار

تُعَدّ حلقات التكرار Loops إحدى أهم الميزات المستخدَمة بكثرة في كل لغات البرمجة، إذ قد يود المبرمج في كثير من الأحيان تكرار كتلة شيفرة معيّنة لمدة معيّنة قد تكون عددًا معيّنًا من المرات، أو إلى حين تحقق شرط معيّن، وذلك ما توفره لنا حلقات التكرار في بايثون وفي كثير من اللغات البرمجية الأخرى، كما تُستخدَم استخدامًا واسعًا في كثير من الخوارزميات وبالطبع في معظم البرامج.

حلقات التكرار في البرمجة

نوضِّح في المخطط السابق آلية عمل البرنامج عندما يقابل حلقة تكرار في البرنامج، إذ يردّ المفسر على الجملة الشرطية أو السؤال، وبناءً على الإجابة إما يتخطى كتلة الشيفرة المُرمز إليها على يمين المخطط، أو يُنفِّذ كتلة الشيفرة، ثم يردّ على الجملة الشرطية مرةً أخرى، ليرى إذا كانت نتيجة الجملة الشرطية قد اختلفت في تلك المرة، وهكذا إلى أن تصبح إجابة الجملة الشرطية خطأ False، فيتخطى المفسر كتلة الشيفرة تلك المرة، ويستكمل البرنامج إذا كانت هناك تعليمات أخرى أو ينهي العمل.

توجد طريقتان لاستعمال الحلقات التكرارية في بايثون، الأولى هي باستعمال تعليمة While والثانية باستعمال تعليمة For، إذ تُستخدَم الأولى لتكرار تنفيذ كتلة شيفرة ما بناءً على جملة شرطية كما وضَّحنا من خلال المخطط السابق؛ أما القاعدة الثانية فتكرِّر تنفيذ كتلة شيفرة معيّنة ولعدد معيّن من المرات.

حلقة While

تُستخدَم هذه الحلقة كما أشرنا في تكرار كتلة شيفرة بناءً على جملة شرطية، وما دامت الجملة الشرطية مُحققةً، فسيُكرَّر تنفيذ كتلة الشيفرة إلى حين عدم تحقق الجملة الشرطية، ويكون بناء جُمل قاعدة حلقة While كما في المثال التالي:

while expression:
    statements

تحل الجملة الشرطية التي قد تحتوي على شرط واحد أو أكثر محل التعبير expression ثم تحل كتلة الشيفرة المُراد تنفيذها محل التعليمات statements، ففي المثال التالي نعرِّف متغيرًا عدديًا ثم نطبع الرقم طالما أنه أصغر من 9، مع زيادة قيمة المتغير بعدد واحد صحيح في كل مرة تُنفَّذ فيها كتلة الشيفرة.

x = 0
while x < 9:
    print (x)
    x += 1

ومن الجدير بالملاحظة أنه يمكن اختصار تركيب الجملة الخاصة بحلقة While إذا كانت كتلة الشيفرة التي تحتويها عبارةً عن سطر واحد كما يلي:

x = 0
while x < 9: print (x); x += 1
print ('Done')

يختصر المثال أعلاه المثال الذي يسبقه تمامًا، مع إضافة طباعة كلمة Done بعد الانتهاء من الحلقة، وذلك بالطبع لأن جملة طباعة كلمة Done تأتي في مستوى حلقة While نفسه، ولذلك هي لا تندرج تحت حلقة While، وإنما تليها بناءً على قاعدة السطور والمسافات السابق ذكرها.

سيطبع المثال السابق الأعداد من 0 إلى 8، إذ أنه عندما تساوي قيمة المتغير x الرقم 9، فسيصبح الشرط في الحلقة خاطئًا، وبالتالي لن تُنفَّذ كتلة الشيفرة.

توجد ما تُدعى بالحلقة اللانهائية Infinite Loop، وذلك يحدث عندما لا يتحول التعبير الشرطي في حلقة While إلى False أبدًا، لتُنفَّذ كتلة الشيفرة إلى الأبد، لذلك فإن آخر سطر في كتلة الشيفرة في المثال السابق، عندما نزيد قيمة المتغير x، هي خطوة ضرورية لكي لا تُنفَّذ كتلة الشيفرة إلى الأبد، لذلك في معظم الأحيان يجب أن تحتوي كتلة الشيفرة بداخل حلقة While على تغيير ما، يؤثِّر على إحدى المتغيرات الموجودة في التعبير الشرطي في الحلقة، وهنالك بالطبع استخدامات جيدة ومفيدة للحلقات اللانهائية في بعض البرامج خصوصًا في الألعاب، إذ تتطلب بعض التطبيقات تنفيذ تعليمات تنفيذًا مستمرًا ودائمًا.

حلقة For

تُنفِّذ حلقة For كما أوردنا كتلة الشيفرة المندرجة بداخلها عددًا معيّنًا من المرات، ويُحدَّد ذلك العدد من خلال عدد عناصر السلسلة الموضوعة في تعبير الحلقة، وقد تكون السلسلة صفًا أو قائمةً أو مجموعةً، ويكون بناء جملة قاعدة حلقة For كما يلي:

for variable in sequence:
    statements

يحل اسم المتغير الذي يحتوي على قيمة العنصر الحالي أثناء دوران الحلقة محل variable في حين يحل اسم المتغير الذي يحتوي على السلسلة محل sequence والذي قد يكون قائمةً، أو مجموعةًً، أو صفًا؛ أما statements فيحل محلها كتلة الشيفرة المُراد تكرار تنفيذها.

نوضِّح في المخطط التالي مسار عمل المفسر أثناء العمل على حلقة For، إذ نكرِّر تنفيذ كتلة الشيفرة بناءً على عدد العناصر الموجودة في قائمة تحتوي على أسماء أشخاص.

حلقة For البرمجية

ويوضح المثال التالي تنفيذ المخطط بلغة بايثون:

names = ['Adam', 'Noah']
for name in names:
    print (name)

عرَّفنا قائمةً تحتوي على اسمَي Adam و Noah، ثم استخدمنا معها حلقة For، وفي تلك الحالة ستُنفَّذ كتلة الشيفرة بداخل الحلقة مرتين فقط، وذلك لأنّ السلسلة التي استُخدِمت هي قائمة تحتوي على عنصرين اثنين فقط، ففي المرة الأولى ستستطيع كتلة الشيفرة بداخل الحلقة الوصول إلى العنصر الأول في السلسلة -أي الاسم Adam- ثم في المرة الثانية ستستطيع كتلة الشيفرة بداخل الحلقة الوصول إلى العنصر الثاني في السلسلة -أي الاسم Noah- وتتوقف لعدم وجود عناصر أخرى في السلسلة.

لاحظ أنه يمكن استخدام النصوص في حلقات التكرار عبر قاعدة for، إذ أنّ كل محرف في النص هو عنصر مستقل بداخل السلسلة النصية، ففي المثال نطبع كل حرف من محارف كلمة Hello بصورة مفرَدة باستخدام حلقة for.

for letter in 'hello':
        print (letter)
>> h
>> e
>> l
>> l
>> o

يمكن أيضًا إضافة حلقات تكرار داخل حلقات أخرى، أو إضافة جمل شرطية داخل حلقات التكرار، أو إضافة جمل شرطية داخل جمل شرطية أخرى إلى ما لا نهاية، فلا يوجد ما يمنع أن تحتوي كتلة الشيفرة الموجودة داخل إحدى القواعد، على قاعدة أخرى وكتل أخرى بأيّ عدد.

الدالة range

تُستعمل الدالة range عادة مع حلقات التكرار for والتي تعني بالعربية نِطَاق أو مَدَى لتنفيذ كتلة الشيفرة عددًا معيّنًا من المرات عبر سلسلة من الأعداد التي يُحدَّد العدد الأدنى والعدد الأقصى فيها، إليك المثال التالي:

for number in range(1, 6):
    print (number)

سيطبع المثال بناءً على ذلك الأرقام من 1 إلى 5 بالتتالي ولاحظ أن العدد الأقصى لا يدخل ضمن المجال.

التعليمة else

يمكن استخدام الكلمة المفتاحية else في حلقتَي While وFor، إذ تُكتَب بعد كتلة الشيفرة المُنفَّذة على مستوى تعبير الحلقة نفسه، ثم إدماج كتلة شيفرة تُنفَّذ عند انتهاء تنفيذ الحلقة، فحتى إذا نُفِّذت كتلة الشيفرة الموجودة بداخل الحلقة مرةً أو ثلاث مرات أو أيّ عدد من المرات، أو لم تُنفَّذ على الإطلاق، فستُنفَّذ دائمًا كتلة الشيفرة التابعة للكلمة المفتاحية else في النهاية، كما في الأمثلة الآتية:

for number in []:
    print (number)
else:
    print ('Done')
>> Done

يتخطى مسار التنفيذ حلقة التكرار في المثال السابق لعدم وجود عناصر في السلسلة المُزوَّدة، لكنه مع ذلك ينفِّذ كتلة الشيفرة المندرجة بداخل الكلمة المفتاحية else أما في المثال التالي فتُنفَّذ حلقة التكرار مع تعليمة else:

for number in [1, 2]:
    print (number)
else:
    print ('Done')
>> 1
>> 2
>> Done

التوقف والتخطي في حلقات التكرار

تُعَدّ الكلمات break وcontinue وpass من أهم الكلمات المفتاحية الأخرى المُستخدَمة في حلقات التكرار، فكل واحدة منها يمكن استخدامها في حلقة While أو حلقة For على حد سواء.

تُستخدَم أولًا كلمة break في الخروج من الحلقة كلها واستكمال باقي البرنامج، وغالبًا ما يتم ذلك عبر وضع جملة شرطية أولًا، إذ أنه عند تحقق ذلك الشرط، يخرج مسار التنفيذ من الحلقة تمامًا، ويستكمل تنفيذ باقي البرنامج، فإذا وُجدت حلقة for تعمل على قائمة تحتوي على ثلاثة أسماء مثلًا، فسنستطيع طباعة أول عنصر فقط من خلال التحقق من قيمة العنصر الحالي في الحلقة، فإذا كان لا يساوي ما نريد طباعته فسنخرج من الحلقة كاملةً كما في المثال التالي الذي يطبع أول عنصر فقط وهو Adam، وعند وجود أيّ قيمة أخرى، فسنخرج من الحلقة.

x = ['Adam', 'Noah', 'Jacob']
for name in x:
    if name != 'Adam':
        break

    print (name)

>> Adam

كما يمكن إيضاح مسار تنفيذ المثال السابق عبر المخطط الآتي:

التوقف والتخطي في حلقات التكرار

نلاحظ أنّ قيمة المتغير name ستحمل القيمة Adam في أول دورة، وعندما يُتحقَّق من الجملة الشرطية هل الاسم لا يساوي آدم؟ فستكون الإجابة بالطبع لا، وستُنفَّذ عملية طباعة الاسم؛ أما في الدورة الثانية، فسيحمل المتغير القيمة Noah، وبالتالي سيتحقق الشرط أي يصبح True، وبالتالي ستُنفَّذ كتلة الشيفرة المندرجة تحت الشرط مباشرةً، وتلك الكتلة تحتوي على تعليمة واحدة وهي break، والتي تعني إنهاء الحلقة بجميع دوراتها واستكمال باقي البرنامج.

أما الكلمة المفتاحية continue، فتُستخدَم لتخطي الدورة الحالية والبدء في الدورة التالية مباشرةً، بمعنى أنها تقوم بإنهاء الدورة الحالية، وتخطي باقي التعليمات الموجودة في كتلة الشيفرة الخاصة بحلقة التكرار، على عكس break التي تنهي حلقة التكرار تمامًا، لينتقل مسار التنفيذ لما بعد قاعدة For أو While، ونوضِّح في المخطط التالي آلية عمل الكلمة المفتاحية continue والتي غالبًا ما تُنفَّذ من خلال جملة شرطية.

آلية عمل الكلمة المفتاحية continue  في الحلقات التكرارية

نكتب المخطط السابق بلغة بايثون بالشكل التالي:

x = ['Adam', 'Noah', 'Jacob']
for name in x:
    if name == 'Adam':
        continue

    print (name)

>> Noah
>> Jacob

لدينا قائمةً تحتوي على ثلاثة أسماء، إذ نهدف من البرنامج إلى طباعة أيّ اسم في القائمة غير اسم آدم Adam، فلذلك كتبنا جملةً شرطيةً بداخل حلقة التكرار for، إذ تطرح الجملة الشرطية على المفسر سؤالًا وهو: هل الاسم الحالي يساوي آدم؟ ستكون الإجابة في أول دورة صحيحةً True، ولذلك سينفِّذ المفسر التعليمات المندرجة أسفل الشرط، إذ توجد تعليمة وحيدة مندرجة أسفل هذا الشرط وهي الكلمة المفتاحية continue، والتي تخبر مفسر اللغة كما ذكرنا ببساطة، بعدم استكمال الدورة الحالية والذهاب مباشرةً إلى الدورة التالية، أي العنصر التالي في القائمة وهكذا سيُطبَع الاسمان Noah و Jacob فقط.

يمكن استخدام الكلمتان المفتاحيتان السابق ذكرهما break وcontinue في حلقات while وحلقات for على حد سواء، وفيما يلي مثال على استخدام continue في حلقة while.

سنطبع الأعداد الزوجية فقط بين الصفر والعشرة ونتخطى الأرقام الفردية، كما يمكننا التحقق من كون الرقم فرديًا أو زوجيًا بصورة بسيطة في الرياضيات عبر ناتج باقي القسمة على 2، إليك المثال:

x = 0
while x <= 10:
    if x % 2 != 0:
        x += 1
        continue
    print (x)
    x += 1

تعرفت الآن على كيفية التحكم في مسار تنفيذ البرنامج وآلية اتخاذ القرار أثناء التنفيذ لذا جرب الآن كتابة برامج وتدرب بها على ما تعلمته، وسننتقل في المقال التالي إلى الحديث عن الدوال في لغة بايثون.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...