انتقل إلى المحتوى
Topos Uranos

ملخص

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

أهداف التعلم

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

الغاية

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

فلغة C++ إذن أداة الدورة لا غايتها. غير أن الأداة ليست محايدة إزاء ما يُتعلَّم بها، واختيار هذه الأداة، الذي يبدو للوهلة الأولى أصعب الاختيارات، مقصود؛ والقسم اللاحق يسوّغه. ومع ذلك يحسن أن نقدّم نتيجته الأوضح: كل خلاصة وحدة تتضمّن قسمًا ثابتًا، «ما يصحّ في أي لغة»، يفصل ما تُعُلِّم عن صورته في C++ ويبيّن كيف يُعبَّر عنه، أو ما الذي يتغيّر، في لغات أخرى. ويترتّب على ذلك أن الطالب الذي يُتمّ الدورة لن يعرف الكتابة بلغة C++ فحسب، بل سيتعرّف في أي لغة الأفكارَ نفسها في ثوب آخر.

لماذا C++ وليس لغة ألطف

ثمة لغات منحنى تعلّمها أنعم، مثل Python، يُكتب فيها أول برنامج مفيد في أسطر قليلة، دون تصريح بالأنواع، ودون ترجمة، ودون التساؤل عن المكان الذي تعيش فيه البيانات. ولو كانت الغاية كتابة برامج تعمل في أقرب وقت، لكان ذلك هو الطريق. أما غاية هذه الدورة فهي فهم ما يفعله البرنامج، ولهذا تناسبها لغة لا تخفي الآلة. وتُلزم C++ برؤية ستة أمور تحلّها اللغات الأكثر راحةً في صمت:

  • الأنواع. يُصرَّح بكل معطى مع نوع يحدّد القيم التي يمكن أن يأخذها، والحيّز الذي يشغله، والعمليات التي يقبلها؛ ويرفض المترجم ما لا يتوافق قبل تنفيذ أي شيء.
  • الترجمة. الكتابة والترجمة والربط والتنفيذ لحظات متمايزة، وكل خطأ ينتمي إلى إحداها؛ ومعرفة اللحظة التي ينتمي إليها نصفُ تصحيحه.
  • الذاكرة. المتغير خانة ذاكرة لها اسم، ولها مدة حياة ونطاق رؤية؛ والمرجع اسم آخر للخانة نفسها، والمرجع إلى خانة لم تعد موجودة خطأ حقيقي.
  • كلفة النسخ. تمرير متجه إلى دالة قد ينسخه كاملًا؛ والاختيار بين التمرير بالقيمة والتمرير بالمرجع قرار يتّخذه من يبرمج، لا الآلة.
  • حدود الأعداد. العدد الصحيح ذو 32 بتًا لا يتجاوز 2 147 483 6472\,147\,483\,647، وعدد الفاصلة العائمة لا يحفظ 0,10{,}1 بدقة.
  • السلوك غير المعرَّف. ما لا يعرّفه المعيار (الخروج عن حدود مصفوفة، وفيضان عدد صحيح ذي إشارة، وقراءة متغير غير مهيَّأ) لا يُنتج خطأً مضمونًا، بل أي شيء؛ ولهذا تترجم الدورة دائمًا مع التحذيرات ومع الكواشف (sanitizers).

يبيّن المثال الآتي ذلك على نطاق صغير. يحسب البرنامج مضروبات الأعداد من 11 إلى 1515 في متغير من النوع int. في Python، حيث تنمو الأعداد الصحيحة بلا حدّ، كان الحساب نفسه سيطبع دون اعتراض 13!=6 227 020 80013! = 6\,227\,020\,800؛ أما في C++ فإن جداء 12!12! في 1313 لا يتّسع له int، والكاشف عن السلوك غير المعرَّف، الذي تترجم به الدورة كل أمثلتها، يوقف البرنامج عند السطر بعينه:

