المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : [Cpp] مشروع قاعدة بيانات الطلاب : تطبيق لمفاهيم الـOOP:


the.matrix.sdn
18-05-2009, 09:37 PM
http://the.matrix.sdn.googlepages.com/besm63dp5.gif

هذا المشروع عبارة عن برنامج قاعدة بيانات لتسجيل بيانات الطلاب على شكل سجلات كل سجل يحوي بيانات الطالب مثل الاسم و الرقم و الدرجات و التقدير الخ ، و قد قمت بكتابته بلغة سي بلس بلس لسببين :
الأول : التمرين و التدريب الذاتي على كتابة المشاريع بهذه اللغة القوية و المتينة لتحقيق مفاهيم البرمجة كائنية التوجه OOP لحل المشكلات البرمجية راجع هذا الموضوع (http://www.absba.org/showthread.php?t=761593)بخصوص الـOOP .
الثاني : أن هذه اللغة و برغم انتشارها الواسع عالميا فإن استخدامها بين المبرمجين العرب بصورة احترافية قليل – نوعا ما – و ذلك لأسباب ليس هذا مجال بيانها ، لهذا أحببت المساهمة في عملية نشر استخدام هذه اللغة و محاولة تبسيطها و تقريبها للمبرمج العربي خاصة المبتدئين من أمثالي :D :D .

الدخول إلى التفاصيل :
لتنفيذ هذا المشروع نحتاج إلى 5 كلاسات (طبقات) كالتالي – مع ملاحظة أن استخراج الطبقات مسألة نسبية تختلف من مبرمج إلى آخر - :
· كلاس Student : و فيه عناصر بيانات كل طالب كالرقم و الاسم و الدرجات ...
· كلاس dBase : تخزين بيانات الطلاب في قاعدة بيانات مبينة على السلاسل المتصلة Linked List و القيام بعمليات الحذف و الاضافة و التعديل الخ.
· كلاس RW2File : مهمته تسجيل البيانات على القرص الصلب و قراءتها منه.
· كلاس UserInterFace : و هو واجهة المستخدم الذي يقوم بإدارة كل العمليات التي يقوم بها البرنامج.
· كلاس StudentCount : و هو كلاس بسيط مهمته تنحصر في عدّ الطلاب بحيث يكون لدينا عدد الطلاب جميعا و عدد الناجحين فقط و عدد الراسبين فقط و ذلك باستخدام الدوال الساكنة static function بدون إنشاء كائنات منه كما سيأتي التفصيل لاحقا...

نأتي الآن إلى تصميم مبسط بواسطة لغة UML (لغة النمذجة الموحدة ) مستخدمين في ذلك تخطيط الطبقة Class Diagram :

http://tw.absba.org/teamwork11/787212/1.PNG


شرح مختصر للمخطط أعلاه :
· مساحة الأسماء الجديدة التي سنستخدمها في المشروع بالاسم : studentDB وضعناها بالأعلى.
· الكلاس UserInterFace يستخدم نسخة واحدة من الكلاس RW2File .
· الكلاس RW2File يرث الكلاس dBase

· الكلاس dBase يتضمن نسخ من الكلاس Student عددها مابين 0 – إلى n .
· الكلاس Student يرث الكلاس StudentCount .

الطبقة الأولى Student :
بدأنا بها لأنها أهم طبقة ، و كما ترى فهي ترث من الطبقة StudentCount و لكن دعنا لا نستعجل الآن في ذكر هذا و لنقم بإنشاء الطبقة و كبسلتها بصورة محترفة ! و نترك الكلام عن StudentCount لاحقا :
هذه الطبقة (الكلاس) مطلوب منها تخزين البيانات الخاصة بالطالب : الاسم و الرقم و الدرجات لعدد 6 مواد و درجة نصف السنة و درجة آخر السنة و المتوسط و المعدل (التقدير) كل ذلك في عناصر بيانات (متغيرات) بالاضافة إلى دوال تقوم بإدخال هذه البيانات في المتغيرات الأعضاء (Setter) و دوال تقوم بقراءة هذه القيم (Getter) ... دعنا لا نطيل الكلام و حيّ على العمل :
افتح مشروع جديد على الـ Dev-C++ - حيث سيكون هو المترجم (و بالأصح IDE) الذي سنعمل عليه المشروع ( راجع هذا الموضوع لتحميل المترجم المميز Dev-C++ و معرفة أساسيات استخدامه : هنـــــــــا (http://www.absba.org/showthread.php?t=784075)) و ليكن مشروعنا على الكونسول – و يمكن تطويره لاحقا ليعمل على واجهة رسومية GUI - و اكتب اسم المشروع و ليكن Student_Database_System أو أي اسم مناسب ثم اختر النوع Console Application ثم ok كما في الصورة بالأسفل ثم حدد مكان حفظ المشروع و من الأفضل عمل مجلد جديد لحفظ ملفات المشروع به :
http://tw.absba.org/teamwork11/787212/2.PNG


سيقوم البرنامج بفتح ملف الـmain تلقائيا و لن نحتاجه الآن و سنعدّله لاحقا المهم ، قم بفتح ملف جديد تابع للمشروع (Ctrl+N) ثم اضغط yes لتأكيد إضافته للمشروع و احفظه بالاسم StudentClass.h ثم اكتب الكود التالي و احفظه : (ملاحظة كل كلاس سيكون له ملفان منفصلان :
ملف رأس و ملف تنفيذي.. )

http://tw.absba.org/teamwork11/787212/3.png
حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/1.h)

تحليل :
السطر 5:
أعلنا عن مساحة أسماء جديدة بالاسم studentDB بحيث تتضمن تعريف الكلاس بالاضافة للمتغير الثابت QuizeSize و الذي يساوي القيمة 6 في سطر 7 ، هذا الثابت سنستخدمه لتحديد حجم المصفوفة في السطر 33 لدرجات 6 مواد و سنستخدمه أيضا في أماكن أخرى من المشروع .
السطران 11 و 13 :
دالة البناء و دالة الهدم للكلاس.
الأسطر 15 – 21 :
هذه دوال الـ Setter و واضح من اسمها أن وظيفتها هي تعيين قيم المتغيرات الأعضاء في القسم الخاص private و بما أنها في القسم الخاص فهذا يعني أنه لا يمكن الوصول إليها من خارج الكلاس لذلك نستعمل دوال الـSetter لتعيين قيم هذه المتغيرات بحيث اننا نمرر القيمة التي نريد وضعها للدالة و تقوم هي بإسنادها للمتغير – بمعرفتها J - كما سنرى عند عمل الملف التنفيذي implementation file للكلاس.
الأسطر 23 – 29 :
دوال الـGetter و وظيفتها بكل بساطة هي ارجاع القيم المحفوظة بالمتغيرات الخاصة ، فمثلا لو أردنا الاسم نستعمل الدالة GetName() التي ترجع الاسم المحفوظ بالمتغير الخاص Name ، و هكذا... و أعلنا عن هذه الدوال أنها ثابته const حتى لا يسمح لها المترجم بأن تقوم بتغيير قيمة المتغير و إنما فقط تُرجع قيمته و ذلك تجنبا لحدوث أي خطأ غير مقصود ..
كلا النوعين – دوال الـSetter و الـGetter في القسم العام public من الكلاس ، يسمى هذا النوع من الدوال بالواجهة الخارجية للكلاس بحيث يتم الوصول للأعضاء في القسم الخاص عن طريق هذه الواجهة فقط و لايمكن الوصول مباشرة لأعضاء القسم الخاص و ذلك لحماية الكائن من أن يتم تعديل حالته الداخلية – أي المتغيرات الخاصة – من خارجه .
الأسطر 31 – 35 :
هذه هي متغيراتنا الأعضاء في القسم الخاص و هي التي ستحفط لي بيانات الطالب : الرقم stID و الاسم Name و مصفوفة حجمها 6 خانات لحفظ درجات 6 مواد Quize[QuizeSize] و درجة نصف السنة Mid و درجة نهاية السنة Final و متوسط كل الدرجات Average و أخيرا تقدير الطالب Grade ، لاحظ أننا استعملنا أسماء واضحة تدل على الغرض من استخدام المتغير – أو الدالة – و هذا له أهمية كبرى في تسهيل فهم البرنامج و تعديله أو صيانته لاحقا و خاصة في البرامج الكبيرة . طبعا هذه المتغيرات ليست ثابتة أي يتم تحديدها على حسب رؤية المبرمج الذي يقوم ببرمجة المشروع حسب رغبة العميل ...
بهذا نكون قد صممنا الكلاس Student بصورة جيدة يمكن قراءته أي الكود و فهمه و بالتالي تعديله بسهولة و في زمن وجيز J ، نأتي الآن إلى الملف التنفيذي للكلاس كما يلي:
(قم أيضا بعمل ملف جديد و اضافته للمشروع بالاسم StudentClass.cpp )

http://tw.absba.org/teamwork11/787212/4.png
حمل ملف الكود من هنا (http://the.matrix.sdn.googlepages.com/2.cpp)

تحليل :
السطر 2:
قمنا بتضمين ملف رأس الكلاس StudentClass.h و قد وضعناه بين علامتي تنصيص " " حتى يعرف المترجم أنه موجود في نفس المجلد الخاص بالمشروع .
السطر 4:
أعلمنا المترجم باستخدامنا لمساحة الأسماء التي سبق و أعلنا عنها في رأس الكلاس بالاسم studentDB .
الأسطر 6 – 13 :
تنفيذ (متن) دالة البناء و فيها نقوم بتصفير (تهيئة) المتغيرات الخاصة و يتم ذلك في كل كائن يتم انشاؤه من هذا الكلاس تمهيدا للإستخدام.
السطر 15 :
دالة الهدم .
السطر17 :
أولى دوال الـSetter هذه الدالة نمرر لها وسيط من النوع long – عدد صحيح طويل – عبارة عن رقم الطالب يتم اسناد قيمته للمتغير الخاص stID بعبارة أخرى تقوم الدالة يتخزين القيمة الممررة في المتغير الخاص stID .
السطر 19 :
هذه الدالة مثل الدالة السابقة و لكن نمرر لها وسيط من النوع string هو اسم الطالب .
السطران 21 – 22 :
مثل الدالتان بالأعلى إلا أننا استخدمنا تكرار for لنسخ القيم من المصفوفة quize[] التي قمنا بتمريرها للدالة إلى المصفوفة العضو بالكلاس Quize[] و استفدنا هنا من الثابت QuizeSize الذي سبق الإعلان عنه في رأس الكلاس – بالأعلى - سطر 7 و هو يحدد عدد المواد بـ6 مواد
السطر 24 و 26 :
هذان السطران هما دالتان Setter كما الدوال السابقة و وظيفتهما : الأولى تعيين قيمة المتغير الخاص Mid و الثانية تعيين قيمة Final عن طريق القيمة التي يتم تمريرها لكل منهما من النوع int .
الأسطر 28 – 34 :
الدالة SetAverage() و وظيفتها تعيين قيمة المتوسط لكل الدرجات و هي كما ترى لاتحمل أي وسيط و بالتالي لن نمرر لها قيمة المتوسط بل تقوم هي بحسابه ثم تخزين قيمته في المتغير العضو Average من النوع float أي عدد ذو فاصلة عشرية ، طبعا المتوسط يعني مجموع الأعداد على عددها أي مجموع درجات المواد (6 مواد + نصف السنة + نهاية السنة ) على عددها أي 8 .
الأسطر 36 – 44 :
الدالة SetGrade() و هي كالدالة السابقة تقوم بتعيين تقدير الطالب حسب متوسطه باستخدام if – else كما هو واضح و لا نمرر لها أي قيمة .
كل دوال الـSetter أعلاه تعيد قيمة من النوع void أي لا شيء و ذلك لطبيعة وظيفتها ...
الأسطر 46 – 58 :
دوال الـGetter و هي 7 دوال وظيفة كل واحدة ارجاع قيمة المتغير الخاص الذي تتبع له كما سترى عند اختبار الكلاس. قم الآن بترجمة هذا الملف فقط (Ctrl+F9) بحيث أننا كلما نقوم بعمل ملف تنفيذي نقوم بترجمته و في النهاية سنحتاج فقط لترجمة الملف main ثم تنفيذ البرنامج .

اختبار الكلاس Student :
من الأفكار الجيدة في البرمجة هي تقسيم المشروع إلى أجزاء أو مراحل و عند نهاية كل جزء القيام بعمل اختبار لهذا الجزء للتأكد من عمله بكفاءة و في الحقيقة فللإختبار أنواع كثيرة لن نخوض في تفاصيلها و يكفينا الآن عمل برنامج مبسط نستعمل فيه الكلاس Student لإدخال بيانات طالب ثم عرضها فقط لنطمئن أن كل شيء على ما يرام حتى هذه اللحظة JJ :
قم بكتابة الكود التالي في ملف main – و الذي سيختلف شكله من مرحلة إلى أخرى وصولا إلى نهاية البرنامج - :
http://tw.absba.org/teamwork11/787212/5.JPG


حمل ملف الكود من هنا (http://the.matrix.sdn.googlepages.com/3.cpp)

التحليل :
السطر 3:
ضمنّا المكتبة stdlib.h و هذه هي الطريقة القياسية المتفق عليها – مؤخرا ! – لتضمين المكتبات التقليدية – و المستخدمة أساسا في لغة سي C و قامت لغة سي بلس بلس بوراثتها - بحيث تكتب على الشكل <cstdlib> يتم اضافة الحرف c و حذف الامتداد .h ، ملاحظة يقوم المترجم Dev-C++ بتضمينها تلقائيا حيث أنها تعرِّف الدالة system("PAUSE") المستخدمة لتثبيت الشاشة.
الأسطر 4 و 5 :
تضمين المكتبة iostream لعمليات الادخال و الاخراج و تضمين ملف رأس الكلاس StudentClass.h .
الأسطر 7 و 8 :
و فيهما أخبرنا المترجم باستخدامنا لمساحة الأسماء القياسية std بالإضافة لمساحة الأسماء الخاصة بنا studentDB .
السطر 12 :
أعلنا عن الكائن st من الكلاس Student .
الأسطر 15 – 22 :
نقوم فيها باستدعاء دوال الـSetter الخاصة بالكائن – باستعمال معامل النقطة . – أي اسم الكلاس نقطة ثم اسم الدالة مثلا st.SetID(111); و مررنا لهذه الدالة قيمة عبارة عن رقم صحيح هي رقم الطالب سيقوم المترجم باستدعاء الدالة و تنفيذها و بالتالي تخزين الرقم 111 في المتغير الخاص stID و لو حاولت الوصول مباشرة لهذا المتغير مثلا : st.stID = 111; فسيعطيك المترجم رسالة خطأ بأنه لايمكن الوصول إلى المتغير الخاص stID . و هكذا في بقية دوال الـSetter نقوم باستعمالها لإدخال بيانات الطالب إلى المتغيرات الأعضاء ما عدا الدالتان st.SetAverage() و st.SetGrade() حيث لا نمرر لهما أي قيمة و إنما تقومان بحساب المتوسط و التقدير من القيم التي سبق إدخالها ثم تخزنهما في المتغيران Average و Grade كما سبق الكلام عنهما .
الأسطر 25 – 32 :
فيها نقوم بعرض البيانات التي سبق إدخالها و نقوم بذلك باستخدام دوال الـGetter ...
السطر 34:
ايقاف الشاشة مؤقتا للإطلاع على النتائج .
الآن قم بترجمة و تنفيذ البرنامج لتحصل على الآتي :
http://tw.absba.org/teamwork11/787212/6.JPG


واو!! كما ترى تمت عملية الاختبار المبسطة بنجاح ! و كلاسنا يعمل بكفاءة و الحمد لله فقد قام بعرض القيم التي قمنا بتمريرها له كما قام بحساب المتوسط Average و التقدير Grade و عرضهما على الشاشة ...

الطبقة الثانية : dBase
هذه الطبقة تقوم بانشاء قاعدة البيانات و تقوم بادارتها مثل الاضافة و الحذف و التعديل ... الخ .
قاعدة البيانات هذه تقوم على القوائم المتصلة Linked List و هي كما نعلم : هيكلة البيانات في شكل سلسلة متصلة من السجلات (العقد) كل سجل (عقدة) يحتوي على الأقل على حقلين الأول لتخزين البيانات الهدف و الثاني عبارة عن مؤشر يُشير لموقع العقدة التالية.
هنا سيكون الحقل الأول كائن st من الكلاس Student أما الحقل الثاني فهو مؤشر للعقدة التالية كما سبق.
في الحقيقة كان يمكننا استخدام المصفوفات array و لكن القوائم المتصلة تتميز عنها بعدة مميزات لعل من أهمها شيئان الأول: استعمال أفضل للذاكرة و الثاني : إدخال عدد غير محدد من الطلاب ، و ليس هذا موضع تفصيل ذلك ! .
الآن لتقم بعمل ملف جديد و اضافته للمشروع و هو ملف رأس الكلاس dBase بالاسم dBaseClass.h كما يلي :
http://tw.absba.org/teamwork11/787212/7.PNG


حمل ملف الكود من هنا (http://the.matrix.sdn.googlepages.com/4.h)
تحليل :
السطر 5 :
تضمين لملف رأس الكلاس Student حيث أننا سنحتاج لاستخدام هذا الكلاس في كلاسنا الجديد هذا لذلك لابد من تضمين ملف الرأس الخاص به.
الأسطر 11 – 14:
هنا و في القسم العام أعلنا عن سجل structure باستخدام الكلمة المحجوزة struct اسمه – أي السجل : student – انتبه فهذا مختلف عن اسم الكلاس Student - ، هذا السجل يحتوي على حقلين – كما سبق – أولهما هو عبارة عن كائن st من الكلاس Student و الثاني هو مؤشر اسمه next من نفس نوع السجل حيث سنستخدمه لاحقا للإشارة إلى عنوان السجل (العقدة) التاليـ(ة)
الأسطر 16 و 19 :
دالتي البناء و الهدم .
السطر 22 :
دالة تعيد قيمة من النوع int و اسمها AddStudent نمرر لها أربع متغيرات أولها من النوع string و البقية أعداد صحيحة int احداها مصفوفة [] . هذه الدالة كما هو واضح من اسمها مهمتها إضافة طالب جديد إلى قاعدة البيانات كما سترى عند الكلام عن متنها ( ملفها التنفيذي ) .
السطر 23:
دالة أخرى من نفس النوع اسمها EditStudent و نمرر لها نفس متغيرات الدالة السابقة مع اضافة متغير آخر من النوع long ، عمل الدالة هو تعديل (تحرير) بيانات طالب موجود مسبقا بقاعدة البيانات .
السطر 24 :
دالة ثالثة اسمها DeleteStudent أي حذف طالب موجود بقاعدة البيانات ، هذه الدالة تاخذ وسيطا واحدا من النوع long .
السطر 25:
دالة رابعة اسمها ChecID سنستخدمها عند الحذف أو التعديل للتأكد من صحة رقم الطالب المدخل بواسطة المستخدم قبل القيام بحذف أو تعديل كما سترى يعد قليل.
هذه الدوال الأربع يمكن اعتبارها دوال عمليات قاعدة البيانات Database Operation كما عنونّاها باستخدام الملاحظة بالسطر 21 و الغرض هو تسهيل و تبسيط الفهم لقاريء الكود ، و الدول التالية هي لعرض البيانات لذلك وضعنا ملاحظة : Get information في السطر 27 .
السطر 28 :
الدالة DisplayAll لعرض بيانات جميع الطلاب.
السطر 29:
الدالة DisplayPass لعرض بيانات جميع الطلاب الناجحين فقط .
السطر 30 :
الدالة DisplayFail لعرض بيانات جميع الطلاب الراسبين .
الأسطر 31 و 32 :
دالتان للبحث عن الطالب اولاهما للبحث عن طريق رقم الطالب لذلك نمرر لها وسيطا من النوع long و الأخرى و بنفس الاسم للبحث عن طريق اسم الطالب لذلك نمرر لها وسيطا من النوع string ، لاحظ استخدامنا لمفهوم زيادة التحميل Overloading لهاتين الدالتين ...

كل الدوال أعلاه في القسم العام من الكلاس و نأتي الآن إلى القسم الخاص :
السطر 34:
متغير fID من النوع long عن طريقه نحدد أول رقم للطالب حيث أن البرنامج يجب أن يقوم بتوليد رقم لكل طالب بصورة آلية (وهذا أسهل للمستخدم ) ، لذلك و كما سترى لاحقا سنستخدم هذا المتغير لتحديد رقم البداية ثم نقوم بزيادته بمقدار 1 عند اضافه طالب و العكس – أي انقاصه بمقدار 1 – عند الحذف .
السطر 35 :
مؤشر اسمه Head من نفس نوع السجل student هذا المؤشر في الواقع هو أهم متغير في كلاسنا هذا حيث أنه يُشير إلى أول عقدة في السلسلة المتصلة التي تحوي بياناتنا و بالتالي إذا أردنا الوصول إلى أي سجل (عقدة) في هذه السلسلة فلا يمكن ذلك إلا عن طريق هذا المؤشر !! لذلك هو مهم جدا جدا ، و إليك هذا المخطط المبسط لشكل السلسلة المتصلة و موقع المؤشر Head منها :
http://tw.absba.org/teamwork11/787212/8.PNG



نأتي الآن أعزائي إلى الملف التنفيذي للكلاس dBase و الذي سنكتب فيه متون دواله كالتالي :

http://tw.absba.org/teamwork11/787212/9.png
حمل الكود من هنا (http://the.matrix.sdn.googlepages.com/5.cpp)

تحليل الكود :
السطر 4:
تضمين ملف الرأس dBaseClass.h .
السطر 8 :
دالة البناء الخاصة بالكلاس و التي سيتم استدعاءها عند إنشاء كائن من الكلاس ، و كما ترى تم تهيئة المتغيرات الخاصة : فالمؤشر Head سنعطيه القيمة NULL أي خالي و ذلك للدلالة على أن قاعدة البيانات (السلسلة المتصلة ) خالية و سيتم تغيير هذه القيمة عند اضافة الطلاب لاحقا ، المتغير الخاص الآخر fID تم إعطاءه القيمة 1000 (و هي اختيارية حسب مزاجك ;) ) و ذلك لاخبار الكائن أن الأرقام – أي أرقام الطلاب stID – سيبدأ عدها من هذا الرقم بحيث يتم زيادته بمقدار 1 عند إضافة طالب جديد و بالعكس : إنقاصه بمقدار 1 عند حذف طالب ...
السطر 10:
دالة الهدم التي سيتم استدعاءها عند تدمير الكائن أو عند خروجه من مداه ، هذه الدالة ستقوم بحذف المؤشر Head من الذاكرة – و بالتالي حذف كامل السلسلة - و في الحقيقة فهذه مسألة مهمة جدا جدا لتجنب الوقوع في فخ تسرب الذاكرة ، و في لغة سي بلس بلس فهذه مسئولية المبرمج بخلاف لغة جافا و ليس هذا موضع تفصيل ..
الأسطر 12 – 45 :
هذه أول دالة عضو بالكلاس و اسمها AddStudent() و كما هو واضح فهي تقوم بإضافة طالب جديد لقاعدة البيانات كالتالي :
14 : في هذا السطر أعلنا عن مؤشرين current و linker و هما من نفس نوع السجل student .. فائدة المؤشرين ستتضح بعد قليل حيث سنستخدمهما لإنشاء عقدة جديدة و ربطها بالعقدة التالية في كل مرة يتم استدعاء الدالة لإضافة سجل جديد و هما مؤشران مؤقتان في الواقع (على الرصة stack) بحيث سيقوم المترجم بتدميرهما آليا عند الوصول لقوس نهاية الدالة و بالتالي فلا حاجة لحذفهما باستخدام المعامل delete.
15 : زيادة المتغير الخاص fID بمقدار 1 ، لاحقا سنقوم بتمرير هذا المتغير – بعد زيادته – إلى الدالة SetID() و هي عضو بالكلاس Student و ذلك لوضع رقم الطالب .
16 : سنختبر هنا هل Head = NULL باستعمال عبارة الشرط if ، فإذا كان كذلك (أي قيمة الشرط صواب ) فهذا يعني أن هذه أول عقدة في السلسلة و عند ذلك ينفذ الكود الخاص بإنشائها و وضع البيانات بها في الأسطر 18 – 26 .
18 : نقوم بإنشاء العقدة الأولى عن طريق المعامل new (طبعا هذه العقدة تحتوي على حقلين الأول هو كائن st من الكلاس Student و الثاني هو مؤشر لموقع العقدة التالية ) ثم يخزن عنوان (موقع ) هذه العقدة – بالذاكرة – في المؤشر Head و قد ميزنا العقدة الأولى هنا لأنها الأهم ، و في الأسطر التالية – حتى سطر 26 يتم وضع بيانات الطالب عن طريق دوال الـSetter التي سبق الكلام عنها في الكلاس Student .
26 : في هذا السطر نعطي المؤشر next في هذه العقدة قيمة أولية NULL و هي أولية لأنه سيتم تغييرها عند إضافة عقدة أخرى و لكن الآن لابد من التأكد من جعلها خالية حتى لايكون بها عنوان قديم و غير مقصود بالذاكرة مما قد يسبب أخطاءً كبيرة عند التعامل مع السلسلة بالحذف أو الاضافة أو غير ذلك.

30 : هذا السطر و الأسطر اللاحقة له في هذه الدالة هي قسم else التابعة للشرط if السابق و سيتم تنفيذه إذا لم يكن المؤشر Head خالي (أي كانت قيمة الشرط بالأعلى خطأ ) أي أن السلسلة ليست خالية ( لاحظ هنا فائدة تهيئة المؤشر Head في دالة البناء ) و في هذا السطر يتم اسناد قيمة المؤشر Head إلى المؤشر المؤقت linker و الغرض من ذلك أننا لا نريد تغيير قيمة المؤشر Head لأنه مفتاح للوصول لكامل السلسلة كما سبق و إذا غيرنا قيمته فهذا يعني ضياع كامل السلسلة و عدم تمكننا من الوصول لها بعد ذلك ، لذلك نستعمل هذه الخدعة البسيطة :D : نحن بحاجة لعنوان أول عقدة بالسلسلة ، نقوم بتخزين هذا العنوان في مؤشر مؤقت هو linker بحيث نغير قيمته هو لاحقا و نحافظ بذلك على قيمة المؤشر الأهم Head .
31 – 32 : هنا نستعمل التكرار للوصول إلى عنوان آخر عقدة بالسلسلة – باستخدام المؤشر linker - و ذلك تمهيدا لإضافة عقدة جديدة و إلحاقها بذيل السلسلة المتصلة كما سترى بعد قليل.
33 : نقوم بإنشاء سجل (عقدة ) جديد(ة) و تخزين عنوانه في المؤشر current و في الأسطر اللاحقة نقوم بوضع بيانات الطالب الجديد باستخدام دوال الـSettre كما بالأعلى .
42 : هذا السطر هو الذي يقوم بعملية ربط العقدة الجديدة بالعقدة الأخيرة بالسلسلة و عنوانها موجود بالمؤشر linker ( حسب الأسطر 31 – 32 ) حيث سنضع بالمؤشر next في هذه العقدة عنوان عقدتنا الجديدة و التي عنوانها محفوظ في المؤشر current .
44 : هنا و بعد الانتهاء بنجاح ستعيد الدالة القيمة 0 للدلالة على نجاح العملية ( إضافة طالب جديد ) .

الأسطر 47 – 69 :
متن دالة أخرى هي EditStudent() و وظيفتها هي تحرير – تعديل – بيانات طالب سبق إدخاله و هي تسمح بتعديل كل البيانات ما عدا رقم الطالب .
49 : لابد أولا من اختبار قيمة المؤشر Head للتأكد من أنه ليس خاليا – أي أن السلسلة ليست فارغة – فإذا كان خاليا فإن الدالة لن تفعل شيئا ، و إذا لم يكن خاليا يقوم بتنفيذ بقية كود الدالة .
51 : نعلن هنا عن مؤشر مؤقت ptr من نفس نوع السجل student و نعطيه قيمة المؤشر Head حيث سنستعمل هذا المؤشر للتنقل خلال العقد ( السجلات) في السلسلة المتصلة .
53 – 57 : هذا التكرار وظيفته هي البحث عن الطالب المراد تعديله بدلالة رقم الطالب و الغرض من ذلك هو معرفة عنوان عقدة هذا الطالب بحيث نتمكن من تعديل البيانات بدلالة المؤشر ptr .
58 – 67 : عند إيجاد الطالب فإن المؤشر ptr لن يكون خاليا بل سيحتوي عنوان سجل الطالب المراد تعديل بياناته و بالتالي فسيقوم بالتعديل باستخدام القيم الجديدة التي تم تمريرها للدالة – و لن يتم تعديل رقم الطالب كما سبق- .

71 – 93 : هذه دالة الحذف DeleteStudent() و وظيفتها بكل بساطة هي حذف سجل الطالب و لكن لابد من معالجة ذلك بحيث لا يحصل انقطاع في السلسلة بسبب حذف عقدة بها كما سترى ، و سنمرر لهذه الدالة وسيطا واحدا هو رقم الطالب المراد حذفه .
73 : التأكد من عدم خلو المؤشر Head و قد سبق الكلام عن ذلك .
75 : نعلن هنا عن مؤشران جديدان أولهما parent و سنخزن به عنوان (والد) العقدة المراد حذفها (أي العقدة السابقة لها) و المؤشر الثاني ptr و سنعطيه قيمة المؤشر Head – عنوان أول عقدة – ثم سنستخدمه لاحقا للتنقل داخل السلسلة .
76 – 77 : في هذا الشرط سيختبر –باستخدام if - إن كانت العقدة المراد حذفها هي العقدة الأولى – و التي يشير إليها المؤشر Head فإذا كان كذلك ( أي صواب ) فسيقوم بكل بساطة بتغيير المؤشر Head بحيث يضع به عنوان العقدة التالية . و إلا فسينفذ مقطع else كما يلي:
78 – 89 : هذا الجزء من الكود سيتم تنفيذه في حالة لم تكن العقدة المراد حذفها هي العقدة الأولى – و التي دائما نميزها بالذكر كما لاحظت لأهميتها - .
80 – 86 : هذا التكرار وظيفته هي البحث عن العقدة السابقة للعقدة المراد حذفها و تخزين عنوانها في المؤشر parent بحيث نستفيد من ذلك بعد قليل في ربط العقدة السابقة بالعقدة التي تلي العقدة المراد حذفها (العقدة الهدف ) ! و ذلك حتى لا تنقطع السلسلة عند حذف عقدة منها .
87 : نعم هذا السطر هو الذي يقوم بعملية الربط المشار إليها بالأعلى ( حيث أن العقدة السابقة يتم ربطها بالعقدة اللاحقة تمهيدا لحذف العقدة الهدف في السطر 88 ) .
90 : يتم انقاص المتغير fID – رقم الطالب - بمقدار 1 و ذلك بعد نجاح عملية الحذف .
و هنا سؤال ذكي : افترض أن رقم الطالب – و الذي مررناه لدالة الحذف هذه – غير صحيح ، مما سيسبب مشكلة أو عدة مشاكل أقلها إنقاص رقم الطالب فما الحل ؟ الجواب : لن نستدعي دالة الحذف – أو دالة التعديل – إلا بعد التأكد من أن رقم الطالب صحيح و ذلك باستخدام دالة عضو مخصصة لذلك ChecID() :

95 – 114 : هنا متن الدالة ChecID() و وظيفتها هي التأكد من أن رقم الطالب الذي أدخله المستخدم هو رقم صحيح ( أي موجود بقاعدة البيانات ) .
97: أعلنا عن متغير صحيح اسمه ReturnCode و كما هو واضح من اسمه سيحمل القيمة التي سترجعها الدالة و أعطيناه قيمة أولية -1 ( و التي ستعني أن قاعدة البيانات خالية ) .
101 – 109 : هذا التكرار سيقوم بالبحث عن رقم الطالب فإذا وجده ستتغير قيمة المتغير ReturnCode إلى 1 ( سطر 105 ) .
110 – 111 : إذا لم يجده (ptr = NULL) ستتغير قيمة ReturnCode إلى 0 .
113 هنا تقوم الدالة بارجاع قيمة المتغير ReturnCode ، إذن و باختصار فهذه الدالة سترجع إحدى ثلاث قيم : -1: للدلالة على أن قاعدة البيانات خالية ، 1: للدلالة على أن رقم الطالب صحيح – أي موجود بقاعدة البيانات - ، 0: للدلالة على أن رقم الطالب غير صحيح – أي غير موجود - ، و سنستفيد بشكل كبير من هذه القيم لاحقا عند حذف أو تعديل سجل طالب كما سترى بحول الله عند اختبار الكلاس dBase .

116 – 141 : هذه دالة بالاسم DisplayAll() أي عرض جميع الطلاب و هي بكل بساطة تقوم بالمرور على كل عقدة في السلسلة بدلالة المؤشر ptr حيث تعرض بيانات كل عقدة (كل طالب ) و لا أعتقد أنها تحتاج إلى مزيد شرح!.

143 – 171 : الدالة DisplayPass() و هي كالسابقة إلا أنها تقوم بعرض الطلاب الناجحين فقط حيث نختبر تقدير كل طالب فإذا لم يكن "F" – أي راسبا يتم عرضه ( الاختبار في سطر 151 ) .

173 – 201 : و هذه الدالة DisplayFail() و هي كسابقتها إلا أنها تعرض بيانات الطلاب الفاشلين ! ، قصدي: الراسبين :DJ
.

203 – 264 : هنا دالتان أولاهما GetStudent() نمرر لها وسيطا واحدا StudentID من النوع long و وظيفتها هي البحث عن طالب بدلالة رقمه و عند إيجاد الطالب يتم عرض بياناته و إلا فستعرض الدالة رسالة تفيد أنها لم تجد طالبا بالرقم المذكور أما الدالة الأخرى فهي بنفس الاسم حيث تقوم بنفس الوظيفة : البحث عن طالب و لكن بدلالة اسمه هذه المرة و كلا الدالتان تقوم بعملهما عن طريق التفتيش عن الرقم أو الاسم في كل عقدة و عند التطابق تقوم بعرض كل بيانات الطالب المطلوب .
انتهينا – حتى الآن – من الكلاس الثاني dBase الخاص بإنشاء و إدارة قاعدة بيانات الطلاب دعونا الآن نقوم باختبارها للتأكد من عملها بصورة مقبولة ثم نستمر في عملية بناء المشروع J .

يتبع ...


تم نقل الصور الى سرفر المنتدى مع الشكر

eldoktor007
18-05-2009, 11:34 PM
اكثر من رائع اخى الكريم

وفقك الله دوما وابدا

TheFantasy
19-05-2009, 12:23 PM
شيء عظيم

تابع:)

elqnas1
19-05-2009, 06:41 PM
شرح رائع جدا

واصل ابداعك بالتوفيق

the.matrix.sdn
19-05-2009, 08:05 PM
اختبار الكلاس dBase :

قم بتعديل الملف main الذي قمنا باختبار البرنامج عن طريقه - بعد كلامنا عن الكلاس - Student


ليصبح كالتالي:




http://the.matrix.sdn.googlepages.com/dBaseClassTest.png


التحليل :
الأسطر 10 – 22 :
هذه دالة عامة – ليست عضوا في الكلاس – و قد أخذتها من صندوق الأدوات tool boxJ الخاص بي (و الذي يضم مجموعة متميزة من الدوال و الكلاسات) و أضفتها هنا و اسمها HandleNotaNumberError() ، وظيفتها التصدي لخطأ إدخال قيمة غير رقمية في متغير رقمي من خلال الكائن cin و سيتم استدعائها عند كل إدخال إذا حدث فشل في الكائن cin – بسبب إدخال قيمة غير رقمية في متغير رقمي – حيث تتم معالجة الفشل عن طريق الدالة cin.clear() و يتم تنبيه المستخدم حتى يحاول الادخال مرة أخرى ، و سيتكرر الأمر إذا أدخل قيمة خاطئة مرة أخرى و هكذا .. سنقوم بتطوير هذه الدالة لتعمل من خلال الاستثناءات عند تصميمنا لكلاس يمثل واجهة المستخدم لاحقا بحول الله ...

السطر 26 :
هنا أعلنا عن الكائن db من الكلاس dBase و هذا الكائن هو الذي سيقوم بكل العمل و ما علينا إلا إرشاده و توجيهه بالأوامر J;):cool: .

السطر 27 :
استعملنا التكرار for(;;) و هو يجعل البرنامج يكرر الكود التالي – بين القوسين سطري 28 و 179 – دائما بحيث لا يخرج من التكرار إلا بجملة شرطية ( بطريقة مشابهة للـ while ) الغرض من ذلك أن البرنامج سيعرض قائمة خيارات للمستخدم ليختار منها ، عند الاختيار يذهب البرنامج لتنفيذ ما تم اختياره ثم يرجع إلى نفس قائمة الخيارات مستعدا لتلقي أوامر أخرى حتى ينفذها و يرجع مرة أخرى للقائمة الرئيسية و هكذا دائما لحين الخروج من البرنامج .

السطر 29 :
مسح الشاشة و الغرض من ذلك هو أن يكون البرنامج منسقا بصورة جميلة تعجب المستخدم مما يرفع أسهم البرنامج لديه.

الأسطر 31 – 40 :
هذه هي قائمة البرنامج الرئيسية بها 9 خيارات : 1. لإضافة طالب جديد ، 2. تعديل بيانات طالب 3. حذف سجل طالب 4. البحث عن بيانات طالب بدلالة اسمه 5. البحث عن بيانات طالب بدلالة رقمه 6. عرض بيانات جميع الطلاب 7. عرض بيانات الناجحين فقط 8. عرض بيانات الراسبين 9. الخروج من قاعدة البيانات ، و يتم توجيه المستخدم للإختيار .

الأسطر 43 – 44 :
هنا ستم استدعاء دالة HandleNotaNumberError() في حالة حدوث فشل في الكائن cin بسبب إدخال قيمة غير رقمية في المتغير الرقمي choice و الذي يفترض أن يأخذ القيمة بين 1 – 9 التي تمثل اختيار العميل تمهيدا لتنفيذ الإختيار عن طريق أمر الـ switch .

الأسطر 45 – 46 :
الإعلان عن دوال مؤقته تستخدم لإدخال بيانات الطالب تمهيدا لتمريرها للكائن db من خلال الدوال الأعضاء ..

السطر 48 :
عبارة switch و تعمل على اختبار المتغير choice و من ثم يتم تنفيذ الجزء الخاص بقيمة المتغير من خلال case ..

الأسطر 50 – 74 :
في حالة اختار المستخدم الخيار 1 – إضافة طالب جديد - و بالتالي كانت قيمة المتغير choice هي 1 فسيتم تنفيذ هذا المقطع من الكود و فيه يقوم المستخدم بإدخال بيانات الطالب الجديد ثم يقوم الكائن بإضافته عن طريق الأمر (db.AddStudent()) و بعد ذلك يتم الرجوع مرة أخرى للقائمة الرئيسية .

الأسطر 75 – 111 :
و هذا الجزء سيتم تنفيذه في حالة اختيار الخيار رقم 2 – تعديل بيانات طالب – حيث سيتم أولا التأكد من رقم الطالب ( التأكد من وجود الطالب بقاعدة البيانات ) عن طريق الدالة العضو بالكائن (db.ChecID()) ثم يتم التعديل بإدخال البيانات الجديدة و استدعاء دالة التعديل العضو في الكائن (db.EditStudent()) لتقوم بالتعديل المطلوب.

الأسطر 112 – 133 :
هنا ستم تنفيذ الجزء الخاص برقم 3 و هو حذف سجل الطالب و بنفس طريقة الجزء السابق سيتم أولا التأكد من رقم الطالب الذي أدخله المستخدم و في حالة كان الرقم صحيحا يتم حذف سجل الطالب عن طريق الدالة (db.DeleteStudent()) . و هكذا بقية الأجزاء حتى النهاية و في الحقيقة لا أريد الاطالة أكثر و إنما قم بترجمة و تنفيذ كامل المشروع و اختبار النتائج للتأكد من عمل البرنامج بصورة سليمة قدر المستطاع .

الطبقة الثالثة : RW2File

هذا الكلاس وظيفته هي تسجيل بيانات الطلاب على القرص و ذلك تجنبا لضياع هذه البيانات عند إغلاق البرنامج ، ثم و عند تشغيل البرنامج مرة أخرى يقوم بقراءة هذه البيانات التي سبق تسجيلها على القرص و بالتالي يُدخلها في قاعدة البيانات ( السلسلة المتصلة ) مرة أخرى حتى نستطيع التعامل معها ( عرض ، تعديل ، حذف ...الخ ) لذلك سيقوم هذا الكلاس بوراثة الكلاس السابق dBase ليؤدي مهمته بنجاح ، و هي مهام الكلاس dBase بالإضافة إلى مهام أخرى جديدة ( الوراثة من المفاهيم المهمة و المستخدمة في تطوير البرمجيات في الـOOP ) و سنحتاج لتجهيز الكلاس dBase حتى يصبح هو الكلاس الأساس Base class الذي سيرثه كلاسنا الجديد RW2File بحيث يصبح ملف الرأس كالتالي :






http://the.matrix.sdn.googlepages.com/dBaseClassH3.png


حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/7.h)


ستلاحظ تغييرات في بعض الأسطر كالتالي :

سطر :20
تمت إضافة الكلمة المحجوزة virtual (ظاهري أو خيالي ) قبل دالة الهدم ~dBase() – لإعلام المترجم أننا نريد تجاوزها (عدم استخدامها) - و ذلك للتأكد من أن عملية تدمير الكلاس RW2File ستتم بصورة آمنة باستخدام دالة الهدم الخاصة به – و متنها هو نفسه متن الدالة ~dBase() حيث تقوم أيضا بحذف المؤشر Head ، و إذا لم نفعل هذا – أي اضافة virtual – فإن دالة البناء في الكلاس الأساس dBase قد يتم استدعاؤها عندما يتم تدمير الكلاس المشتق RW2File باستخدام المؤشر Head ( و الذي هو أصلا عضو في الكلاس dBase ) عن طريق الأمر delete و قد لايتم تحرير أي مساحة تم حجزها من الذاكرة ، لذلك كان لابد من هذا التعديل .

سطر 23 :
تم الإعلان عن دالة صديقة – و الدالة الصديقة يتم الإعلان عن رأسها فقط داخل الكلاس باستعمال الكلمة المحجوزة friend ، فهي ليست عضوا فيه ! و يتاح لها الوصول لكل عناصر الكلاس ! – و هذه الدالة و اسمها operator<< (المعامل >> ) و ستقوم بزيادة تحميل المعامل >> بحيث يقوم بعرض كل بيانات الطالب بدلالة مؤشر يشير لسجل الطالب و سترى ذلك بالتفصيل في الملف التنفيذي ( و هذا التعديل في الواقع لا دخل له بعملية تجهيز الكلاس dBase لعملية الوراثة و إنما هو فكرة لتحسين الكود باستخدام زيادة تحميل المعاملات Operator Overloading سترى نتائجها بعد قليل ، و قد وضعتها هنا حتى تتمكن من المقارنة بين الكلاس قبل التعديل و بعد التعديل ) .

سطر 26 :
في الدالة العضو AddStudent() قمنا بعمل تغييرين أو لهما أننا جعلنا القيمة التي تعيدها الدالة هي إشارة من نفس نوع السجل dBase::student (و قد كانت في السابق تعيد عددا صحيحا int !) ما الغرض من ذلك ؟ الجواب أن الكلاس المشتق RW2File يقوم - كما سبق ذكره - بكتابة سجلات الطلاب إلى القرص الصلب و أيضا قراءتها منه ، و لتنفيذ عملية الكتابة يجب أولا أن يقوم المستخدم بإدخال بيانات الطالب إلى قاعدة البيانات ثم و مباشرة يتم كتابة السجل الجديد على القرص ، سنستخدم – في الكلاس المشتق - دالة لكتابة السجل على القرص – كما سترى لاحقا - و لكن هذه الدالة ستحتاج لعنوان كل سجل على حدة حتى تستطيع الوصول لبياناته لتسجيلها لذلك تم تعديل الدالة AddStudent() بحيث ستعيد عنوان كل سجل يتم إدخاله في كل مرة .
التغيير الثاني في الدالة AddStudent() هو إضافة الكلمة المحجوزة virtual لإعلام المترجم أننا نريد تجاوز هذه الدالة بحيث أننا لن نستطيع استدعاءها إلا عن طريق دالة عضو في الكلاس RW2File لماذا ؟ لأن الوراثة تتيح لك إضافة تحسينات لدوال الكلاس الأساس عن طريق تجاوز الدالة المراد تحسينها و إنشاء دالة أخرى بنفس الاسم في الكلاس المشتق و تكون بنفس اسم الدالة التي تم تجاوزها في الكلاس الأساس (حيث أن الكلاس المشتق لا يستطيع تعديل الكلاس الأساس). قد يبدو لك هذا الكلام غامضا الآن و لكن ستتضح الرؤية أكثر عند الكلام بتفصيل عن الكلاس المشتق لاحقا بحول الله.

سطر 30 :
أضفنا دالة جديدة ChecName() و مشابهة للدالة الأخرى ChecID() ، هذه الدالة الجديدة ستعيد القيمة 1 إذا كان الاسم الذي مررناه لها موجودا بقاعدة البيانات – كما سترى في المتن – هذه الدالة سنستخدمها حتى لا نسمح للمستخدم بإدخال اسم لطالب جديد و هذا الاسم سبق إدخاله بحيث أن أسماء الطلاب – كأرقامهم – لا بد أن تكون فريد – مختلفة – ( هذا التعديل للكلاس dBase هو أيضا تعديل لتحسين عمل الكلاس و لا علاقة له بعملية تجهيزه للوراثة ..).

سطر 38 :
وضعنا المتغيرات الأعضاء (fID و Head) – و التي كانت في القسم الخاص private - وضعناها في القسم المحمي protected و ذلك حتى يتمكن الكلاس المشتق من الوصول لها ...


و الآن قم بتعديل الملف التنفيذي للكلاس الأساس


ليصبح كالتالي :



http://the.matrix.sdn.googlepages.com/dBaseClassCPP3.png



حمل ملف الكود من هنا (http://the.matrix.sdn.googlepages.com/8.cpp)


الأسطر 13 – 27 بها الدالة الصديقة operator<<()– و هي ليست عضوا في الكلاس لذلك لم نضع اسم الكلاس قبلها – متبوعا بالمعامل :: - كما فعلنا مع الدوال الأخرى ، هذه الدالة و بكل بساطة تقوم بزيادة تحميل المعامل >> باستخدام كائن os من الكلاس ostream (مكتبة iostream) بحيث يعرض لي بيانات الطالب بدلالة مؤشر ptr من نوع السجل dBase::studentبعبارة أخرى إذا استعملت العبارة cout << ptr; ( ptr مؤشر يُشير إلى سجل ) فسيتم عرض بيانات الطالب المخزنة في السجل الذي يشير إليه المؤشرptr و سنقوم باستخدام ذلك في أربع دوال ! : DisplayAll() و DisplayPass() و DisplayFail() و GetStudent() و GetStudent() – النسخة الأخرى منها – (انظر الكود ) فائدة هذا أن زيادة تحميل هذا المعامل مكنتني من تقليل حجم الكود بأكثر من 30 سطرا و جعلته أسهل الآن أو مستقبلا ...

ستلاحظ السطر 43 – في متن الدالة AddStudent() أصبح يعيد قيمة المؤشر Head (في حالة كانت هذه العقدةالأولى في السلسلة ) أما السطر 61 فيعيد قيمة المؤشر current حيث أننا عدلنا نوع البيانات الذي ستعيده الدالة من عدد صحيح إلى إشارة إلى السجل الذي تمت إضافته كما سبقت الإشارة لذلك بالأعلى...

الأسطر 238 – 257 : بها متن الدالة الجديدة ChecName() و هي مشابهة لعمل الدالة ChecID() .


قم بإجراء التعديلات أعلاه على الكلاس الأساس dBase ثم قم بإضافة ملف رأس للكلاس المشتق RW2File للمشروع و اكتب به الكود التالي :




http://the.matrix.sdn.googlepages.com/RW2FileClassH.png



حمل ملف الكود من هنا (http://the.matrix.sdn.googlepages.com/9.h)


تحليل الكود :

السطر 6 :
تضمين المكتبة fstream و التي تضم تعاريف تيارات الإدخال و الإخراج من و إلى الملف تمهيدا لاستخدامها...

السطر 11 :
أعلنا عن الكلاس الجديد RW2File و في نفس السطر أعلمنا المترجم بأن هذا الكلاس سيرث الكلاس الأساس dBase عن طريق كتابة اسمه بعد الرمز : مسبوقا بالكلمة public .
السطر 13 :
أول المتغيرات الخاصة و هو عبارة عن المتغير buffer من النوع الحرفي char بسعة 256 حرفا و سنستخدمه كمخزن مؤقت عند قراءة البيانات من الملف على القرص.

السطر 14 :
الإعلان عن المتغير DataFileWrite من النوع ofstream (ضمن المكتبة fstream) أي تيار إخراج حيث سنستخدم هذا المتغير لفتح الملف المحدد و كتابة البيانات به ثم إغلاقه .

السطر 15 :
الإعلان عن المتغير DataFileRead من النوع ifstream (أيضا ضمن المكتبة fstream) أي تيار إدخال حيث سنستخدمه لفتح الملف و قراءة البيانات ثم إغلاقه .

السطران 19 و 22 :
دالتي البناء و الهدم .

السطر 25 :
دالة ReadData() لقراءة تيار البيانات من الملف و هي من النوع int و تأخذ وسيطا عبارة عن إشارة إلى كائن من نفس الكلاس.

السطر 26 و 27 :
دالة WriteData() لكتابة تيار البيانات إلى الملف و هي من النوع int و تأخذ أربع وسائط و هذه الدالة تقوم بكتابة بيانات طالب (سجل) واحد فقط إلى الملف في كل مرة يتم استدعاءها أما الدالة الأخرى ( بنفس الاسم ) و بدون وسائط فتقوم بكتابة كامل السلسلة (كل الطلاب) إلى الملف عند استدعائها ، هذه الدالة الأخرى سيتم استدعاؤها عند نهاية البرنامج بغرض تسجيل كامل البيانات – بعد إجراء أي تعديل عليها - .

السطر 28 :
الدالة AddStudent() و هي أصلا عضو في الكلاس الأساس dBase – بتوقيع مختلف – و قد أعدنا تعريفها هنا حيث سيتم تحسينها حتى تستقبل رقم الطالب أيضا مع بقية بياناته لإضافتها لقاعدة البيانات . التوارث لا يتيح للكلاس المشتق إزالة أي شيء من الكلاس الأساس لذلك يمكننا تجاوز الدالة التي لا نريدها في الكلاس الأساس عن طريق وضع الكلمة المحجوزة virtual قبلها – كما سبق عند الكلام عن تجهيز الكلاس dBase – ثم إعادة تعريفها في الكلاس المشتق و هذا بالضبط هو ما عملناه هنا ! و هكذا أصبح لهذه الدالة تنفيذان أحدهما بالكلاس الأساس و الآخر بالكلاس المشتق و كل تنفيذ سيقوم بعمل مختلف ، تعدد التنفيذات – بنفس الاسم - هذا هو ما يسمى بتعدد الأشكال (تعدد الأوجه ) polymorphism . جميع أعضاء الكلاس dBase (متغيرات و دوال) أصبحت – عن طريق التوارث – أعضاء في الكلاس الجديد RW2File يمكن استخدامها مباشرة و عند استدعاءها يستطيع المترجم معرفة مكانها و الوصول لها بدون أي كود إضافي ، و هكذا استفدنا من الكلاس الأساس عن طريق توريثه لكلاس جديد يضمه مع تحسينات و إضافات من دون حاجة لإعادة كتابته من جديد و لعل هذا من أهم فوائد التوريث Inheritance و كما ترى فهو مفيد جدا في تطوير البرامج خاصة البرامج الكبيرة و المعقدة.



نأتي الآن لملف تنفيذ الكلاس كالتالي :




http://the.matrix.sdn.googlepages.com/RW2FileClassCpp.png



حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/10.cpp)


تحليل الكود :

الأسطر 8 – 11 :
متن دالة الهدم و تقوم بحذف المؤشر Head و الذي هو في الأصل عضو في الكلاس الأساس ، لاحظ أنها بنفس متن دالة هدم الكلاس الأساس dBase لذا كان لابد من تجاوز دالة الهدم في الكلاس الأساس عن طريق وضع الكلمة virtual قبلها كما سبق ...

الأسطر 13 – 44 :
متن الدالة ReadData() و نمرر لها إشارة لكائن rd من الكلاس RW2File ، و تعمل كالتالي كالتالي :
15 : نقوم باستخدام المتغير DataFileRead لفتح الملف أولا باستخدام الأمر open() حيث نضع بين القوسين اسم الملف بين علامتي تنصيص "DataRecord.dat " ( يمكن وضع مسار الملف كاملا لإعلام المترجم عن مكان وجوده أو ذكر اسم الملف فقط مما يُعلم المترجم أن الملف موجود في نفس مجلد المشروع و إذا لم يكن موجودا فسيقوم بإنشائه!) ، أما الأمر ios::in فهو يُعلم المترجم أن فتح الملف بغرض القراءة منه .
16 : هنا – و بعد فتح الملف – سيتأكد أولا من نجاح فتح الملف عن طريق الأمر is_open() و الذي يعيد القيمة صواب true إذا تمت عملية الفتح و بالتالي سينفذ الكود التالي بين قوسين :
18 – 20 : هنا متغيرات مؤقتة ستستخدم لتخزين البيانات التي ستتم قراءتها من الملف ثم تمريرها لدالة AddStudent() لإضافتها للسلسلة .
21 : تكرار for و سيستمر حتى تتم قراءة جميع البيانات من الملف . طبعا سنكون قد كتبنا البيانات بالملف مسبقا بطريقة محددة بحيث نفصل بين كل حقل و الآخر (كالرقم و الاسم .. ) بالرمز | ثم الرمز * للدلالة على نهاية السجل .

23 : نستخدم المتغير DataFileRead لقراءة أول جزء من البيانات باستخدام الأمر getline() حيث سنضع بين القوسين اسم المتغير الذي سنضع به البيانات التي ستتم قراءتها –و هو المتغير العضو buffer – ثم فاصلة , ثم عدد الأحرف المطلوب قراءتها – و هو عدد تقريبي – ثم و بين العلامتين ' ' نضع مُحدِّد – أيّ رمز تختاره – ، هذا المحدد سيخبر الأمر بحدود الجزء الذي تريد قراءته من البيانات ، بعبارة أخرى : هذا الأمر يقوم بالقراءة من السطر – بالملف – حتى يصل إلى الرمز المحدد أو حتى يصل إلى الرقم المحدد أيهما كان أولا . الغرض من ذلك هو الفصل بين البيانات – الرقم و الاسم و الدرجات .. الخ – بحيث أن كل نوع سيتم تخزينه في متغير مختلف :
24 : استخدمنا المتغير المؤقت studentID لنحفظ فيه قيمة الجزء الأول من سطر و البيانات و الذي هو رقم الطالب و لكن و لأن هذا الجزء من البيانات المخزن في المتغير buffer هو حرفي لذلك لابد من تحويله إلى عدد صحيح int باستخدام الأمر atoi() و الذي يقوم بالتحويل من char إلى int ثم نقوم باسناد الرقم الناتج إلى المتغير المؤقت studentID الخاص بحفظ رقم الطالب .
و ستتكرر هذه العملية ( قراءة البيانات جزءا بعد جزء و تخزينها في متغير مؤقت ) حتى الوصول للسطر :
36 و 37 : سيختبر إن كانت هذه نهاية الملف بحيث يخرج من التكرار for إن كان كذلك .
38: هنا يتم استدعاء الدالة المحسنة AddStudent() عن طريق الكائن rd و الذي مررنا إشارة له إلى دالة القراءة من الملف ، (سيتجاوز المترجم نسخة الدالة AddStudent بالكلاس الأساس و يستدعي النسخة الموجودة بالكلاس المشتق و هو – أي المترجم - واثق من ذلك لأننا عند تعريف هذه الدالة بالكلاس الأساس سبقناها بالكلمة المحجوزة virtual ! و بالرغم من ذلك فيمكننا استدعاء نفس الدالة و لكن من الكلاس الأساس و ذلك في الدالة WriteData() العضو في الكلاس المشتق كما سترى بعد قليل !) ، هذه الدالة سنمرر لها بيانات الطالب – و المخزنة في خمس متغيرات مؤقته – و وظيفة الدالة هي إضافة هذه البيانات إلى قاعدة بياناتنا (السلسلة المتصلة) و سيتم تكرار ذلك لكل الطلاب الذين تم تخزين بياناتهم في الملف . سيأتي الكلام عن متن هذه الدالة بعد قليل.
40 : إغلاق الملف بعد إنتهاء القراءة منه .
41 : ستعيد الدالة الرقم 0 للدلالة على نجاح العملية .
43 : أما في حالة الفشل في فتح الملف فستعيد الدالة الرقم -1 ، هذه القيم سنتعامل معها لاحقا عند استعمال الدالة في ملف main .

الأسطر 46 – 66 :
هنا الدالة WriteData() و التي تقوم بكتابة سجل طالب واحد للملف حيث نمرر لها بيانات هذا الطالب لإضافته أولا لقاعدة البيانات ثم كتابته للملف.
48 : نعلن هنا عن المؤشر ptr و الغرض منه تخزين عنوان سجل الطالب بالذاكرة – بعد إضافته لقاعدة البيانات – بغرض استخدام هذا المؤشر للوصول لبيانات الطالب (خاصة رقم الطالب) كما سيتضح بعد قليل .
49 : هنا يتم استدعاء الدالة AddStudent() العضو في الكلاس الأساس dBase عن طريق وضع معامل تحديد المدى :: بين اسم الدالة و اسم الكلاس الذي تنتمي له و ذلك حتى يعرف المترجم أننا نريد هذه الدالة و ليست الأخرى بالكلاس المشتق ، ( لاحظ هنا أن هذه الدالة ستقوم بعمل مختلف – نوعا ما – عن عمل الدالة AddStudent() بالكلاس المشتق RW2File – برغم أنهما يحملان نفس الاسم - و هذا ما سبق الاشارة إليه بأنه تعدد الأشكال لنفس الدالة polymorphism . ) بعد إضافة بيانات الطالب لقاعدة البيانات تعيد الدالة عنوان سجل الطالب بالسلسلة و يتم تخزين هذا العنوان في المؤشر ptr.
50 – 52 : هنا ستقوم الدالة بعرض رقم الطالب و المتوسط و التقدير حيث أن البرنامج هو الذي يقوم بتوليدها ثم يُخبر المستخدم فورا بها ...
53 : هنا سنقوم بفتح الملف تمهيدا للكتابة فيه باستخدام الأمر open() كما سبق عند الكلام عن القراءة من الملف ، و هنا نستخدم الأوامر : ios::out لإعلام المترجم أننا نريد الكتابة في الملف هذه المرة ، ثم الأمر ios::app لإعلام المترجم أيضا أننا و عند الكتابة لا نريد حذف البيانات الموجودة مسبقا بالملف ( و نستخدم هذا لأننا نستخدم هذه الدالة لكتابة بيانات طالب جديد في كل مرة يتم استدعاءها لذلك لا نريد حذف بيانات الطلاب الذين سبق إدخالهم ) ، أما الأمر ios::binary فهو يُفيد في تسجيل البيانات في شكل متسلسل أي بدون فراغات و الغرض من ذلك هو تقليل حجم الملف – قدر الإمكان - (خاصة إذا احتوى على عدد كبير جدا من الطلاب) بعدم وضع أي فراغات – أو أسطر جديدة - .
56 : هنا سنستخدم المتغير DataFileWrite لتسجيل رقم الطالب في الملف باستخدام معامل الادراج << (بصورة شبيهة لاستخدام هذا المعامل مع الكائن cout ) و بدلالة المؤشر ptr و الذي يُشير إلى عنوان سجل الطالب – الذي قمنا بإضافته للسلسلة – في الذاكرة . و سيتم تسجيل بقية البيانات في الملف في الأسطر التالية لذلك .
62 : إغلاق الملف بعد إنتهاء عملية الكتابة .

الأسطر 68 – 93 :
نفس الدالة السابقة WriteData() إلا أنه تم إعادة توصيفها هنا (overloaded) بحيث تقوم بكتابة بيانات جميع الطلاب إلى الملف بدلا عن النسخة الأولى التي تقوم بكتابة بيانات طالب واحد في كل مرة .
70 : أعلنا عن مؤشر ptr و أعطيناه قيمة المؤشر Head بحيث سنصل لكل سجلات (عقد) السلسلة عن طريقه.
71 : هنا سيتم فتح الملف تمهيدا للكتابة فيه و هو كما في النسخة السابقة من الدالة إلا أنك تلاحظ أننا لم نستخدم الأمر ios::app مما يعني أن هذه البيانات ( جميع الطلاب ) ستتم كتابتها بعد حذف كل البيانات التي سبقت كتابتها !!، لماذا ؟ : افترض أنك قمت بتشغيل قاعدة البيانات و قمت بإضافة طالب جديد فسيقوم البرنامج بكتابة بيانات هذا الطالب و هكذا في كل مرة تقوم بإضافة طالب ، و لكن يمكنك أيضا تعديل هذه البيانات أو حذفها لذلك في هذه الحالة سيتم إعادة كتابة جميع هذه البيانات مرة أخرى – مع حذف البيانات القديمة – و هذه الدالة سيتم استدعاءها في الملف main كما سترى لاحقا عند تجربتنا للكلاس.
74 : هنا نختبر المؤشر Head للتأكد من أن قاعدة البيانات ليست خالية و بالتالي نقوم بتسجيل بيانات الطلاب واحدا بعد آخر .
88 : في حالت كانت قاعدة البانات خالية (أي أن المؤشر Head خالي) فلن تتم كتابة أي شي و لكن سيحذف البيانات الموجودة فقط (سترى فائدة ذلك إذا كان بقاعدة البيانات سجل طالب واحد – مثلا – و قام المستخدم للبرنامج بحذفه ثم أغلق البرنامج ).

الأسطر 95 – 128 :
الدالة AddStudent() و هي نفس الدالة AddStudent() في الكلاس dBase مع وجود 3 إختلافات بينهما لذلك لن نعيد الكلام عنها و إنما نتكلم عن الإختلافات بينهما أولها توقيع الدالة بمعنى الوسائط التي نمررها للدالة ، فهذه الدالة نمرر لها هنا 5 وسائط – أولها رقم الطالب – أما الأخرى فنمرر لها أربع وسائط فقط – بدون رقم الطالب – الإختلاف الثاني :
94 : في هذا السطر نعيّن قيمة المتغير fID العضو بالكلاس الأساس بإعطائه قيمة الوسيط id – و الذي يحمل رقم الطالب الذي تمت قراءته من الملف - . أما في نفس الدالة بالكلاس الأساس فكنا نزيده بمقدار 1 (سطر 14 في الملف التنفيذي للكلاس dBase) .
124 : هنا الإختلاف الأخير بينهما حيث أن هذه الدالة تعيد القيمة 0 للدلالة على نجاحها في تنفيذ مهامها أما الدالة الأخرى فقد كانت تعيد إشارة لعنوان العقدة التي تمت إضافتها (انظر سطري 26 و 44 بالملف التنفيذي للكلاس dBase ) .


و هكذا انتهينا بحمد الله من تصميم و تنفيذ الكلاس RW2File و المشتق من الكلاس dBase نأتي الآن إلى تجربته ، قم بتعديل ملف main ليصبح كالتالي :




http://the.matrix.sdn.googlepages.com/RW2FileClassTest.png


التحليل :

السطر 10 :
رأس الدالة HandleNotaNumberError() و قد سبق الكلام عنها عند تجربة الكلاس dBase . و بقية الكود هو نفسه كما في اختبار الكلاس dBase مع بعض التعديلات :

السطر 14 :
الإعلان عن الكائن rd من الكلاس RW2File .

السطر 15 :
المتغير DataChange من النوع البوولي (المنطقي : صواب أو خطأ) و قد أعطيناه قيمة أولية false أي خطأ ، سنستفيد منه لاحقا عند استخدام دالة WriteData() – النسخة التي تقوم بكتابة السلسلة بكاملها للملف – الغرض من ذلك تحسين أدء البرنامج – خاصة عند ضمه لبيانات جمع غفير من الطلاب – حيث لن يتم مناداة الدالة إلا إذا كانت هناك تعديلات قد أجريت ( بالحذف أو الإضافة ) على قاعدة البيانات كما سترى بالسطر 171.
السطر 17 :
هذه أول دالة عضو نستخدمها و هي ReadData() حيث ستعمل على قراءة البيانات الموجودة بالملف أولا – إن وجدت – تمهيدا للعمل عليها .

الأسطر 18 – 19 :
هنا و في حالة فشل الدالة الآنفة في فتح الملف فستعرض للمستخدم رسالة خطأ تخبره بذلك .

السطر 67 :
هنا استدعاء الدالة العضو WriteData() و التي تقوم بإضافة الطالب لقاعدة البيانات ثم تقوم بكتابة بيانات الطالب للملف على القرص كما سبق عند شرحها .

الأسطر 81 و 104 :
تلاحظ هنا أننا استدعينا دالتي ChecID() و EditStudent() عن طريق كائن من الكلاس RW2File مع أنهما يتبعان للكلاس dBase في الأصل و لكن قام الكلاس RW2File بوراثة الكلاس dBase و بالتالي سيرث جمع الدوال و المتغيرات ( العامة و المحمية ) به و يستطيع استعمالها مباشرة كأنها تتبع له هو في الأساس ! و هذا أجمل ما في الوراثة ، كالكائن الحي تماما JJ ، و الأمر كذلك في بقية الدوال ، لاحظ أنه إذا نجحت الدالة EditStudent() في تعديل بيانات الطالب فستتغير قيمة المتغير DataChange إلى صواب true مما سيجعل الدالة WriteData() – سطر 172 تقوم بكتابة كل البيانات مرة أخرى للملف و هكذا الأمر عند حذف سجل أي طالب في case 3 (سطر 120 ).

الأسطر 181 – 185 :
عند اختيار المستخدم لإغلاق قاعدة البيانات سيتم اختبار المتغير DataChange فإذا كانت قيمته true فهذا يعني أنه تم عمل تعديل بالحذف أو الإضافة مما يوجب استدعاء الدالة العضو WriteData() لإعادة كتابة جميع البيانات مرة أخرى إلى الملف و إذا لم تنجح الدالة في ذلك فسيتم عرض رسالة تفيد المستخدم بذلك ، و في كل الحالات يتم الخروج من البرنامج .

الآن قم بالترجمة ثم شغل البرنامج و قم باختبار جميع الخيارات بصورة مكثفة ، و قد قمت بذلك - إلا أنني لم أضع الصور هنا بداعي الاختصار – و قد عمل البرنامج بصورة ممتازة...
يتبع ...

the.matrix.sdn
19-05-2009, 08:35 PM
من مميزات المترجم Dev-C++ أنه يضم أداة لتحليل عمل البرنامج بحيث يخبرك عن عدد مرات و زمن استدعاء كل دالة مما يفيد في اختبار سرعة البرنامج و أدائه و تفاعل دواله ...
اضغط على القائمة Execute و اختر Profile analysis كما بالصورة :


http://the.matrix.sdn.googlepages.com/Analys1.png


بعد ثوان سيفتح لك نافذة شبيهة بالنافذة التالية :


http://the.matrix.sdn.googlepages.com/Analys2.png

قم بالاطلاع عليها ففيها معلومات مفيدة عن أداء البرنامج بحيث إذا كانت هناك دالة تستغرق وقتا أطول من اللازم – بسبب بطء أدائها أو كثرة تكرارها – تقوم بتعديلها و تحسينها و ليس هذا موضع تفصيل .

الطبقة الرابعة UserInterFace :
هذه الطبقة – و كما ذكرنا – هي ستمثل الوسيط بين المستخدم و البرنامج فهي واجهة الاستخدام التي ستتفاعل مع طلبات المستخدم و تقوم بتحقيقها و عرض النتائج ، بالتالي فسيتغير شكل الملف main بشكل كامل حيث ستقوم هذه الطبقة بمعظم مهامه ... و لكن دعونا الآن نطلع على ملف الرأس الخاص بها كالتالي :


http://the.matrix.sdn.googlepages.com/UserInterFaceClassH.png

حمل الكود من هنا (http://the.matrix.sdn.googlepages.com/12.h)


أما الملف التنفيذي للكلاس فكالتالي :


http://the.matrix.sdn.googlepages.com/UserInterFaceClassCpp.png

حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/13.cpp)

كما تلاحظ هذا الكلاس هو المسئول عن عرض قائمة الخيارات للمستخدم و التفاعل مع اختيار المستخدم لتنفيذ طلبه ، الآن عدل الملف main حتى يصبح كالتالي :


http://the.matrix.sdn.googlepages.com/UserInterFaceClassTest.png

حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/14.cpp)

جميل جدا :D:D، الملف main أصبح أصغر و أجمل بعد أن قام الكلاس UserInterFace بأداء مهامه ، قم بالترجمة و التنفيذ و تجربة البرنامج بصورة مكثفة ;);)..
و هكذا نكون على وشك الانتهاء من المشروع و لكن يتبقى لنا كلاس واحد فلنتكلم عنه :

