ملخص
علّم الدرس الحلقات كيف يُكتب التكرار؛ وهذا الدرس يعلّم كيف يُكتب كتابةً صحيحة وكيف نعرف لماذا هو صحيح. يبدأ بالأنماط التي تُبنى بها أكثر الحلقات (العدّاد، والمجمِّع، والقيمة العظمى والقيمة الصغرى، والقيمة الحارسة، والعَلَم)، وكل نمط منها معرَّف بما تدل عليه متغيرته بعد كل جولة. وتقود هذه الملاحظة إلى المفهوم المركزي: اللامتغير، وهو عبارة عن المتغيرات تصحّ قبل الجولة الأولى وبعد كل جولة، وتستلزم مع شرط الخروج النتيجةَ. إنه استقراء على عدد الجولات، وبه تُصمَّم الحلقة بالعكس: أولًا ما يجب أن يصحّ في النهاية، ثم اللامتغير، وأخيرًا الجسم. ويُعلَّل التوقف بالمتغاير، الذي قُدِّم في الدرس من المسألة إلى الخوارزمية، ويعرض الدرس ثلاث حلقات لا تتوقف: واحدة بشرط حقيقي، وواحدة بعدّاد بلا إشارة، وواحدة يفيض عدّادها ذو الإشارة، وهذا سلوك غير معرَّف. ويُختم بأول تعارف مع مصحّح الأخطاء في Visual Studio Code، الذي يوقف البرنامج عند سطر ويعرض متغيراته جولةً بعد جولة.
أهداف التعلم
- أن يتعرّف في الحلقة على أنماط العدّاد والمجمِّع والقيمة العظمى والقيمة الحارسة، وأن يستعملها لتصميم حلقات جديدة.
- أن يصوغ لامتغير حلقة بسيطة وأن يتحقق من أنه محفوظ في جولة كيفما كانت.
- أن يعلّل توقف حلقة بكمية صحيحة تتناقص ومحدودة من الأسفل.
- أن يتابع تنفيذ حلقة بمصحّح الأخطاء في Visual Studio Code، بنقطة توقف وبعرض المتغيرات.
الأنماط
ما تدل عليه المتغيرة
أكثر الحلقات لا تُخترع: إنها تُركَّب من قطع قليلة تعود في كل البرامج. وكل قطعة متغيرةٌ لها تهيئة قبل الحلقة، وتحديث داخلها، وفوق ذلك دلالة تصحّ بعد كل جولة. ومعرفة القطع بدلالتها، لا بشكلها، هي ما يسمح بجمعها دون خطأ.
- العدّاد قيمته عدد البيانات التي عولجت (أو عدد ما يحقق منها شرطًا). يُهيَّأ بالقيمة 0، لأنه لم يُعالَج أي معطى قبل الجولة الأولى، ويُحدَّث بـ
++count، فقط حين يكون هناك ما يُعدّ. - المجمِّع قيمته تركيب البيانات التي عولجت: مجموعها، أو جداؤها. يُهيَّأ بالعنصر المحايد للعملية (0 للجمع، و1 للضرب)، لأن مجموع لا شيء من البيانات هو 0 وجداء لا شيء منها هو 1.
- القيمة العظمى قيمتها أكبر البيانات التي عولجت، والقيمة الصغرى أصغرها. والقيمة العظمى لمجموعة خالية من البيانات لا وجود لها: ولذلك تُهيَّأ بأول معطى، لا بعدد مختار عشوائيًا.
- القيمة الحارسة قيمة في المدخلات ليست معطى، بل علامة على أن البيانات انتهت. ويقتضي النمط القراءة مرة قبل الحلقة ومرة أخرى في آخر الجسم، كما فعل الدرس الحلقات حين جمع حتى الصفر، بحيث يفحص الشرط كل قيمة قبل أن تُعالَج، ولا تُعدّ القيمة الحارسة معطى أبدًا.
- العَلَم متغير من النوع
boolيدل على ما إذا كان أمر ما قد وقع ولو مرة بين البيانات التي عولجت. يُهيَّأ بـfalseويصيرtrueفي أول مرة يقع فيها الأمر؛ ولا تعيده أي جولة لاحقة إلىfalse.
مثال يجمع القطع كلها
يدوّن سجلّ للأمطار عدد المليمترات التي هطلت في كل يوم. يقرأ البرنامج أولًا عتبةً، ثم قياسات عدة أيام، تنتهي بعدد سالب، لا يمكن أن يكون قياسًا ويؤدي دور القيمة الحارسة؛ ويكتب عدد القياسات، ومتوسطها، والقيمة العظمى، وعدد الأيام التي تجاوزت العتبة، وهل كان هناك يوم بلا مطر.
#include <iostream>#include <print>int main(){ double threshold{}; std::cin >> threshold; int count{0}; // عدّاد: القياسات المعالَجة int aboveCount{0}; // عدّاد: القياسات فوق العتبة double total{0.0}; // مجمِّع: مجموع القياسات double largest{0.0}; // القيمة العظمى: لا معنى لها إلا إذا count > 0 bool dryDay{false}; // عَلَم: كان هناك يوم بلا مطر double value{}; std::cin >> value; while (std::cin && value >= 0.0) { if (count == 0 || value > largest) { largest = value; } ++count; total += value; if (value > threshold) { ++aboveCount; } if (value == 0.0) { dryDay = true; } std::cin >> value; } if (count == 0) { std::println("لا توجد قياسات."); } else { std::println("عدد القياسات: {}؛ المتوسط: {:.2f} مم", count, total / count); std::println("القيمة العظمى: {:.1f} مم؛ الأيام فوق {:.1f} مم: {}", largest, threshold, aboveCount); std::println("أيام بلا مطر: {}", dryDay ? "نعم" : "لا"); }}104.5 0 12.5 21.5 7.5 -1عدد القياسات: 5؛ المتوسط: 9.20 ممالقيمة العظمى: 21.5 مم؛ الأيام فوق 10.0 مم: 2أيام بلا مطر: نعمأربعة قرارات تستحق التعليق. الشرط count == 0 || value > largest يهيّئ القيمة العظمى بأول معطى دون قراءة مستقلة: في الجولة الأولى يكون العدّاد 0 ويقع الإسناد دائمًا؛ وفي الجولات اللاحقة، لا يقع إلا إذا تجاوز المعطى القيمة العظمى. والمقارنة value == 0.0 مضبوطة، لأن القيمة قُرئت ولم تُحسب: الرقم 0 يتحوّل إلى الصفر المضبوط، وتحذير الدرس أعداد الفاصلة العائمة من == يخصّ نتائج العمليات. ويتضمن شرط الحلقة std::cin، بحيث إن مدخلات تنتهي بلا قيمة حارسة تنهي الحلقة هي أيضًا. ولا يُحسب المتوسط إلا إذا وُجدت قياسات: إذا كان count يساوي 0، فإن total / count يكون ، وهو في الفاصلة العائمة ليس خطأ، بل القيمة «ليس عددًا»، التي كان البرنامج سيكتبها دون تنبيه.
البرهان
قبل الحلقة: العتبة 10، والعدّادان والمجمِّع قيمتها 0، والعَلَم خاطئ، وقد قُرئ القياس الأول، 4.5. والقيمة العظمى 0، لكن هذه القيمة لا تعني شيئًا ما دام
countيساوي 0.الجولة الأولى:
countيساوي 0، فيصير 4.5 القيمة العظمى؛ ويرتفع العدّاد إلى 1 والمجموع إلى 4.5. ويُقرأ 0.الجولة الثانية: 0 لا يتجاوز القيمة العظمى، لكنه يرفع العَلَم. ويُقرأ 12.5.
الجولة الثالثة: 12.5 هو القيمة العظمى الجديدة ويتجاوز العتبة: يرتفع
aboveCountإلى 1. ويُقرأ 21.5.الجولة الرابعة: 21.5 هو القيمة العظمى الجديدة ويتجاوز العتبة كذلك. ويُقرأ 7.5.
الجولة الخامسة: 7.5 لا يغيّر القيمة العظمى ولا
aboveCount؛ ويبلغ المجموع 46. ويُقرأ .يفحص الشرط ، وهو سالب: تنتهي الحلقة دون أن تعالجه. والمتوسط .
ولنلاحظ أن كل متغيرة، في كل صف من الشكل، تحقق دلالتها بالنسبة إلى القياسات التي عولجت حتى تلك اللحظة: total مجموعها، وlargest قيمتها العظمى، وdryDay يقول هل كان بينها صفر. وهذه الخاصية، التي تصحّ بعد كل جولة، لها اسم.
جارٍ تحميل المحتوى…