برنامج بلغة C++
#include <print>​int main(){    int factorial{1};    for (int n{1}; n <= 15; ++n) {        factorial = factorial * n;   // هل يتّسع int للجداء؟        std::println("{}! = {}", n, factorial);    }}
المخرجات
1! = 12! = 23! = 64! = 245! = 1206! = 7207! = 50408! = 403209! = 36288010! = 362880011! = 3991680012! = 479001600main.cpp:7:31: runtime error: signed integer overflow: 479001600 * 13 cannot be represented in type 'int'

انتهى البرنامج بالرمز 1.

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

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

غير أن C++ لغة كبيرة، وعلى دورة في الأسس أن تقاوم إغراء تدريسها كلها. وتقتصر هذه الدورة الأولى على البرمجة الهيكلية (البيانات، والتعابير، والتحكم في التدفق، والتسلسلات، والنصوص، والدوال) وفق المعيار C++23، بصوره الحديثة: الإخراج بـstd::println، والتسلسلات بـstd::array وstd::vector، والنصوص بـstd::string، وخوارزميات المكتبة في صورتها القائمة على النطاقات (ranges). وتترك لدورة البرمجة بلغة C++ II ما يتطلّب هذا الأساس: المؤشرات والذاكرة الديناميكية، والأصناف ذات التوابع، والقوالب الخاصة، والدوال المجهولة، والاستثناءات.

الفئة المستهدفة والمعارف السابقة

تتوجّه الدورة إلى من لم يبرمج قط، من أي برنامج دراسي ومنذ السنة الأولى: طلاب المعلوماتية الذين يحتاجون إلى أساس متين قبل دورات بنى المعطيات والأنظمة، وطلاب الهندسة والعلوم الذين يحتاجون إلى الحساب بالحاسوب دون الوثوق به ثقة عمياء، وطلاب الرياضيات الذين يريدون أن يروا خوارزمياتهم وقد صارت برامج تُنفَّذ.

إنها دورة من المستوى 1، بلا متطلبات سابقة، مكتفية بذاتها. ولا تفترض إلا أمرين: الحساب المدرسي، بما فيه القسمة الصحيحة وباقيها، والتعامل الأولي مع الحاسوب (إنشاء مجلد، وحفظ ملف، وفتح برنامج). وما تستعمله من التمثيل الثنائي، أو من الاستدلال بالحالات، أو من منطق الشروط، أو من الاستقراء، تعلّمه في الموضع الذي تحتاج إليه فيه: النظام الثنائي في الدرس الخاص بالأعداد الصحيحة؛ وقوانين دي مورغان في الدرس الخاص بالعلاقات والمنطق؛ والاستقراء في الدرس الخاص بالاستدعاء الذاتي. فالإحالات إلى دورات أخرى في الموقع، التي تظهر في الدروس، هي إذن تعميقات، لا متطلبات.

إلى أين يقود

ويترتّب على ما سبق موقع الدورة في الموقع. فهي بلا متطلبات سابقة، وهي هدف لبرنامجين دراسيين، «المعلوماتية والحوسبة» و«الهندسة»، لأن البرمجة في كليهما أداة وموضوع في آن واحد. ولذلك يحسن أن تكون من أولى دورات هذين البرنامجين، إلى جانب LaTeX للكتابة الأكاديمية والمنطق الرياضي 1: منطق القضايا.

ولها دورة مكمّلة يمكن متابعتها قبلها أو بالتوازي معها أو بعدها. فدورة المنطق الرياضي 1: منطق القضايا تدرس نظريًّا ما يُستعمل هنا عمليًّا: الشروط المركّبة، وجداول الصدق، وقوانين دي مورغان في الوحدة 3، وفكرة البرهان على أن إجراءً ما صحيح، وهي فكرة تتّخذ في هذه الدورة صورة اللامتغير في الحلقة وصورة الاستقراء على الاستدعاء الذاتي. ودورة الجبر والهندسة 1، من جهتها، تبرهن نتائج الأعداد التي تبرمجها الدورة: القسمة الإقليدية، وخوارزمية إقليدس، وأنظمة العدّ، وقاعدة هورنر. ودورة LaTeX للكتابة الأكاديمية تعلّم، في درسها الكتابة الجماعية، التحكم في الإصدارات باستعمال Git، الذي توصي هذه الدورة باستعماله منذ البرنامج الأول.

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

