أي تابع بلغة الـ C++ يتألف من قسمين أساسيين : (1 ترويسة التابع : function header وهي توجد في بداية التابع وتتألف.

Download Report

Transcript أي تابع بلغة الـ C++ يتألف من قسمين أساسيين : (1 ترويسة التابع : function header وهي توجد في بداية التابع وتتألف.

‫أي تابع بلغة الـ ‪ C++‬يتألف من قسمين أساسيين ‪:‬‬
‫‪(1‬‬
‫ترويسة التابع ‪ : function header‬وهي توجد في بداية التابع وتتألف من ثالث أجزاء ‪:‬‬
‫‪ Return Type of The Function‬وهذا الجزء يحدد النمط الذي يرده التابع ‪.‬‬
‫‪ Name of The Function‬وهذا الجزء يحدد اسم التابع ‪.‬‬
‫‪ Types and Names of Parameters‬وهذا الجزء يحدد أسماء وأنماط متحوالت دخل التابع‪.‬‬
‫‪(2‬‬
‫جسم التابع ‪ : Body‬وهذا الجزء هو الذي سيعبر عن وظيفة التابع بحيث يعالج الدخل ويقوم بإعطاء خرج‬
‫يتوافق مع مهمة التابع المكتوب ‪.‬‬
‫يوجد طريقتين لكتابة تابع بلغة ‪ c++‬هما ‪:‬‬
‫‪(1‬‬
‫الطريقة األولى ‪ :‬باستخدام الـ ‪. function prototype‬‬
‫نحتاج إلى )‪function prototype(function declaration‬‬
‫نحتاج طبعاً إلى ‪. function definition‬‬
‫‪ (2‬الطريقة الثانية ‪ :‬باستخدام كتابة التابع بشكل كامل قبل أماكن استدعاءه‪.‬‬
‫نحتاج طبعاً إلى ‪. function definition‬‬
‫يوجد طريقتين لكتابة تابع بلغة ‪ c++‬هما ‪:‬‬
‫‪(1‬‬
‫الطريقة األولى ‪ :‬باستخدام الـ ‪. function prototype‬‬
‫يسمى الشكل السابق بـ ‪ prototype‬أو ‪ declaration‬للتابع ‪ ،‬وينتهي بفاصلة منقوطة‪.‬‬
‫يتم وضعه في الـ ‪ global section‬قبل أماكن االستدعاء ولمرة واحدة ‪.‬‬
‫ومن بعدها يتم وضع الـتابع بشكل كامل ‪ function definition‬في أي مكان يلي الـ‬
‫‪. prototype‬‬
prototype
Header + body
‫وهذه الطريقة صحيحة أيضاً إذ أننا‬
‫نقوم باخبار المترجم في سطر الـ‬
‫‪ prototype‬أنه لدينا تابع اسمه ‪add‬‬
‫‪prototyp‬‬
‫‪e‬‬
‫يأخذ متحولين كالهما من النمط ‪int‬‬
‫(ال يهمني اسمهم هنا طالما ال يتم‬
‫استخدامهما أي ال يوجد جسم للتابع)‪.‬‬
‫نهتم باسماء المتحول عند كتابة الـ‬
‫‪.function definition‬‬
‫‪Header +‬‬
‫‪body‬‬
‫هنا سيرى المترجم استدعاء‬
‫تابع غير معرف عنده ‪.‬‬
‫‪Header + body‬‬
‫إذاً في هذه الطريقة يتم في البداية‬
‫تعريف الـ ‪ prototype‬للتابع ونضعه‬
‫في األعلى فوق الـ ‪ main‬حتى يتم‬
‫‪prototyp‬‬
‫‪e‬‬
‫رؤيته من جميع التوابع األخرى ‪.‬‬
‫ثم يتم تعريف كامل التابع ‪function‬‬
‫‪( definition‬الترويسة ‪ +‬جسم‬
‫التابع) في أي‬
‫‪. prototype‬‬
‫مكان يلي الـ‬
‫‪Header +‬‬
‫‪body‬‬
‫يوجد طريقتين لكتابة تابع بلغة ‪ c++‬هما ‪:‬‬
‫‪(1‬‬
‫الطريقة الثانية‪ :‬باستخدام الطريقة المألوفة ‪.‬‬
‫يتم وضع الـتابع بشكل كامل ‪ function definition‬في أي مكان‬
‫ضمن الـ ‪ global section‬وقبل مكان االستدعاء ‪ ،‬كي يتم رؤيته ‪.‬‬
‫يتم وضع الـتابع بشكل كامل‬
‫في أي مكان ضمن الـ‬
‫‪ global section‬وقبل‬
‫مكان االستدعاء ‪ ،‬كي يتم‬
‫رؤيته ‪.‬‬
‫‪Header + body‬‬
‫الـ ‪ function signature‬هو جزء من الـ ‪ function prototype‬الذي‬
‫يتألف من اسم التابع وأنماط الـ ‪ parameters list‬من دون نمط اإلرجاع ‪.‬‬
‫يتم الفصل بين المتحوالت بفاصلة ‪.‬‬
‫المتحوالت هي‬
‫‪ local variables‬أي تموت هذه المتحوالت بعد الخروج‬
‫من التابع ‪.‬‬
‫ال يمكن تعريف متحول داخل التابع بنفس اسم متحول دخل للتابع ‪.‬‬
‫لكتابة تابع بدون متحوالت إما نترك الـ ‪ parameter list‬فارغة أو نكتب‬
‫الكلمة ‪ void‬لتدل على ال شيء‪.‬‬
‫يتم وضع اسم للتابع بحيث يعبر عن وظيفته ‪.‬‬
‫يجب أن يكون اسم التابع غير محجوز مسبقاً ‪.‬‬
‫ال يمكن تعريف تابع ضمن تابع آخر !‬
‫يمكن استدعاء تابع ضمن تابع آخر ‪.‬‬
‫عندما يتم تمرير قيمة متحول لتابع فإنه‬
‫يتم في البداية أخذ نسخة من هذا‬
‫‪10‬‬
‫‪5‬‬
‫المتحول وتعطى كدخل للتابع وبالتالي‬
‫يتم المحافظة على القيمة السابقة كي ال‬
‫يتم تغييرها من داخل التابع‪.‬‬
‫هنا تم نسخ المتحول ‪ x‬في التابع ‪f1‬‬
‫وإعطاء النسخة كدخل للتابع ‪ f2‬فأي‬
‫تعديل على ‪ x‬داخل ‪ f2‬لن يعدل على ‪x‬‬
‫يوجد مكتبة تحوي مجموعة من التوابع الرياضية وتدعى ‪. cmath‬‬
‫نقوم بتضمين المكتبة السابقة في برنامجنا لنتمكن من استدعاء التوابع الموجودة بداخلها ‪.‬‬
‫>‪#include <cmath‬‬
‫أغلب التوابع الموجودة في المكتبة السابقة يكون دخلها من النمط‬
‫‪ double‬والخرج أيضاً ‪. double‬‬
‫يوجد تابع يدعى ) (‪ rand‬يقوم بتوليد أعداد عشوائية ضمن المجال ]‪32767‬‬
‫التابع السابق يوجد ضمن المكتبة >‪. <cstdlib‬‬
‫كل مرة يتم توليد رقم جديد ضمن المجال السابق وفق استراتيجية ما‬
‫بدءاً من قيمة ما تدعى البذرة ‪. seed‬‬
‫ستنتج نفس القيم المولدة عند إعادة تنفيذ البرنامج من جديد !‬
‫‪. [0‬‬
‫يوجد تابع يدعى ) ‪ srand(unsigned int‬والذي يقوم بتعيين القيمة األولية لألعداد المولدة عشوائية أي تحديد‬
‫قيمة البذرة ‪. seed‬‬
‫التابع السابق أيضاً يوجد ضمن المكتبة >‪. <cstdlib‬‬
‫في حال كانت القيمة المدخلة ثابتة فإنه سيتم توليد كل مرة‬
‫تنفيذ نفس سلسلة األرقام المولدة ‪.‬‬
‫التابع السابق يتم استدعاءه لمرة واحدة فقط ‪.‬‬
‫إذاً ماذا نفعل إذا كنا نريد في كل مرة تنفيذ توليد قيم مختلفة‬
‫؟‬
‫في كل مرة نقوم بإدخال قيمة مختلفة كدخل للتابع‬
‫) ‪. srand( unsigned int‬‬
‫مثالً ندخل الوقت الحالي بالثواني !!! يوجد تابع يقوم بذلك‬
‫يدعى )‪ time(0‬وهو ضمن المكتبة >‪. <ctime‬‬
‫في كل مرة نقوم فيها بتنفيذ البرنامج ستنتج لدينا قيم‬
‫عشوائية مختلفة بسبب اختالف قيمة البذرة ‪.‬‬
‫ذكرنا أن التابع ) (‪ rand‬يقوم بتوليد قيمة عشوائية ضمن المجال ]‪32767‬‬
‫ولكن ‪ ........‬ماذا سنفعل إذا كنا نريد توليد قيمة ضمن المجال ]‪end‬‬
‫قيمة ضمن المجال ]‪11‬‬
‫‪. [2‬‬
‫‪. [0‬‬
‫‪ [start‬مثال توليد‬
‫ذكرنا أن التابع ) (‪ rand‬يقوم بتوليد قيمة عشوائية ضمن المجال ]‪32767‬‬
‫‪. [0‬‬
‫ولكن ‪ ........‬ماذا سنفعل إذا كنا نريد توليد قيمة ضمن المجال ]‪end‬‬
‫‪ [start‬مثال توليد قيمة‬
‫ضمن المجال ]‪11‬‬
‫‪. [2‬‬
‫سنقوم بالبداية بإجراء عملية باقي القسمة ‪ %‬ألن ‪ x % y‬سيعطينا قيمة ضمن المجال ]‪y-1‬‬
‫ثم نقوم بعملية إزاحة بقيمة ما ليتم إزاحة كامل المجال ‪!! .‬‬
‫‪[0‬‬
‫مثال توليد قيمتين ضمن المجال ]‪11‬‬
‫مختلفة عن القيم السابقة ‪.‬‬
‫‪ [2‬وبحيث كل مرة يتم فيها تنفيذ البرنامج يتم توليد قيم‬
‫أحياناً نقوم بكتابة عدة ملفات تحوي عدد كبير من التوابع ‪ .....‬لماذا ال نقوم بفرز هذه التوابع بشكل منطقي وفقاً‬
‫لوظيفتها ‪ ،‬مثالً التوابع الرياضية نقوم بوضعها لوحدها (في ملف منفصل)‪ ،‬والتوابع المسؤولة عن تصميم‬
‫الواجهات في مكان آخر ‪ ،‬وهكذا ‪....‬‬
‫(هذه األجزاء هي عبارة عن ملفات منفصلة تدعى مكاتب)‬
‫هذا األمر يساعدنا أيضاً في إعادة استخدام هذه األجزاء المنفصلة في أكثر من مشروع ‪.‬‬
‫سابقاً كنا نقوم باستخدام مكاتب جاهزة في اللغة ولتضمينها نكتب ‪:‬‬
‫ولكن ماذا لو كنا نريد كتابة مكتبة خاصة بنا !!!‬
‫سنقوم اآلن بكتابة مكتبة رياضية بسيطة خاصة بنا تحوي تابع وحيد اآلن يقوم بجمع عددين ‪....‬‬
‫نقوم بإنشاء ملف ‪ header‬نسميه باسم المكتبة الذي نريد مثالً ‪ my_math‬ونضعه ضمن مجلد الـ‬
‫‪ header‬في الـ ‪ project‬الحالي ‪.‬‬
‫تكون الحقة المكتبة ‪ .h‬ألنه سيكون ملف ‪. header‬‬
‫نقوم بكتابة ‪ header‬التوابع التي نريد فقط الترويسة أي ‪ prototype‬من دون كتابة جسم التابع في‬
‫ملف الـ ‪ ، header‬كما يمكننا أيضاً تعريف متحوالت إذا أردنا ‪.‬‬
‫نقوم بكتابة أجسام التوابع كاملة في ملف جديد باالسم ‪ my_math.cpp‬سيتضمن كود تحقيق تلك‬
‫التوابع الموجودة في الـ ‪ ، header file‬إذاً سيتم وضع ملف جديد باالسم السابق ضمن الـ ‪. source‬‬
‫اآلن بقي لنا تضمين مكتبتنا الجديدة لنقوم باستخدامها ‪.‬‬
‫اآلن نقوم بتضمين مكتبتنا في الملف األساسي حتى نتمكن من استخدام توابعنا الجديدة ‪.‬‬
‫‪Compiler Error‬‬
‫عملية التضمن >… < ‪ #include‬تستخدم‬
‫للمكاتب التي أتت مع اللغة وتكون موجودة‬
‫في مكان خاص في القرص الصلب‪.‬‬
‫ويكون التضمين لمكاتبنا الجديدة باستخدام‬
‫”‪#include “filename.h‬‬
‫اآلن نقوم بتضمين مكتبتنا في الملف األساسي حتى نتمكن من استخدام‬
‫توابعنا الجديدة ‪.‬‬
‫‪8.2‬‬
‫إذاً أصبح لدينا ثالث ملفات اآلن ‪:‬‬
‫األو ًل ‪:‬‬
‫إذاً أصبح لدينا ثالث ملفات اآلن ‪:‬‬
‫الثاني‪:‬‬
‫إذاً أصبح لدينا ثالث ملفات اآلن ‪:‬‬
‫الثالث‪:‬‬
‫النطاق المحلي ‪ local scope‬هو أي نطاق يبدأ بـ { وينتهي ب } ‪.‬‬
‫}‪. {………………………………………..‬‬
‫جسم التابع يوجد ضمن نطاق ‪ ،‬والـ ‪ switch body‬أيضاً هو نطاق ‪،‬‬
‫‪.....‬‬
‫يمكن تعريف نطاق بداخل نطاق ‪.‬‬
‫جميع المتحوالت التي يتم تعريفها ضمن نطاق ما تكون فترة حياتها‬
‫ضمن هذا النطاق أي أنها تموت بعد الخروج من هذا النطاق ‪.‬‬
‫المجال الذي ال يقع ضمن أي ‪ block‬هو نطاق عام ‪. global block‬‬
‫فترة حياة المتحوالت ضمن الـ )‪ global scope (file scope‬هي‬
‫بانتهاء تنفيذ البرنامج‪.‬‬
‫تمكننا الـ ‪ global variable‬من سهولة الوصول إليها أينما كنا ‪.‬‬
‫ولكن ينبغي تجنبها ‪ .....‬إذ أنه في حال جعلنا جميع المتحوالت لدينا‬
‫هي ‪ global‬سيصبح هنا عدد هائل من المتحوالت وعدم التمييز بينها‬
‫الحقاً ‪ ،‬مما يصعّب من صيانة البرنامج في حال أردنا تعديله ‪.‬‬
Global variables
Local variable in main
Local variable in scope
inside main
‫يمكن تعريف متحول ما على أنه ‪. static‬‬
‫يمكن تعريف متحول ساكن محلي ‪ static local‬ضمن تابع مثالً ‪ ،‬عندها‬
‫فإن هذا المتحول يتم تهيئته لمرة واحدة فقط (بحيث يصبح ساكن ضمن‬
‫التابع) وتكون فترة حياته بانتهاء البرنامج ولكن ال تتم رؤيته إال من داخل‬
‫التابع ‪.‬‬
‫لدينا متحول عام ‪global variable‬‬
‫ولكننا حتى اآلن لم نصل إليه !!!!‬
‫كيف سنطبع قيمة الـ ‪ x‬العامة ؟!!‬
‫عن طريق المعامل ‪ ::‬والذي يتم وضعه‬
‫قبل اسم المتحول والذي يقصد به الخروج‬
‫إلى الـ ‪ global scope‬ثم انتقاء المتحول‬
‫‪.‬‬
‫انتقل للمثال التالي ‪....‬‬
‫التوابع العودية هي توابع يتم تنفيذها مرة واحدة أو أكثر ويتم الخروج‬
‫منها عند عدم تحقق شرط ما يدعى شرط التوقف ‪.‬‬
‫التابع العودي هو تابع يقوم باستدعاء نفسه كل مرة إلى أن يصل إلى‬
‫شرط التوقف فيتوقف عن االستدعاء ويقوم بتحصيل النتائج المتراكمة‬
‫عن االستدعاءات السابقة ‪.‬‬
‫هذا مثال يقوم بإيجاد عاملي لعدد ما ولكن بشكل تكراري وليس عودي ‪.‬‬
‫هذا مثال يقوم بإيجاد عاملي لعدد ما ولكن بشكل تكراري وليس عودي ‪.‬‬
‫يمكننا كتابة المهمة السابقة عن طريق تابع عودي باالستناد إلى العالقة‬
‫التالية ‪:‬‬
‫نقوم بالتوقف عن العودية عندما يصبح العدد المدخل للتابع هو ‪. 0‬‬
‫إذاً لدينا قاعدتين ‪:‬‬
‫الحالة الخاصة (شرط التوقف)‬
‫الحالة العامة (الحالة التي يحصل فيها استدعاء عودي للتابع نفسه)‬
‫هذا مثال يقوم بإيجاد عاملي لعدد ما ولكن بشكل عودي ‪.‬‬
‫كل عملية استدعاء لتابع تكو ًن له متحوالته الخاصة واملستقلة عن االستدعاء‬
‫السابق ‪.‬‬
‫يجب تنفيذ جميع التعليمات املوجودة في االستدعاء العودي الحالي ‪.‬‬
‫انتقل للمثال التالي والذي يشرح كامل الفكرة !!‬
‫التابع األول يقوم بعملية جمع األعداد من ‪ 1‬إلى ‪ n‬حيث ‪ n‬قيمة مدخلة للتابع بطريقة‬
‫تكرارية (حلقة)‬
‫التابع الثاني يقوم بعملية جمع األعداد من ‪ 1‬إلى ‪ n‬حيث ‪ n‬قيمة مدخلة للتابع بطريقة‬
‫عودية‬
‫التابع الثالث يقوم بعملية جمع األعداد من ‪ 1‬إلى ‪ n‬حيث ‪ n‬قيمة مدخلة للتابع بطريقة‬
‫(ليست عودية وليست تكرارية) أي تعليمات فقط من دون أن يكون هناك أي تكرار أو‬
‫عودية‬