الطبقة الخامسة : StudentCount
هذا الكلاس مهمته بسيطة جدا ألا و هي عد الطلاب بحيث نعرف العدد الإجمالي للطلاب في قاعدة البيانات و عدد الطلاب الناجحون و عدد الطلاب الراسبون ، و في الواقع الغرض منه هو دراسة المتغيرات الأعضاء الساكنة و الدوال الأعضاء الساكنة static function في الكلاس و كيفية التعامل معها لذلك سنقوم بعمل الكلاس ثم نهيء الكلاس الأول Student حتى يرث من الكلاس الجديد StudentCount و نجري بعض التعديلات على بعض الكلاسات الأخرى حتى نستفيد من الكلاس الجديد..
ملف رأس الكلاس StudentCount:


http://the.matrix.sdn.googlepages.com/StudentCountH.png

حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/15.h)

الأسطر 9 – 11 :
أعلنا عن ثلاث متغيرات ساكنة static من النوع int أولها لحفظ عدد جميع الطلاب و الثاني لتسجيل عدد الطلاب الناجحين و الثالث للراسبين، في الواقع كانت المتغيرات الساكنة تستعمل في السابق لحفظ قيم معينة و هذه القيم تحتفظ بها المتغيرات طوال فترة تشغيل البرنامج و بين الاستدعاءات المختلفة للدالات – مع إمكانية تعديل هذه القيم بعكس المتغيرات الثابتة const – و لكن الآن استخدام الكلاسات (الطبقات) أغنانا عن ذلك لأن المتغيرات الأعضاء الخاصة في الكلاس أتاحت لنا حفظ حالتها الداخلية و هي الوظيفة التي كنا نستخدم المتغيرات الساكنة لها .
مع هذا ما زال بإمكان المتغيرات الساكنة لعب دور في الكلاسات ، فالمتغيرات الساكنة في الكلاس تتم تهيئتها عندما يبدأ البرنامج و تصبح مشتركة بين جميع نسخ الكلاس مما يتيح لنا استخدامها لعد نسخ الكلاس Student و الذي - في الواقع - كل نسخة منه تمثل طالبا مختلفا ! (لا تنس أن الكلاس Student يرث الكلاس الجديد) .