أهداف التعلّم العامة

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

  1. الهدف 1. أن يحلّ المسائل ببرامج: أن يحدّد مواصفات ما يدخل وما يخرج، ويصمّم خوارزمية، ويتتبّعها يدويًّا، ثم يكتبها ويترجمها وينفّذها ويصحّح أخطاءها، مفسّرًا رسائل المترجم وتحذيراته.
  2. الهدف 2. أن يختار النوع المناسب لكل معطى، ويستدلّ على حدود تمثيله: مدى قيم الأعداد الصحيحة، والفيضان، وتقريب الفاصلة العائمة، وترميز النصوص.
  3. الهدف 3. أن يبني تعابير صحيحة، عارفًا بالأسبقية، وتحويلات الأنواع، والآثار الجانبية، وما يتركه المعيار غير معرَّف.
  4. الهدف 4. أن يصمّم التحكم في التدفق بقرارات وحلقات صحيحة تتوقّف، وأن يسوّغ صحّتها بلامتغير.
  5. الهدف 5. أن يفكّك مسألة إلى دوال ذات واجهات واضحة، ويختار طريقة تمرير الوسائط، ويحلّ المسائل بالاستدعاء الذاتي.
  6. الهدف 6. أن يمثّل البيانات المركبة ويعالجها (التسلسلات، والجداول، والسجلات، والنصوص، والملفات) بالخوارزميات الأساسية وبالمكتبة القياسية، مقدِّرًا كلفتها.
  7. الهدف 7. أن ينظّم برامج أكبر في عدة ملفات، ويحدّد مواصفاتها بشرط مسبق وشرط لاحق، ويختبرها اختبارًا منهجيًّا، ويحتجّ لصحّتها.

لخمسة أهداف وحدتها الخاصة: الهدف 2 وحدة البيانات والأنواع؛ والهدف 3 وحدة التعابير؛ والهدف 4 وحدة التحكم في التدفق؛ والهدف 5 وحدة الدوال؛ والهدف 6 وحدة البيانات المركبة، التي تمتدّ في وحدة النصوص والملفات، حيث يعود الهدف 2 مع ترميز UTF-8. أما الهدفان الآخران فيسريان في الدورة كلها. فالهدف 1 وحدته الرئيسية هي الوحدة الأولى، التي تعلّم دورة العمل من تحديد المواصفات والكتابة والترجمة والتنفيذ، ومعها درس تصحيح الأخطاء في الوحدة الأخيرة؛ لكنه يُمارَس في جميع الوحدات، لأن كل برنامج في الدورة يُترجَم ويُنفَّذ ويُصحَّح. والهدف 7 وحدته الرئيسية هي الوحدة الأخيرة، وحدة البرامج الأكبر؛ لكنه يبدأ في دليل الأسلوب في الأولى، ويستمرّ في الثوابت في الثانية، ويتّخذ صورته في عقود الخامسة، التي تصحب كل دالة منذ ذلك الحين، وفي اللامتغيرات في الرابعة والسادسة. ويترتّب على ذلك أن بلوغهما لا يمكن نسبته إلى وحدة واحدة، وأن الأجدر تنميتهما على امتداد الدورة كلها.

المحتويات

تنتظم الدورة في عشر وحدات: هذا التقديم، وثماني وحدات محتوى، وختام. وتُفتتح كل وحدة محتوى بدرس مقدّمة يعرض دروسها، وما تفترضه معلومًا، والمسألة التي تحلّها، ويبدأ بتقييم الدخول؛ وتُختتم بدرس خلاصة يعيد بناء سلسلة المفاهيم في الوحدة، ويفصل ما يصحّ في أي لغة عن صورته في C++، ويجمع السلوك غير المعرَّف في الوحدة، ويعيد في تقييم الخروج مهارات تقييم الدخول، ويقترح تحدّيات أصعب من مسائل الدروس.

الوحدة 0. تقديم الدورة

تتألف من هذا الدرس، الذي يحدّد غاية الدورة واختيار اللغة والأهداف العامة والمحتويات والعبء والتصميم.

الوحدة 1. الخطوات الأولى

غايتها أن تقود الطالب من مسألة مصوغة بالكلمات إلى برنامج يُترجَم ويُنفَّذ ويقرأ البيانات ويكتب النتائج، وهو يعرف ما فعلته كل أداة في الطريق. وتبدأ دون شيفرة، لأن الخوارزمية تسبق البرنامج؛ وفي نهايتها لا يعرف الطالب من C++ إلا القليل، لكنه يعرف كيف يُعمَل بها.

  1. الخطوات الأولى في C++: مقدمة.
  2. من المسألة إلى الخوارزمية: تحديد مواصفات المدخلات والمخرجات، والخطوات المرقّمة، والتتبع اليدوي، والتسلسل، والقرار، والتكرار.
  3. البرامج والمترجمات ولغة C++: المعالجة المسبقة، والترجمة، والربط؛ واللغات المترجَمة في مقابل اللغات المفسَّرة؛ ومعايير اللغة.
  4. تثبيت بيئة العمل على Windows و macOS و Linux: الأدلّة الثلاثة الكاملة، والمترجم، وVisual Studio Code وإضافته الخاصة بـC++، والتحقّق، والمشكلات الشائعة.
  5. الترجمة والتنفيذ والإعداد: خيارات الدورة، والأخطاء والتحذيرات، والكواشف، ومهمة البناء (build task) في المحرر، وترميز وحدة التحكم.
  6. تشريح البرنامج: التضمين، وmain، والتعليمات، والكتل، والتعليقات، ودليل الأسلوب في الدورة.
  7. المدخلات والمخرجات والأخطاء: std::cin، وstd::println ومواصفات التنسيق، والمدخلات غير المتوقعة، وتصنيف الأخطاء.
  8. الخطوات الأولى في C++: الخلاصة والتحديات.

الوحدة 2. البيانات والأنواع

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

  1. البيانات والأنواع: مقدمة.
  2. المتغيرات والذاكرة: التصريح والتهيئة بالأقواس المعقوصة، والإسناد، وتتبّع الحالة، والأسماء، والمتغير غير المهيَّأ.
  3. الأعداد الصحيحة وتمثيلها: الأساسان 2 و16، ومدى قيم كل نوع، والمتمِّم الثنائي، والفيضان في الأعداد ذات الإشارة وعديمة الإشارة.
  4. أعداد الفاصلة العائمة: لماذا لا يكون 0,10{,}1 دقيقًا، والتقريب المتراكم، والمقارنة بهامش تسامح، واللانهاية، والقيمة التي ليست عددًا (NaN).
  5. المحارف والقيم المنطقية والتحويلات والثوابت: رمز المحرف، والتحويلات الضمنية والصريحة، ورفض التحويلات التي تُضيع معلومات، وconst وconstexpr وauto.
  6. البيانات والأنواع: الخلاصة والتحديات.

الوحدة 3. التعابير والعوامل

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

  1. التعابير والعوامل: مقدمة.
  2. العمليات الحسابية: خارج القسمة والباقي مع الأعداد السالبة، وشجرة التعبير، والأسبقية، والتجميعية، ونوع النتيجة.
  3. العلاقات والمنطق: الشروط المركّبة، ونفيها بقوانين دي مورغان، والحساب المختصر، والخطأ في 1 < x < 5.
  4. الإسناد والآثار الجانبية والسلوك غير المعرّف: قيمة التعبير وأثره، والزيادات، وترتيب الحساب، وفهرس ما لا يعرّفه المعيار.
  5. البتات والمكتبة الرياضية: العوامل البتّية، والإزاحات، والأقنعة، و<cmath>، وثوابت <numbers>.
  6. التعابير والعوامل: الخلاصة والتحديات.