الأسطر 22 – 25 :
أربع دوال إثنتان منهما تقومان بالزيادة أو الانقاص بمقدار 1 لقيمة المتغير PassSize و إثنتان تقومان بنفس الشيء للمتغير FailSize أما المتغير الثالث فسيتم التعامل معه بالزيادو أو النقصان عن طريق دالتي البناء و الهدم ! كما سترى بحول الله عند الكلام عن الملف التنفيذي للكلاس.

الأسطر 28 – 30 :
ثلاث دوال ساكنة كل واحدة منهما تعيد قيمة أحد المتغيرات الأعضاء الساكنة ، فائدة هذه الدوال الساكنة أننا سنتمكن من استدعائها بدون إنشاء كائن من الكلاس ! كما سترى لاحقا .

نأتي الآن للملف التنفيذي :


http://the.matrix.sdn.googlepages.com/StudentCountCpp.png

حمل الملف من هنا (http://the.matrix.sdn.googlepages.com/16.cpp)

الأسطر 5 – 7 :
هذه الأسطر تقوم بتصفير المتغيرات الأعضاء الثلاث و سيتم تنفيذها أول بدء البرنامج و قبل إنشاء أي كائنات !! و ذلك لأنها متغيرات ساكنة static و سنغير قيمتها لاحقا فعند إضافة طالب جديد ستتم زيادة المتغير AllSize بمقدار 1 ثم سننظر في نتيجة هذا الطالب فإن كان ناجحا سنزيد المتغير PassSize بمقدار 1 و إلا فسنزيد المتغير FailSize بمقدار 1 ، و عند حذف الطالب سنقوم بالعكس : الإنقاص بمقدار 1 .

السطر 9 :
دالة البناء و كما تلاحظ فهي تقوم بزيادة المتغير AllSize (و الخاص بعدد جميع الطلاب) بمقدار 1 ، معنى هذا أنه في كل مرة يتم فيها استدعاء هذه الدالة فسيزيد المتغير الساكن بمقدار 1 ، لا تنس أن الكلاس Student سيرث هذا الكلاس StudentCount و بالتالي فكل كائن من الكلاس Student يتم إنشاؤه فسيتم إستدعاء دالة البناء هذه عند إنشائه ! (ثم يتم أيضا – طبعا – استدعاء دالة البناء الخاصة به ) مما يعني زيادة عدد الطلاب بمقدار 1.

السطر 11 :
دالة الهدم و التي سيتم استدعاؤها عند حذف كائن من الكلاس Student (سجل طالب) و بالتالي سيتم انقاص المتغير AllSize بمقدار 1.

السطر 13 :
الدالة SetPassSize() و التي ستقوم بزيادة المتغير PassSize بمقدار 1 ، هذه الدالة سنستعملها عند إضافة طالب جديد ناجح إلى قاعدة البيانات .

السطر 18 :
الدالة SetFailSize() و هي كسابقتها تقوم بزيادة المتغير FailSize بمقدار 1 ، نستعمل الدالة عند إضافة طالب جديد راسب! .

السطر 23 :
الدالة الساكنة GetAllSize() و التي ستعيد قيمة المتغير الساكن AllSize ، هذه الدالة نستطيع استدعاءها في أي مكان نريد من البرنامج لمعرفة العدد الكلي للطلاب من دون حتى أن نكون قد أنشأنا أي كائن منها ! و كذلك الدالتان الساكنتان الأخريتان! .

السطر 28 :
الدالة الساكنة GetPassSize() و هي تُرجع قيمة المتغير الساكن PassSize .

السطر 33 :
الدالة الساكنة الثالثة GetFailSize() و التي تعيد قيمة المتغير FailSize .

السطر 37 :
الدالة SetPassDec() و التي تقوم بإنقاص المتغير PassSize بمقدار 1 ، نستعمل هذه الدالة عند حذف طالب ناجح بحيث ينقص عدد الطلاب الناجحين بمقدار 1 .

السطر 42 :
الدالة الأخيرة SetFailDec() و التي تقوم بإنقاص المتغير FailSize بمقدار 1 ، و سنستعملها إذا كان الطالب المحذوف راسبا .

الآن أعزائي سنجري بعض التعديلات البسيطة على بقية البرنامج حتى تتم الاستفادة من كلاسنا الجديد و المثير J :
أولا الكلاس Student و الذي سنجعله يرث من الكلاس StudentCount بحيث أن أي نسخة من الكلاس Student (أي سجل طالب ) ستتضمن داخلها تلقائيا نسخة من الكلاس الجديد .
سنقوم بتعديل أول سطر في الكلاس المشتق Student حتى يصبح كالتالي :
Class Student : public StudentCount { //…

أما الكلاس dBase فسنجري عليه عدة تغييرات بحيث سيصبح ملفه التنفيذي كالتالي :


http://the.matrix.sdn.googlepages.com/dBaseClassCPP4.png

حمله من هنا (http://the.matrix.sdn.googlepages.com/17.cpp)

أهم التعديلات هنا الأسطر 167 – 169 حيث ترى أننا قمنا بإستدعاء الدوال الساكنة بدون استعمال أي كائن من الكلاس فقط ذكرنا اسم الدالة مسبوقا باسم الكلاس و بينهما معامل تحديد المدى :: .

أما الكلاس RW2File فسيصبح كالتالي :


http://the.matrix.sdn.googlepages.com/RW2FileClassCpp2.png

حمله من هنا (http://the.matrix.sdn.googlepages.com/18.cpp)

تبقى الكلاس UserInterFace و الذي سنعمل به تعديلا بسيطا بحيث يصبح ملفه التنفيذي كالتالي :


http://the.matrix.sdn.googlepages.com/UserInterFaceClassCpp2.png

حمله من هنا (http://the.matrix.sdn.googlepages.com/19.cpp)


بهذا و بحمد الله نكون قد انتهينا من المشروع قم بالترجمة و التنفيذ و جرب البرنامج بصورة مكثفة – و جرب حتى إدخال قيم خاطئة و غير منطقية – لترى كيف يتصرف البرنامج و هل يحتاج إلى أي تعديل ؟ ، مع العلم أنه ليس هناك برنامج كامل ! و بالتالي فإن أي برنامج يمكن تحسينه و تطويره ، و تذكر دائما أن إعادة تصميم البرنامج و تطويره من المسئوليات الحيوية الملقاة على عاتق المبرمج فقط كن صبورا ، فالأمر لا يتطلب سوى بعض الوقت و الخبرة و التفكير .
لتحميل ملفات المشروع كاملة – في صورته النهائية – مضغوط بصيغة RAR إضغط هنــــــا (http://the.matrix.sdn.googlepages.com/StudentDatabaseSystem.rar) . و لتحميل هذا الموضوع بصيغة مستند .docمضغوط RAR من هنا (http://the.matrix.sdn.googlepages.com/rar) .

بقي أمر أخير : يتيح لنا المترجم أن نضع الأيقونة التي نريدها للبرنامج و ذلك في خيارات المشروع – Project Options(Alt+P) حيث ستظهر لك النافذة التالية :


http://the.matrix.sdn.googlepages.com/Projectpro.png

حيث يمكنك اختيار أيقونة من مكتبة المترجم Library أو تحديد مكان الأيقونة التي تريد على القرص Browse و هناك خيارات أخرى مثل اسم المنتج و الشركة و رقم الاصدار و غير ذلك ... ستجد الملف التنفيذي (الهدف) في نفس مجلد المشروع و بنفس الاسم و لكن بالإمتداد exe و بالأيقونة التي اخترتها ، قم بتجربته و بالتوفيق ...

في مشروعنا التالي – بحول الله – سنعمل على تطوير نفس هذا المشروع بحيث نعمل له واجهة رسومية جميلة J تسر المستخدم و تجعله يحب التعامل مع البرنامج J.

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

أخوكم المحب : the.matrix.sdn

the.matrix.sdn
19-05-2009, 08:41 PM
اكثر من رائع اخى الكريم

وفقك الله دوما وابدا

ألف شكر أخي الكريم / الدكتور ، شرفت الموضوع ...

the.matrix.sdn
19-05-2009, 08:43 PM
شيء عظيم

تابع:)

مشكور يا أستاذ على المرور .. تحياتي

the.matrix.sdn
19-05-2009, 08:45 PM
شرح رائع جدا

واصل ابداعك بالتوفيق

مرحبا اخي الكريم ، مشكور على المرور مع تحياتي و تقديري

nahrin
23-05-2009, 11:08 PM
مشكوووووووووووووووووووور وبارك الله فيك على هذا العمل الرائع

فارس الانتقام
26-05-2009, 01:28 PM
و انا كنت احسب البرمجة بالفيجوال صعبة


بصراحة مجهود رائع ومتميز واصل ابداعك

the.matrix.sdn
26-05-2009, 01:52 PM
مشكوووووووووووووووووووور وبارك الله فيك على هذا العمل الرائع
العفو أخي الكريم و شكرا على المرور ..

the.matrix.sdn
26-05-2009, 01:55 PM
و انا كنت احسب البرمجة بالفيجوال صعبة


بصراحة مجهود رائع ومتميز واصل ابداعك

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

.(زمان الصمت).3
07-06-2009, 05:24 PM
ماشاء الله تبارك الله

ماهو البرنامج المستخدم في التطبيق؟
وماهي اللغه المستخدمه؟

وهل تملك شروح مفيده للـ oop programing
وشكراً
أخوك مبتديء برمجة c++

the.matrix.sdn
08-06-2009, 08:32 PM
ماشاء الله تبارك الله

ماهو البرنامج المستخدم في التطبيق؟
وماهي اللغه المستخدمه؟

وهل تملك شروح مفيده للـ oop programing
وشكراً
أخوك مبتديء برمجة c++

مرحبا بك أخي و شرفت الموضوع...
بالنسبة لأسئلتك أخي فيبدو أنك لم تقرأ الموضوع جيدا لأنه من الواضح أنه يتكلم عن مشروع لتطبيق مفاهيم الـOOP الأساسية من خلال لغة السي بلس بلس و باستخدام مترجم (بيئة تطوير) ++ DevC .
على العموم شكرا مرة أخرى على المرور و بالتوفيق.
تحياتي و تقديري

ابوراقي
10-06-2009, 09:30 PM
موضوع رائع بكل معنى الكلمة
مجهود تشكر عليه

الله يوفقنا واياك قل آمين

the.matrix.sdn
23-06-2009, 11:21 AM
موضوع رائع بكل معنى الكلمة
مجهود تشكر عليه

الله يوفقنا واياك قل آمين

اللهم آميييين يا رب العالمييين
مشكور أخي على المرور و شرفت الموضوع ..

the.matrix.sdn
10-02-2010, 01:46 AM
up

MrProgrammer
10-02-2010, 01:57 AM
بارك الله فيك اخى the.matrix.sdn

فعلا لغة السى بلس بلس من اللغات القوية جدا وليست منتشرة بين المبرمجين الان مثل اللغات الحديثة كالسى شارب مثلا
جزاك الله خيرا

تم التقييم 5 \ 5

the.matrix.sdn
10-02-2010, 02:09 AM
بارك الله فيك اخى the.matrix.sdn

فعلا لغة السى بلس بلس من اللغات القوية جدا وليست منتشرة بين المبرمجين الان مثل اللغات الحديثة كالسى شارب مثلا
جزاك الله خيرا

تم التقييم 5 \ 5

شكرا أخي الكريم على تعليقك و تقييمك للموضوع.

لاشك أن اللغات الحديثة أخذت حيزا مقدرا بين المبرمجين الآن و بخاصة جافا و سي شارب و التي قدمتها شركة ميكروسوفت فهما لغتان قويتان و تحققان الكثير من الاحتياجات الحديثة.. , و من الملاحظ أن كلاهما تم تطويرهما اعتمادا على اللغة الأم سي بلس بلس ، و في كل ٍ خير ..
تحياتي و شكرا لك مرة أخرى و بالتوفيق..

hala_moon
04-04-2010, 10:24 AM
جزاك الله خير

يمانية
11-08-2010, 08:30 AM
ينقل الى قسم الشروحات مع الشكر الجزيل

الجهـنـي
11-08-2010, 03:55 PM
مشروع أكثر من رائع تستحق التقييم
5 / 5 :)
اللي ما يعرف غير فيجول بيسك دوت نت :confused:

Aqeeil
17-08-2010, 11:10 PM
شكرا جزيلا لموضوعكـ،،
تحياتي لــكـ،، Aqeeil
+
+
+

yasser965
09-10-2010, 11:08 PM
جزاك الله الف خيرك عمل رائع لك مني 50 نجمه

دانه الجنه
19-10-2010, 08:08 PM
جزاك الله جنة الفردوس على هذا الشرح الروعه يادكتور

أبوعزاب
05-11-2010, 08:10 AM
موضوع جدا رائع

عبد الله/امهادي
05-11-2010, 09:40 AM
مشكووووووووووور

MR.MILE
09-12-2010, 01:22 PM
http://img99.imageshack.us/img99/4564/678g.gif

MEZO_FOX
25-12-2010, 05:53 AM
بارك الله فيك

asd000asd
08-01-2011, 05:19 PM
بارك الله فيك .. hh: .. وشكراً جزيلاً

shooter1000
09-01-2011, 02:41 PM
♥♥♥

بارك الله فيك

♥♥♥

جنزوري
26-04-2011, 04:45 PM
اخي الكريم جزاك الله خير عن هذا العمل المشرف وانا من الناس اللي بستفيد من هذا العمل ويشرفني ان اذكر مصدر هذا العمل الطيب وفقك الله في خدمة المسلمين

دعاء2011
20-08-2011, 06:19 PM
جزاك الله خيرا
بارك الله فيك جهد طيب
سلمت يدكــ

the.matrix.sdn
21-09-2011, 10:26 AM
شكرا جزيلا اخوتي على المشاركة و التعليق ، وفقنا الله و إياكم ،،
تحياتي و تقديري

النوارس10
29-11-2011, 02:03 AM
بارك الله فيك اخي ...
هل رقم خطوات التحميل للكواد 11 هي نسها 12 و13 لاني ما وجدتهم متسلسلات في الترقيم ...
اسال من الله لكم التوفيق والخير ..

روح سكره
09-12-2011, 03:38 AM
مشكور الله يعطيك العالفيه

alknsa
13-01-2012, 07:41 PM
يمكن تحلو السوال هذ
write a java program to create the class rectangle with constructor and a method to compute the area of a rectangle using overloading of the constructor and create 100 instance for rectangle

سامر الانباري
19-06-2012, 01:21 AM
اللهم يبارك لك في علمك ويرزقك الجنة

الاسحاقي
30-07-2012, 01:42 AM
بارك الله بيك اخي اكثر من رائع

محمود رغمان
20-11-2012, 12:48 PM
ممكن المشروع بالفيجوال بيسك نت حتى يستفيد الجميع

MR.Esso
21-11-2012, 04:16 AM
بارك الله فيك اخي العزيز

shy look
09-01-2013, 11:40 PM
http://im34.gulfup.com/Ogki1.gif (http://www.gulfup.com/?T5qvqK)

meclink
22-09-2013, 03:10 AM
لكن في c++ يمكن للكلاس أن ترث من أكثر من كلاس بينما مثلا في فيبي دوت نيت لا يمكن للكلاس أن ترث سوى من كلاس واحدة