الوحدة 4. التحكم في التدفق

غايتها أن تعلّم التحكم في ترتيب التنفيذ بالقرارات والحلقات، والاستدلال على صحّتها: أن تُعالَج كل حالة، وأن تفعل كل حلقة ما ينبغي، وأن تتوقّف. وهي تحقّق ما أعلنه الدرس الأول من الدورة: القرار والتكرار، مكتوبَين الآن ومتحقَّقًا منهما.

  1. التحكم في التدفق: مقدمة.
  2. القرارات: if وelse المتسلسلة والمتداخلة، والحالات المنفصلة والشاملة، وswitch مع enum class ومزالقها.
  3. الحلقات: while وdo وfor، وتتبّع الحلقة، والتحويل بين صورها، والحلقات المتداخلة.
  4. تصميم حلقات صحيحة: أنماط العدّاد والمجمِّع والقيمة العظمى والقيمة الحارسة، واللامتغير، والتوقّف، وأول احتكاك بمصحّح الأخطاء.
  5. الخوارزميات العددية: اختبار الأولية، وخوارزمية إقليدس، وتغيير الأساس، وقاعدة هورنر، وطريقة التنصيف، ولكل منها تسويغها.
  6. التحكم في التدفق: الخلاصة والتحديات.

الوحدة 5. الدوال

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

  1. الدوال: مقدمة.
  2. الدوال: التصريح والتعريف والاستدعاء، ومكدس الاستدعاءات، والشرط المسبق والشرط اللاحق، والدالة التي لا تُعيد قيمة.
  3. الوسائط ونطاق الرؤية: التمرير بالقيمة وبالمرجع وبالمرجع الثابت، والنتائج المتعددة بالربط المهيكل، ونطاق الرؤية ومدة حياة المتغيرات.
  4. التصميم بالدوال: التنقيح التدريجي، والواجهة قبل الجسم، وقاعدة «دالة واحدة، مهمة واحدة»، والتحميل الزائد.
  5. الاستدعاء الذاتي: الحالة الأساسية والحالة التراجعية، والصحة والتوقّف بالاستقراء، والمكدس وكلفة الاستدعاء الذاتي.
  6. الدوال: الخلاصة والتحديات.

الوحدة 6. البيانات المركبة

غايتها أن تعلّم تمثيل مجموعات البيانات ومعالجتها بالخوارزميات الأساسية، المكتوبة يدويًّا والمأخوذة من المكتبة، مع تقدير كلفتها. وهي تنقل من المعطى المنفرد إلى المجموعة، ومن سؤال «هل هو صحيح؟» إلى سؤال «كم يكلّف؟».

  1. البيانات المركبة: مقدمة.
  2. المصفوفات: std::array، والمرور بالفهارس وبحلقة for على النطاق، والفهرس داخل الحدود، ومصفوفات C للمقابلة.
  3. المتجهات: std::vector، وقراءة سلسلة قيم مجهولة الطول، والتجميع، والترشيح، والتحويل، والحجم والسعة.
  4. كلفة الخوارزمية: عدّ العمليات المهيمنة، ورتب النمو، وقياس الزمن.
  5. البحث والترتيب: البحث الخطي والبحث الثنائي، والترتيب بالاختيار والترتيب بالإدراج مع لامتغيراتهما، وخوارزميات المكتبة.
  6. الجداول: الجداول ذات البعدين، والمرور عليها صفًّا صفًّا وعمودًا عمودًا، والمنقولة، والجداء، والجدول في متجه مسطَّح.
  7. السجلات: struct، والمهيِّئات المعيَّنة، والسجلات بوصفها وسائط، والترتيب بحسب حقل.
  8. البيانات المركبة: الخلاصة والتحديات.

الوحدة 7. النصوص والملفات

غايتها أن تعلّم التعامل مع النص بوصفه معطى، وأن تجعل البرنامج يقرأ الملفات ويكتبها دون أن ينهار أمام مدخلات سيئة التكوين. وفي نهايتها يستطيع الطالب كتابة برامج تعالج بيانات حقيقية، بما فيها من علامات تشكيل وأخطاء.

  1. النصوص والملفات: مقدمة.
  2. السلاسل النصية: std::string وعملياتها، وnpos، والعروض std::string_view، وسلاسل C للمقابلة.
  3. النص ليس ASCII: ترميز UTF-8، والبايتات والمحارف، والعمليات التي تُفسد النص.
  4. قراءة المدخلات بإحكام: std::getline، وحالة المجرى، والاستدراك بعد معطى غير صالح، والتحقق من الصحة بـstd::from_chars.
  5. الملفات النصية: الفتح، والقراءة سطرًا سطرًا، والكتابة، والإلحاق، ومعالجة ملف من القيم المفصولة بفواصل.
  6. النصوص والملفات: الخلاصة والتحديات.

الوحدة 8. برامج أكبر

غايتها أن تعلّم تنظيم البرامج التي لم تعد تتّسع لملف واحد ولا للذهن، والتحقّق منها وتصحيح أخطائها. وهي تُغلق الدائرة التي فتحها الدرس الأول: تحديد المواصفات، ثم البناء، ثم التحقّق؛ وتنتهي خلاصتها بمشروع نهائي يجمع الدورة كلها.

  1. برامج أكبر: مقدمة.
  2. ملفات متعددة ومكتبات خاصة: ملف الترويسة وملف التنفيذ، وحرّاس التضمين، وقاعدة التعريف الواحد، والترجمة المنفصلة.
  3. اختبار البرامج: حالات الاختبار المستخرجة من المواصفات، والاختبارات الآلية، وassert وstatic_assert.
  4. تصحيح أخطاء البرامج: مصحّح الأخطاء في Visual Studio Code، ونقاط التوقف، ومكدس الاستدعاءات، واستراتيجية منهجية لتحديد موضع الخطأ.
  5. برامج أكبر: الخلاصة والتحديات.

الوحدة 9. ختام الدورة

تتألف من درس الحصيلة النهائية لدورة البرمجة بلغة C++ I، الذي يذكّر بالأهداف العامة السبعة، ويبيّن في رسم في أي الوحدات والدروس يُعمَل على كل منها، ويجمع حسب الهدف المحاولة الأولى في تقييمات الخروج، ويشير إلى حيث تتواصل الدراسة.

العبء الدراسي والساعات المعتمدة

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

النتائج

تضمّ دروس الدورة في مجموعها من المسائل المحلولة 105105، ومن المسائل المقترحة 105105، ومن التحديات 5252، فضلًا عن ستة عشر تقييمًا للوحدات وسبعين تمرينًا قصيرًا يراجعها الموقع في الحال. والعبء المقدَّر لكل وحدة، مقرَّبًا إلى أقرب ساعة، هو الآتي:

  • الوحدة 0، تقديم الدورة: 11 ساعة.
  • الوحدة 1، الخطوات الأولى: 2828 ساعة.
  • الوحدة 2، البيانات والأنواع: 2222 ساعة.
  • الوحدة 3، التعابير والعوامل: 2222 ساعة.
  • الوحدة 4، التحكم في التدفق: 2222 ساعة.
  • الوحدة 5، الدوال: 2222 ساعة.
  • الوحدة 6، البيانات المركبة: 3030 ساعة.
  • الوحدة 7، النصوص والملفات: 2121 ساعة.
  • الوحدة 8، برامج أكبر: 2020 ساعة.
  • الوحدة 9، ختام الدورة: أقل من 11 ساعة.

ويبلغ المجموع نحو 188188 ساعة من عمل الطالب. ويحسن أن يُقرأ هذا الرقم على حقيقته: تقديرًا لطالب يكتب الأمثلة كلها ويترجمها، ويحلّ المسائل والتحديات كلها. ومن سبق له أن برمج بلغة أخرى سيحتاج إلى أقل من ذلك بكثير في الوحدات الأولى؛ ومن لم يثبّت برنامجًا قط ولم يقرأ رسالة خطأ قد يحتاج إلى أكثر، ولا سيما في الوحدة 1، وهي أيضًا، مع وحدة البيانات المركبة، أطول الوحدات.

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

الوتيرة المقترحة

ولتسمية الوتائر، تعتمد هذه الخطة المعيار نفسه الذي تعتمده الخطط الأخرى في الموقع: الدوام الكامل هو دوام عام أكاديمي من 6060 ساعة معتمدة، أي نحو 16501650 ساعة موزّعة على نحو أربعين أسبوعًا، أي نحو 4040 ساعة في الأسبوع، والدوام الجزئي نصفه، أي نحو 2020 ساعة في الأسبوع. ويترتّب على ذلك وتيرة موصى بها قدرها فصل دراسي من ستة عشر أسبوعًا، بنحو 1212 ساعة دراسة في الأسبوع، أي أقل قليلًا من ثلث الدوام الكامل؛ ومع النطاق الواقعي، من 1212 إلى 1616 ساعة في الأسبوع. ويمكن أن يُتقاسَم هذا الفصل مع دورة المنطق الرياضي 1: منطق القضايا، التي تُتعرَّف جداول الصدق فيها وفكرة البرهان في الشروط واللامتغيرات في هذه الدورة.

والوتيرة المكثّفة، بنحو 2020 ساعة في الأسبوع، أي دوام جزئي، تُتمّ الدورة في تسعة أسابيع أو عشرة. والوتيرة الأرحب، بنحو 66 ساعات في الأسبوع، تمدّها إلى فصلين دراسيين ينقسمان مناصفة تقريبًا: فالوحدات من 0 إلى 4، من الخوارزمية إلى التحكم في التدفق، تشغل نحو 9595 ساعة، والوحدات من 5 إلى 9، من الدوال إلى المشروع النهائي، نحو 9393. والقطع طبيعي: ففي نهاية الوحدة 4 يكتب الطالب برامج كاملة في دالة main واحدة، ويعلّمه النصف الثاني تنظيمها.

الساعات المعتمدة

تقيس الساعات المعتمدة في هذا الموقع مجموع الجهد الذي تتطلّبه الدورة ممن يدرسها (القراءة، والمسائل، والتحديات، والمراجعة)، لا ساعات الحصص. فالساعة المعتمدة الواحدة تعادل نحو 27,527{,}5 ساعة عمل، وعامٌ من الدراسة بدوام كامل يعادل 6060 ساعة معتمدة، أي نحو 16501650 ساعة؛ وهو المعيار نفسه الذي سُمّيت به وتائر الدراسة في القسم السابق.

غير أننا إذا قسمنا الساعات المقدَّرة 188188 على 27,527{,}5 حصلنا على 6,8، الذي يُقرَّب إلى 77. وإذا قُبل للساعة المعتمدة نطاق من 2525 إلى 3030 ساعة عمل، كان عدد الساعات المعتمدة CC للدورة محصورًا بين 6,3 و7,5:

(18830)≤C≤(18825)\left( \frac{188}{30} \right) \leq C \leq \left( \frac{188}{25} \right)

ومن ثَمّ فللدورة 77 ساعات معتمدة، أي أكثر قليلًا من تُسع عام من الدوام الكامل. وليس الرقم سهوًا: فالدورة تستغرق ما ينبغي أن تستغرقه لتعليم الأسس، ولم تُختصَر لتوافق عددًا مستديرًا من الساعات المعتمدة.

وفائدتها عملية: فهي تتيح المقارنة بين أعباء دورات الموقع، وتقدير عدد ما يحسن دراسته منها في آن واحد دون تجاوز الوقت المتاح. فمن كان لديه، مثلًا، دوام جزئي طوال فصل دراسي من ستة عشر أسبوعًا، أي نحو 320320 ساعة، أمكنه أن يتناول دورات يبلغ مجموعها نحو 1212 ساعة معتمدة؛ ومع الدوام الكامل في الفصل نفسه، نحو 2323.

وهذه الساعات المعتمدة مقياس خاص بالموقع لتخطيط الدراسة: فهي لا تقابل أي نظام رسمي للساعات المعتمدة، ولا تعني اعترافًا أكاديميًا من أي مؤسسة.

تصميم الدورة

نمط الدراسة

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

بنية الدرس

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

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

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

القارئ الصوتي

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

التقييم

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

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

مساعدو الذكاء الاصطناعي

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

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

كيف تُدرَس هذه الدورة

صُمّمت الدورة لتُدرَس بالترتيب. فكل وحدة تفترض الوحدات السابقة: التعابير تُكتب بأنواع الوحدة الثانية، والحلقات بتعابير الثالثة، والدوال تغلّف حلقات الرابعة، والبيانات المركبة تُعالَج بالدوال؛ وتجاوز درس يُلزم، عاجلًا أو آجلًا، بالعودة إليه.

والقاعدة الرئيسية واحدة: كتابة كل مثال وترجمته. فالبرمجة لا تُتعلَّم بالقراءة، بل بالكتابة والترجمة وقراءة ما يجيب به المترجم. ولذلك يثبّت الطالب بيئته الخاصة متّبعًا درس تثبيت بيئة العمل على Windows و macOS و Linux، ويعيد إنجاز كل برنامج في Visual Studio Code الخاص به، بالخيارات التي يعلّم درس الترجمة والتنفيذ والإعداد ضبطها؛ ومن يستعمل حاسوبًا لا يستطيع أن يثبّت عليه برامج يتاح له، مؤقتًا، مترجم عبر الإنترنت يصفه درس التثبيت. ويحسن أن تُكتب الأمثلة يدويًّا بدل نسخها، لأن اليد تحفظ ما تتجاوزه العين؛ ويحسن أن يُتنبَّأ بمخرجات كل برنامج قبل تنفيذه، لأن الفرق بين المتنبَّأ به والحاصل هو بالضبط ما بقي ليُتعلَّم؛ ويحسن أن يُقرأ كل تحذير من المترجم سؤالًا يستحق الجواب، لا ضجيجًا يُحتمَل. وبعد أن يعمل البرنامج، يحسن فوق ذلك تعديله عمدًا (حذف فاصلة منقوطة، أو تغيير نوع، أو الخروج عن حدود متجه) وقراءة ما يقوله المترجم أو الكاشف، لأن كل خطأ مُستثار خطأٌ سيُعرَف فيما بعد.

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

التحكم في الإصدارات

وأخيرًا، يحسن حفظ عمل الدورة بنظام للتحكم في الإصدارات منذ البرنامج الأول. فـGit يسجّل كل حالة لمجلد العمل، ويتيح العودة إلى أي منها، ويبيّن ما الذي تغيّر بين حالتين؛ وهذا يعني لمن يبرمج أنه يستطيع التجريب دون خوف من فقدان ما كان يعمل، وأن يحدّد، بمقارنة النسخ، التغيير الذي أدخل خطأً، وهو ما ينقل إلى تاريخ البرنامج التنصيفَ الذي يعلّمه الدرس الخاص بتصحيح الأخطاء. ولا تعلّم الدورة Git، لأن دورة أخرى في الموقع تفعل ذلك: فدرس الكتابة الجماعية، من دورة LaTeX للكتابة الأكاديمية، يشرح سير العمل الأدنى، وأي الملفات تُحفظ وأيها تُستبعد، وكيف يُحلّ التعارض. وما يصحّ هناك في مصادر المستند يصحّ كذلك في مصادر البرنامج؛ ويكفي أن تُستبعد، بدل الملفات المساعدة في LaTeX، الملفات التنفيذية والملفات الكائنية التي تعيد الترجمة توليدها.