مقدمة إلى البرمجة بلغة c++
TRANSCRIPT
1
الوحدة األولى++Cمقدمة إلى البرمجة بلغة
0.1
بنهاية هذه الوحدة: ستتمكن من كتابة برامجC++.بسيطة .ستتمكن من استخدام عبارات اإلدخال واإلخراج ستتعرف على أنواع البيانات األساسية فيC++. ستتمكن من إستعمال العوامل الحسابية فيC+
+. ستتعرف على العوامل العالئقية فيC++.
تتمتع بطابعالتيمن أشهر اللغات ++ C لغة تعتبر;إلالقوة والمرونة . وعلىنتاج أسرع برامج وأفضلها أداءا
إال أنهاالرغم من وجود العديد من لغات البرمجة األخرى تتميز++C وقوتها . فاللغة ++C لغة تفتقر شمولية
القوةو ،بقابليتها على معالجة التطبيقات الكبيرة والمعقدة; في تصميمفي صيانة البرامج المكتوبة بها مما يوفر وقتا
وتطويرها .البرامج; للغة ++Cتعتبر اللغة Bjarne وقد أنشأها .C امتدادا
Stroustrupحينها وكانت تسمى ،م 1979 عام Cمع العامفي ++C إلى وتغير اسمها (،C with classes )فئات
م.1983 أسلوب البرمجة كائنية المنحى++Cتعتمد اللغة
Object Oriented Programming، بـ والذي ; ) يعرف اختصاراOOP،) تم تطويره بسبب قيود كانت أساليب البرمجةوالذي
اللغات اإلجرائية تفرضها علىفيالقديمة المتمثلة نتعرف على طبيعة تلك القيود يجب أنولكي .المبرمجين
اللغات اإلجرائية.فينلقى الضوء على ما يحدث اللغات اإلجرائية:
وغيرها من لغاتFortran و Pascal،C ،Basicلغات أنأي (.Procedural) لغات إجرائية هيالبرمجة التقليدية
عبارة عن تعليمة للحاسوب أن ينفذهي اللغة فيكل عبارة ; ما : أحصل على دخل أو أجمع أرقام الخ.. .… شيئا
لذا نجد أن البرنامج المكتوب بلغة إجرائية هو عبارة تبدو هنالك مشكلة مع البرامج عن الئحة من التعليمات. ال
التعليمات ويقوم الئحة فالمبرمج ينشئ،اإلجرائية الصغيرة ولكن مع كبر حجم البرامج ال تعود الئحة.الحاسوب بتنفيذها
من التعليمات فعالة حيث يصعب فهم برنامج يتألف من أجزاء أصغر،إلىمئات من العبارات إال إذا كانت مقسمة
) واإلجراءات(Functions )لذا تم اعتماد أسلوب الداالتProcedures)كوسيلة لجعل البرامج أسهل للقراءة والفهم ،
;، البرنامج واجهة محددةفيتمتلك كل دالة حيث وتنفذ هدفا; ولكن المشكلة ما تزال قائمة : مجموعة من.محددا
; محددة. التعليمات تنفذ مهاما
2
المقدمة .11
يظهر ضعف،حجم البرامج وتعقيدها مع تزايدو إلي حيث تصبح البرامج الضخمة معقدة اإلجرائي،األسلوب
من أهم أسباب فشل اللغات اإلجرائية هو الدور .حد كبير حيث تعطى البيانات أهمية ثانوية،انات فيهاي تلعبه البالذي
ويكون، وجود البرامجفي السبب هيعلى الرغم من أنها حيث ، تعمل على هذه البياناتالتيالتشديد على الداالت
يصبح باإلمكانلكي دالة أييتم تعريف البيانات خارج ; ماالداالت فيالوصول إليها من كل البرنامج، لذا غالبا
تكون البيانات عرضة للتغيير أو التعديل الخطأ. وعلى الرغم تعرف متغيراتC وPascalـ من أن هنالك بعض اللغات ك
لكن. دالة واحدةفيوهي متغيرات معرفة (، Local)محلية يجبالتيالمتغيرات المحلية غير مفيدة للبيانات المهمة
; البرنامج.فيالوصول إليها من عدة داالت هناكأيضا مشكلة طريقة تخزين البيانات بسبب إمكانية عدة داالت
يمكن تغيير ترتيب البيانات من دون تغيير للوصول إليها. ال تتعامل معها.التيكل الداالت
إذا أضفنا بيانات جديدة نحتاج لتعديل كل الداالت حتىوتستطيع هذه الداالت استعمال هذه البيانات الجديدة .
،; ; ما يكون تصميم البرامج اإلجرائية صعبا أنلغالبا مكوناتها الرئيسية )الداالت( عبارة عن بنية بيانات ال تقلد
; الحقيقيالعالم اللغات اإلجرائية إنشاءفي يصعب .و جيدا; أي تلكفي نوع بيانات جديد بخالف األنواع المعرفة أصال
نياللغات ، لكل هذه األسباب تم تطوير األسلوب الكائالمنحى.
المنحى:- ي األسلوب الكائن دمج هيالفكرة األساسية وراء اللغات كائنية المنحى
كينونةفي تعمل على تلك البيانات التيالبيانات والداالت -وعادة تزود داالت الكائن ، (Object)واحدة تسمى كائن
الطريقة-(Member functions) تسمى أعضاء دالية والتي لذا تكون البيانات محمية من، البياناتإليالوحيدة للوصول
)التعديالت الخطأ ويقال أن البيانات وداالتها مغلفةEncapsulated ) كينونة واحدة.في
مميزات اللغات كائنية المنحى : البرمجة وكائنات الحياةفيهنالك تطابق بين الكائنات
الفعلية، فالعديد من الكائنات الفعلية لها وضعية ) خصائص.يمكن أن تتغير ( وقدرات )أشياء يمكن أن تقوم بها(
3
تسجل بيانات الكائن ووضعيته كما تتوافق++C في أعضاءه الدالية مع قدراته، تدمج البرمجة كائنية المنحى
كينونة واحدةفي للوضعيات والقدرات البرمجيالمرادف تسمى كائن النتيجة لذلك كينونة برمجية تتطابق بشكل جيد
مع الكثير من كائنات الحياة الفعلية. : ( Inheritance ) الفئات والوراثة
حيث يمكننا، مثيالت من الفئاتهي OOP فيالكائنات وتلعب دور خطة،تعريف كثير من الكائنات تابعة لفئة معينة تحددالتي يوه، أو قالب يتم إنشاء الكائنات على أساسه
كائنات تلكفي سيتم شملها التي البيانات والداالت هيما . وصف لعدد من الكائنات المتشابهةهي لذا فالفئة .الفئة
حيث يمكن استعمال، فكرة الوراثةإليوتؤدى فكرة الفئات كأساس لفئة فرعية واحدة أو أكثر تسمى الفئةOOPفئة
ويمكن تعريف فئات أخرى تتشارك،(Base class) لقاعدة ا يف خصائصهاض خصائصها مع الفئة القاعدة ولكنها تفي
; Derived) تسمى هذه الفئات المشتقة ،الذاتية أيضاclasses).
: Reusability قابلية إعادة االستعمال لكيبعد كتابة الفئة يمكن توزيعها على المبرمجين
برامجهم ، يسمى هذا األمر قابلية إعادةفييستعملوها ;Reusabilityاالستعمال ; هاما ويزود مفهوم الوراثة ملحقا
حيث يستطيع المبرمج أخذ فئةاالستعمال فكرة إعادة إلي; ومن دون تغييرها يضيف ميزات وقدرات موجودة أصال
فئة جديدة من الفئةاشتقاق وذلك من خالل إليهاجديدةالقديمة.
إنشاء أنواع بيانات جديدة:- من أهم فوائد الكائنات أنها تعطى المبرمج وسيلة
كاألرقام المركبة أو اإلحداثيات،إلنشاء أنواع بيانات جديدة بيانات قدال أنواع أي نوع من ثنائية األبعاد أو التواريخ أو
استعمالها.إلي يحتاج المبرمج : د تعدد األشكال والتحميل الزائ
Polymorphism and overloading أساليبفي الداالت والعوامل استعماليسمى
; لما يتم تعدد األشكال. اله ب علياستعمالهامختلفة وفقا ، إمكانية إنشاء أنواع بيانات جديدة فقط++Cتضيف اللغة
; للمبرمج القدرة على العمل على أنواع بل وتتيح أيضا التيالبيانات الجديدة تلك باستعمال نفس العوامل
4
+ أو = ويقال عندها أنه تمكـتستخدمها األنواع األساسية تحميل هذه العوامل بشكل زائد لتعمل مع األنواع الجديدة.
; على الشاشة:- سنبدأ بكتابة برنامج يعرض نصا
//Program 1-1://This program will display a message on the screen.#include<iostream.h>main ) ({ cout <<''welcome to C++ !\n'';return 0; }
الخرج من البرنامج:
welcome to C++ !
Comments التعليقات:// Program 1-1: //This program will display a message on the screen.
يبدأ هذا السطر من البرنامج بالشرطة المزدوجة )//( ،(comment)لة على أن بقية السطر عبارة عن تعليق الدا
شخصأيتضاف التعليقات إلى البرامج لتساعد المبرمج أو يفعلهالذيآخر قد يحتاج إلى قراءة البرنامج على فهم ما
لغةفيالبرنامج، لذا من المستحسن أن يبدأ كل برنامج C ++ من أجله كتب البرنامج.الذي بتعليق يوضح الغرض
5
++Cكيفية كتابة برنامج بـ .12
يقوم الحاسوب بتنفيذ البرنامج ويعود سريعاb للمحررIDE.
من اآلن فصاعداb، إذا أردت تثبت المخرجات علىالشاشة عليك إضافة التالي إلى البرنامج:
#include <conio.h>في أول البرنامج، وإضافة العبارة:
getch) (.return 0في السطر الذي يسبق العبارة
تستخدم الشرطة المزدوجة )//( إذا كان التعليق يمتد. single-line commentلسطر واحد فقط
هنالك نوع آخر من التعليقات يتيح لنا كتابة تعليقات ، نستطيع كتابة multi-line commentsتمتد إلى عدة أسطر
التعليق السابق على الصورة:/* Program 1-1: This program will display a message on the
screen */
. نجد أن نهاية*/التعليق وينهيه الرمز / *يبدأ الرمز السطر ال تعنى انتهاء التعليق لذا يمكننا كتابة ما نشاء من
.*/أسطر التعليقات قبل االنتهاء بالرمز
6
:- ( Preprocessor Directive ) المهيئ مرشدات #include<iostream.h>
،Preprocessor directiveمرشد المهيئ يسمى هذا ب وهو عبارة عن تعليمة للمصرف أن يدرج كل النص الموجود
وهو ملف يجبالبرنامج، في iostream.h الملففي برنامج يحتوى على عبارات تطبع بيانات علىأيتضمينه مع
الشاشة أو تستقبل بيانات من لوحة المفاتيح. ، وهنالك(header file) ملف ترويسة iostreamيسمى
; إذا كنا نستعمل الكثير من ملفات الترويسة األخرى، فمثال نحتاج إلى) (cos و) (sinفي برنامجنا داالت رياضية كـ
، وإذا كنا نتعامل معmath.hشمل ملف ترويسة يدعى ; هنالكstring.hسالسل األحرف سنحتاج للملف . وعموما
عدد كبير من ملفات الترويسات التي يجب تضمينها على حسب طبيعة البرنامج ، تعتبر ملفات الترويسات جزء مهم
وسنحتاج إلى شمل الملف++Cمن برامج لغة iostream.hلتشغيل أي برنامج يقوم بعمليات إدخال
وإخراج. :- main الدالة
main) ( ،) (main من دالة تدعي ++Cيبدأ تشغيل أي برنامج
وهي دالة مستقلة ينقل نظام التشغيل التحكم إليها. وهي.++C برنامج في أساسيجزء
عبارةهي main تشير إلى أن mainاألقواس بعد على أكثر من دالة++Cعن دالة. قد يحتوى برنامج
. يحتوى البرنامج السابق علىmain هيإحداهما بالضرورة دالة واحدة.
حتى لو لم تكن mainيبدأ تنفيذ البرنامج من الدالة main سياق البرنامج. يتم حصر جسم الدالة في األولى هي
. { } بأقواس حاصرةالخرج إلى الشاشة:-
cout<<'' welcome to C++ !\n ''; تجبر الحاسوب أن يظهر(statement)هذه العبارة
.'' '' االقتباس عالمتيعلى الشاشة النص المحصور بين . سلسليويسمى هذا النص ثابت
بفاصلة++C برنامج في كل عبارة تنتهييجب أن .(semi colon) ; منقوطة
7
في يمثل كائن C out ـ يلفظ كوالذي cout االسمC++ يسمى بعاملوالذي << مقترن مع الشاشة والعامل
علىالتي يجبر على إرسال األشياء Put to operatorالوضع . يظهر على يسارهشئ أييمينه إلى
.cout يوضح الخرج بواسطة 1-1 الشكل
مثال:
//Program 1-2: Output#include <iostream.h>main ) (
{cout << 7 << " is an integer.\n";cout << 'a' << "is a character.\n";
}
الخرج من البرنامج:
7 is an integer.a is a character
من خرج البرنامج يتضح لنا اآلتي: - يتم حصر النص المطلوب ظهوره على الشاشة بين1
". is an integerعالمتي اقتباس" <<- تتم كتابة الثوابت الرقمية بدون عالمتي اقتباس 27. - يتم حصر حرف واحد مطلوب ظهوره على الشاشة3
.’a<<’بعالمة اقتباس فردية ; باالنتقال إلى سطرBasicتقوم بعض اللغات كـ مثال
; في نهاية كل عبارة خرج ، لكن ال تفعل++Cجديد تلقائيا ذلك كما أن العبارات المختلفة والموضوعة في أسطر
مختلفة ال تؤدي إلى ذلك .
8
متغير
>>octu
الشاشة
الخرج (1-1)شكل tuocبواسطة
;، coutال ينشئ الكائن ; جديدة تلقائيا أسطراوالمخرجات في البرنامج التالي توضح ذلك:-
//Program 1-3:This program displays output on the screen#include<iostream.h>main ) ({ cout<<10; cout<<20<<30; return 0;}
تظهر الخرج:-
102030
حيث يلتصق كل الخرج ببعضه البعض ، لذا من الجيد للتحكم بطريقة تنسيق++Cأن يكون لدينا طرق في
. (Escape Sequences)الخرج والتي منها تتابعات الهروب : ( Escape Sequences ) تتابعات الهروب
على الشاشة ، \ تسمىn\نالحظ أنه لم تتم طباعة Escape)حرف هروب أو (Back slash)الشرطة الخلفية
character) يليها تتابع هروب.الذي والحرف هي وتسمى إلى سطر جديد حيث يجبراالنتقال يعنى n\تتابع الهروب ، اآلن إليكالتالي إلى بداية السطر االنتقالالمؤشر على
بعض تتابعات الهروب الشائعة:-الوصف تتابع الهروب
\nسطر جديد.\tأفقية. مسافة\b حرف التراجعback space.
.لطباعة شرطة خلفية\\\rحرف اإلرجاع، يجبر المؤشر
إلىاالنتقالعلى . بداية هذا السطر
اقتباسلطباعة عالمة \'' :- return 0 العبــارة
9
في نهاية الدالة; return 0 تكتب العبارة main ) ( تشير إلى أن البرنامج انتهى نهاية0. القيمة
صحيحة وسيبدو لنا سبب تضمين هذه العبارة واضحا عندما بالتفصيل. ++Cنتعرف على الدوال في
:- ++ C مثال آخر لبرنامج ; لبرنامج يستقبل رقمين من المستخدم إليك اآلن مثاال
ويجمعهما ويعرض ناتج الجمع:-
// Program 1-4: Addition program#include<iostream.h>#include<conio.h>main ) ( {
int integer1, integer2, sum;cout <<"Enter first integer\n";cin >> integer1;cout <<"Enter second integer\n";cin >> integer2;sum= integer1+integer2;cout <<"sum="<<sum<<endl;getch)(;
return 0; }
Enter first integer7Enter second integer3sum= 10
10
11
حدد ما إذا كانت العبارات اآلتية صحيحة أم.1خطأ:
التعليقات تجبر الحاسوب على طباعة النص الذي يلي // على الشاشة عند تنفيذ البرنامج.
تتابع الهروب\nيجبر المؤشر على االنتقال إلى سطر جديد.
برنامجC++والذي يقوم بطباعة ثالث أسطر على الشاشة يجب أن يحتوى على
.coutثالث عبارات تستعمل ما هو الخرج من العبارة اآلتية:.2
cout << “\n **\n ***\n ****\n”;
،++C في أساسية بيانات هنالك سبعة أنواع; كاملة )أعداد واحد منها يمثل األحرف وثالثة تمثل أرقاما
; حقيقية. الجدول يلخصاآلتيصحيحة( وثالثة تمثل أرقاما.هذه األنواع
عن القيمأمثلةالمخزنة
يستعمللتخزين
النوعاسم
''a'' أحرف char
222 أرقام صحيحةقصيرة
short
153,406 أرقام صحيحةعادية الحجم
int
123,456,789 أرقام صحيحةطويلة
long
3,7 أرقام حقيقيةقصيرة
float
7,533,039,395 أرقام حقيقيةمزدوجة
double
9,176,321,236,01202,6
أرقام حقيقيةضخمة
long double
:- char / األحرف1 العبارة:-charيتم تخزين األحرف في متغيرات من النوع
char ch; . لتخزينchتنشئ مساحة من الذاكرة لحرف وتسميه
حرف ما في هذا المتغير نكتب ch=’z’
; تكون األحرف الثابتة كـ محصورة بعالمة’b’ و’a‘ودائمااقتباس فردية.
لتخزين أرقامcharيمكن استعمال المتغيرات من النوع ; يمكننا كتابة:- ; من أحرف ، فمثال كاملة بدال
ch=2;
لكن نطاق القيم الرقمية التي يمكن تخزينها في يتراوح بين charالنوع
12
C++ أنواع البيانات األساسية في لغة .13
لذا فإن هذه الطريقة تعمل مع األرقام127 إلى 128–الصغيرة فقط.
/ األعداد الصحيحة:2; كاملة أي قيم يمكن تمثل األعداد الصحيحة أرقاما
; ، وال تعدادها ، كعدد أشخاص أو أيام أو عدد صفحات مثال; ذات نقطة عشرية يمكن أن تكون األعداد الصحيحة أرقاما
ولكنها يمكن أن تكون سالبة. ++Cهنالك ثالثة أنواع من األعداد الصحيحة في
:short ،قصير int ،عدد صحيح longطويل وهي تحتل مساحات مختلفة في الذاكرة. الجدول التالي يبين هذه
األنواع والمساحة التي تأخذها في الذاكرة ونطاق األرقامالتي يمكن أن تأخذها:
اسمالنوع
النطاقالحجم
char1byte-128 127 إلىshort2byte-32,768 32,767 إلى
int مثلshort 16 في أنظمةbit ومثل long 32bitفي أنظمة
long4byte-2,147,483,648إلى 2,147,483,647
:- (Unsigned)/ األعداد الصحيحة غير المعلمة3كل األعداد الصحيحة لها إصدارات غير معلمة )
unsigned)،ال تستطيع المتغيرات التي ليس لها عالمة تخزين قيم سالبة . ونجد أن نطاق قيمها الموجبة يساوى ضعف مثيالتها التي لها عالمة، الجدول
التالي يبين هذا:-
الحجاسم النوعم
النطاق
unsigned char
1byte
255 إلى 0
unsigned short
2byte
65,535 إلى 0
unsigned int
16bit في أنظمة short unsignedمثل32bitفي أنظمة long unsignedومثل
unsigned long
4byte
4,294.967.295 إلى 0
13
:(Float)/ األرقام العائمة 4 يتم استعمال األرقام العائمة لتمثيل قيم يمكن
قياسها كاألطوال أو األوزان. ويتم تمثيل األرقام العائمة عادة برقم كامل على اليسار مع نقطة عشرية وكسر على
اليمين. هنالك ثالثة أنواع من األرقام العائمة في أنظمة
التشغيل الشائعة االستعمال. وأشهر نوع أرقام عائمة هو ++C والذي يتم استعماله لمعظم داالت doubleالنوع
.double ذاكرة أقل من النوع floatالرياضية. يتطلب النوع الجدول التالي يوضح هذه األنواع والحجم الذي تأخذه في الذاكرة.
الحجماسم النوعfloat4byte
double8bytelong
double10byte
نحتاج لتخزين، ++C برنامج بلغة أيعند كتابة ذاكرة الحاسوب تحتفيالمعلومات الواردة للبرنامج
أنواع أنعناوين يطلق عليها أسماء المتغيرات، وبما المعلومات المراد تخزينها تكون عادة مختلفة مثل القيم
الصحيحة أو الرمزية فإننا نحتاج أن نعلمأوالحقيقية نريدالتي المتغيرات أنواع بداية البرنامج عن فيالمترجم
; :-استخدامها فمثال أسماءهي integer1 , ,integer2 sumالكلمات
( وهو أحدintلمتغيرات عبارة عن أعداد صحيحة)النوع .++C فيأنواع البيانات المتوفرة
البرنامجفي مكان أي في يمكن تعريف المتغيرات ، يمكن تعريف المتغيراتاستعمالهالكن يجب تعريفها قبل
سطر واحد.في إلى نفس النوع تنتمي التي : تسمية المتغير
التيسم ونوع البيانات اال يتم تعريف المتغير بذكر سلسلة تحتوى علىأييمكن أن يحملها هذا المتغير من
; Digits أو أرقام Lettersأحرف ; تحتيا Under أو خطاscore )_(، المتغير برقم. ومن الجديراسم على أن ال يبدأ
تفرق بين الحروف األبجدية الصغيرة++Cبالذكر أن لغة
14
تعريف المتغيرات .14
; ،والكبيرة تعامل ,integer1 Integer1 األسماء فمثالكمتغيرات مختلفة.
الدخل من لوحة المفاتيح:-cin>>integer1 هذه العبارة تخزن الرقم الذي يكتبه المستخدم من
يمثل الكائن. integer1 لوحة المفاتيح في متغير يدعيcin ـ يلفظ ك-والذي C in-ويأخذ عامل، لوحة المفاتيح
األشياء الموضوعة على يساره)>>( get fromالحصول المتغير الموجود على يمينه، عند تنفيذ هذهفيويضعها
; من النوع العبارة ينتظر البرنامج أن يكتب المستخدم رقماinteger ويضغط على مفتاح Enter التي ، يتم تعيين القيمة
.integer1أدخلها المستخدم إلى المتغير يمكن استعمال عامل الحصول عدة مرات في نفس
العبارة:cin >> integer1>>integer2
، أو مفتاح المسافة Enterيضغط المستخدم هنا Space أو مفتاح ،Tabبعد كل قيمة، قبل أن يكتب القيمة
التالية، ولكنه من األفضل عادة إدخال قيمة واحدة في كلمرة لتجنب الخطأ.
.cin يوضح الدخل بواسطة (1-2)الشكل
:- endl المناور :العبارة
cout<<''sum= ''<<sum<<endl; بقيمة =sumتطبع النص أننا ، نالحظ sum متبوعا
إلىلالنتقال ++Cفي وهو وسيلة أخرى endlاستخدمنا ; endl وmanipulator ويسمى مناور،سطر جديد لـاختصارا
end line ،كما يعمل تتابع الهروب ; .n\وهو يعمل تماما
15
صحيحة تقوم باآلتي:++Cأكتب عبارة .1 تعريف المتغيراتx ، y، z و resultلتكون
.intمن النوع الطلب من المستخدم إدخال ثالثة أرقام
صحيحة. حدد ما إذا كانت العبارات اآلتية صحيحة أم.2
خطأ:يجب اإلعالن عن المتغيرات قبل استعمالها في
البرنامج.
ic>>متغيرn
لوحةالمفاتيح
يوضح الدخل (1-2)شكل ++Cبواسطة
إلي integer1لقد استعملنا عامل الجمع )+( لجمع integer2 ، تتضمنC ++العوامل الحسابية األربعة الجدولفي باإلضافة إلى عامل خامس كما مبين االعتيادية
:التالي
التعبير++C في
التعبيرالجبري
الوظيفة العامل
B+h B+h جمع +B-h B-h طرح -B*h Bh ضرب *B/h B/h, قسمة /
B%h B mod h الباقي %
; مألوفة لدينا، العوامل األربعة األولى تنجز أعماال; المعامل الباقيأما عامل يتم، modulus % المسمى أيضا القسمة لعدد صحيح على عدد آخر،باقي لحساب استعماله
. تسمى هذه العوامل2 يساوى 3%20 فالتعبير لكلذمتين.قيالحسابية بالعوامل الثنائية ألنها تعمل على
رياضي تعبير في أكثر من عامل استعماليمكن ; التعبير: واحد، فمثال
C=)f-32(*5/9; )يحول درجة الحرارة من مئوية إلى فهرنهايت.
; بالرغم منلكي األقواس استعملت يتم تنفيذ الطرح أوال إلى Precedence أولويةأولويته المتدنية، يشير المصطلح
/ لهما أولوية أعلى من و *ترتيب تنفيذ العوامل، العامالن ; بعد أن نتعرف على بقية عوامل.(+و- وهذا ما سنراه الحقا
C++.
وتؤدى إلى نتيجة،تقارن العوامل العالئقية قيمتين; لما إذا كانت المقارنة صحيح/خطأ. هنالك صحيح/خطأ وفقا
الجدول أدناه:فيستة عوامل عالئقية مبينة مثال المعنى الرمز
a==b يساوى ==
16
lanoitaleR )العوامل العالئقية srotarepO)
.16
) (srotarepO htaMالعوامل الحسابية .15
a!=b يساوى ال =!a>b أكبر من <a<b أصغر من >
a>=b أكبر من أو يساوى =<a<=b أصغر من أو يساوى =>
أو عمود المثال صحيحة فيتكون التعابير المبينة .b و aخطأ وفقا لقيم المتغيرين
; أن :فلنفرض مثالa 9 يساوى وb 10 يساوى .
. خطأa==bالتعبير ،a<=b و a<b صحيح وكذلك التعبيرينa!=bالتعبير
. خطأ.a>=b و a>b والتعبيرين
17
تبدأ التعليقات فيC++والتي تتكون من سطر واحد بشرطة مزدوجة )//(.
تبدأ التعليقات فيC++والتي تمتد لعدة أسطر /*. وتنتهي بالرمز*/ بالرمز
السطر#include<iostream.h<يسمى "مرشد المهيئ" وهو عبارة عن تعليمة للمصرف أن يضمن
في البرنامج والذي يجب تضمينه فيiostream.hالملف أي برنامج يقوم بعمليات إدخال وإخراج.
يبدأ تنفيذ برنامجC++ من الدالة main)(. المتغيرات فيC++يجب اإلعالن عنها قبل
استعمالها. يتم تعريف المتغيرات فيC++بذكر اسمها ونوع
بياناتها وتكون االسم من أي سلسلة تحتوى على أحرف ; ; تحتيا على أن ال يبدأ اسم المتغير) _ (أو أرقام أو خطا
برقم.C++حساسة تجاه األحرف ونعنى بذلك أنها تفرق
) والكبيرة (small)بين الحروف األبجدية الصغيرة capital).
يرتبط كائن الخرجcoutمع الشاشة وهو يستخدم في إخراج البيانات.
18
الملخص:
صحيحة تقوم باآلتي:++C-أكتب عبارة 1ما سيقوم بحساب حاصل ; توضيح أن برنامجا
ضرب ثالثة أرقام صحيحة..الطلب من المستخدم إدخال ثالثة أرقام صحيحةإدخال ثالثة أرقام عن طريق لوحة المفاتيح
.z و x، yوتخزين قيمها في المتغيرات حساب حاصل ضرب األرقام المخزنة في
.result وتعيين النتيجة للمتغير z و x، yالمتغيرات طباعة العبارة “The product is" :متبوعة
.resultبقيمة المتغير إرجاع قيمة من الدالةmainلتوضيح أن البرنامج
انتهى بنجاح.
- إستعمل العبارات في السؤال السابق لكتابة2 كامل يقوم بحساب حاصل ضرب++Cبرنامج بلغة
ثالثة أرقام صحيحة.
- حدد ما إذا كانت العبارات اآلتية صحيحة أم3خطأ:
نفس درجة%تمتلك العوامل الحسابية + ، - و أ.األولوية.
والذي يقوم بطباعة ثالث أسطر++Cبرنامج ب. على الشاشة يجب أن يحتوى على ثالث عبارات
.coutتستعمل
4bيستقبل من المستخدم عددا bأكتب برنامجا- مكوناb من خمسة أرقام ثم يقوم بطباعة األرقام
; إذا أدخل المستخدم المكونة للعدد تفصلها مسافة فمثال يكون الخرج من البرنامج 13456العدد
1 3 4 5 6
- ما هو نوع البيانات الذي ستستعمله على5 أعداد.4األرجح لتمثيل رقم موظف تسلسلي من
- أي من العبارات اآلتية تعطي المخرجات التالية:6
19
األسئلة
1 22 4
1- cout << “ 1\t2\t\n3\t4\n”;2- cout <<’1’ << ‘\t’ << ‘2’ << ‘\n’ <<’3’ <<’\t’
<<’4’ <<’\n’;3- cout << “1 \n 2\t 3\n 4\t”;4- cout <<1 << ‘\t’ << 2 << ‘\n’ <<3 <<’\t’
<<4 <<’\n’;
- أكتب جزء من برنامج يقوم بما يلي:7 ينشئ متغيرينnum و denomيمثالن البسط والمقام
في كسر..يطلب من المستخدم تزويد قيم البسط والمقام.يضع هذه القيم في متغيرات.تعرض الكسر مع شرطة )/( بين الرقمين
قد يبدو الخرج كاآلتي:Enter the numerator: 2Enter the denominator: 3Fraction = 2/3
20
الوحدة الثانية2I(serutcurtS lortnoC(- (I)بنيات التحكم
.20
: الوحدة هذه بنهايةاإلختبار تعبير استعمال من ستتمكن if. اإلختبار تعبير استعمال من ستتمكن if… else.االختبار تعبير استعمال من ستتمكن switch.
في ورودها تسلسل حسب العبارات تنفيذ يتم عادة Sequential) يالتتابع بالتنفيذ هذا ويسمى البرنامج
Execution) .عبارات لبعض سنتعرض لكننا C++ والتي في التالية تكون ال قد أخرى لعبارة ينتقل التنفيذ تجعل
Transfer of التحكم نقلب هذا ويسمى ،البرنامج تسلسلcontrol.
قسمين: بنيات إلى++C في التحكم بنيات تنقسم لتوضيحها. والنوع الوحدة هذه وسنفرد الشرطية التحكم الوحدة سنفرد والتي التكرارية التحكم بنيات وهو الثانيعنها. للحديث التالية
العبارة بواسطة هي ++C في قرار التخاذ طريقة أسهلif.
مثال:-//Program 2-1:#include <iostream.h>main ) ({int num1 , num2;cout << " Enter two integers, and I will tell you\n" <<" the relation ships they satisfy: ";cin >> num1>> num2;if )num1== num2( cout << num1 << " is equal to " << num2 << endl;if )num1!= num2( cout << num1 << " is not equal to " << num2 << endl;if )num1< num2( cout << num1 << " is less than " << num2 << endl;
21
fi العبـارة .2.21
بنيات التحكم الشرطية2.2
مقدمة 1.2
if )num1> num2( cout << num1 << " is greater than " << num2 << endl;if )num1<= num2( cout << num1 << " is less than or equal to " << num2 << endl;if )num1>= num2( cout << num1 << " is greater than or equal to " << num2
<< endl;return 0;}
األرقام أدخل قد المستخدم أن بافتراض البرنامج من الخرجnum1 =3 ، num2= 7.
Enter two integers , and I will tell youThe relation ships they satisfy: 3 7
3 is not equal to 73 is less than 73 is less than or equal to 7
تعبير يليها ،if األساسية الكلمة من if العبارة تتألف إما ذلك يلي الذي القرار جسم ويتألف ،قوسين بين اختبار
أقواس تحيطها عبارات عدة من أو ،واحدة عبارة من{ } حاصرة
.if العبارة عمل طريقة ( يبين2-1الشكل)
22
إنهاء
تعبير إختبار
fiجسم
صحيح
خطأ
( طريقة عمل 2-1شكل )fiالعبارة
الشرط كان إذا شئ يحدث البسيطة if العبارة في،; .اإلطالق على شئ يحدث ال كذلك يكن لم إذا لكن صحيحا
كان إذا الحالتين في شئ حدوث نريد أننا لنفترض لكن; الشرط ذلك لتحقيق كذلك، يكن لم إذا وآخر صحيحا if... else العبارة نستخدم
مثال:-
//Program 2-2:#include <iostream.h>main ) ({int grade ;cout << " Enter the grade";cin >>grade;if)grade>= 50(cout<<"pass" <<endl;elsecout <<"fail"<<endl;return 0; }
أدخل قد المستخدم أن بافتراض البرنامج من الخرجgrade = 90
Enter the grade 90Pass
; عدة منelse أوif جسم يتألف أن يمكن هنا أيضا طريقة ( يبين2-2 الشكل)حاصرة. أقواس تحيطها عبارات
.if…else العبارة عمل
وذلك السابق المثال عن للتعبير أخرى طريقة هنالكالمشروط: بالعامل يسمى ما باستخدام
cout<<)grade>= 50 ? ''pass'' :''fail''( << endl; ++C في الوحيد العامل هو المشروط العامل
عالمة رمزين من ويتألف قيم ثالثة على يعمل الذي. ونقطتين استفهام
23
esle…fi .2.2العبـارة 2
; ثم االستفهام، عالمة ثم االختبار، تعبير يأتي أوال; االختبار تعبير كان إذا.نقطتان تفصلهما قيمتان ينتج صحيحا تعبير كان وإذا النقطتين قبل الموجودة القيمة بأكمله التعبير
النقطتين. تلي التي القيمة بأكمله التعبير ينتج خطأ االختبار Absolute) المطلقة القيمة يحسب التالي مثالال
value)من أقل العدد كان إذا العدد سالب تساوي وهي الصفر. من أكبر العدد كان إذا العدد موجب وتساوي الصفر
Abs_value =)n<0( ? -n:n; الحالة في n و0 من أقل n كان إذا n- هي النتيجة
األخرى.
24
fiجسم
إنهاء
تعبير اختبار
esleجسم
خطأ
صحيح
عمل ( طريقة2-2) شكلif…else
؟ اآلتي في الخطأ هو ماif )gender==1( cout<<women <<endl;else cout <<man<<endl;
المتداخلة:- if ... else العبارات بعضها ضمن if ......else العبارات وضع يمكن
ذلك: يوضح التالي البرنامج ، البعض//Program 2-3:#include <iostream.h>main ) ({int grade;cout <<"Enter the grade:" ;cin >> grade;if)grade>= 75(cout<<'A'<< endl;elseif)grade>= 65(cout<<'B'<< endl;elseif)grade>= 55(cout<<'C'<< endl;elseif)grade>= 40(cout<<'D'<< endl;elsecout<<"fail"<<endl;return 0;}
وليسelse الجسم في المتداخلة العبارات تنتهي العبارات نضع عندما مشكلة تحدث أن يمكن ،if الجسم في
if ……elseبعضها ضمن ; من المفروض البعض. فمثال عمر يكون عندما infant الكلمة تعرض أن التالية العبارات:-2 يساوى أو أقل الشخص
if )age >2(if )age<18(cout <<"\n child”;elsecout <<"\n infant";
كلما infant الكلمة ستظهر ، يحدث لن هنا ولكن
يتبع else الجزء ألن وذلك18 يساوى أو أكبر العمر كان بها. لذا خاص else جزء لها ليس والتي إليهif عبارة أقرب
25
قبله موجودة غير if لعبارة تابع else جزء نريد كنا إذا بأقواس بينهما الموجودة if العبارة حصر علينا مباشرة. حاصرة
if )age >2(}if )age<18(
cout <<"\n child;” {else
cout <<"\n infant;"
26
:-التالي العام الشكل++ Cفي switch جملة تأخذSwitch )Variable name(}case constant1 : statement1; break;case constant2 : statement2; break;..case constant n : statement n; break;default : last statement;
{ switch األساسية الكلمة منswitch العبارة تتألف
حاصرة أقواس بين جسمها ثم ،قوسين بين متغير اسم يليها أقسام نحو البرنامج وتوجه المتغيرswitch العبارة تفحص ،
; مختلفة المتغير. ذلك لقيم وفقا;switch العبارة جسم يتضمن الوسوم من عددا
الكلمة من الوسوم هذه تتألف.نقطتان تليها أسماء يوهنقطتين. ثم ثابت ثم case األساسية
ة مساويswitch العبارة متغير قيمة تكون عندما إلى التنفيذ ينتقلcase وسوم أحد في المذكور للثابت
إلى break العبارة وتؤدى الوسم ذلك تلي التي العبارات متغير قيمة تتطابق لم إذاو ،switch العبارة بقية تنفيذ منع
الوسم إلى التنفيذ ينتقل وسم أي معswitch العبارة .default االفتراضي
) العلة حروف عدد لحساب برنامج بكتابة سنقومvowels letters)وهي (a, e, i, u, o)من مدخل نص في
فإذا المدخل الحرف بفحص البرنامج . يقوم المفاتيح لوحة تمهيده تم والذيacounter إلى1 إضافة تتمa الحرف كان إلى1 إضافة فتتمe المدخل الحرف كان إذا . أما0 عند
ecounterلـ بالنسبة وهكذا uو iو o، الحرف يكن لم إذا يقوم والذي االفتراضي الوسم تنفيذ يتم علة حرف المدخل.OtherLettersCounter لـ1 بإضافة
.switch العبارة عمل طريقة بتوضيح ( يقوم2-3) الشكل
27
hctiws .2.2العبـارة 3
//Program 2-4: #include <iostream.h>enum vowels{a='a',u='u',i='i',o='o',e='e'};main) ({char ch ;int acounter=0,ecounter=0,icounter=0;
28
خطأ
خطأ
إنهاء
الجسم االفتراضي
جسم الوسم الثالث
hctiwsمتغير يساوى ثابت الوسم الثالث
جسم الوسم الثانى hctiwsمتغير
يساوى ثابت الوسم الثانى
صحيح
صحيح
جسم الوسم األول
hctiwsمتغير يساوى ثابت الوسم األول
صحيح
خطأ
– طريقة عمل (2-3)شكل hctiwsالعبارة
int ucounter=0,ocounter=0,otherletterscounter=0;while)cin>>ch(switch)ch( {case a:++acounter;break;case e:++ecounter;break;case i :++icounter;break;case o:++ocounter;break;case u:++ucounter;break;default:++ otherletterscounter;};cout<<endl;cout<<endl;cout<<endl;cout <<"acounter: \t"<<acounter<<" \n";cout<< "ecounter: \t"<<ecounter<<" \n";cout<< "icounter: \t"<<icounter<<" \n";cout<< "ocounter: \t"<<ocounter<<" \n";cout<< "ucounter: \t"<<ucounter<<" \n";cout<<"otherletterscounter: \t"<<otherletterscounter <<" \n";return 0;}
" المدخل النص أن بافتراض البرنامج من الخرجyouareverypunctional"
29
acounter: 2ecounter: 2icounter: 1ocounter: 2ucounter: 2OtherLettersCounter: 11
30
العبارة تأخذ if التالي: العام الشكلif )Condition( statement;
Statement تأخذ عبارة من أكثر من يتكونif جسم كان إذاالتالي: الشكل
{ Statement 1; Statement 2; . . Statement n}
العبارة تستعمل ifلغة في C++أو عبارة لتنفيذ ; يليها الذي الشرط كان إذا عبارات عدة . صحيحا
العبارة تأخذ if…elseالتالي: العام الشكلif)Condition( Statement 1; elseStatement 2;
فإننا عبارة من أكثر من يتكون else و if جسم كان إذا{ }. حاصرة بأقواس العبارات تلك نحيط
العبارة تستعمل if …elseعدة أو عبارة لتنفيذ ;if العبارة يلي الذي الشرط كان إذا عبارات صحيحا
يكن لم إذا عبارات عدة أو أخرى عبارة وتنفيذ ،كذلك.
العامل المشروط هو وسيلة للتعبير عن العبارة if…else.
العبارة switch :تأخذ الشكل العام التاليswitch )Variable name({ case constant 1: statement 1;
break;
case constant n: statement n; break;
default: last statement;}
31
الملخص:
.
.
.
التالي: تؤدى++ C عبارة / أكتب1صحيح متغير قيمة إدخال xباستعمال cinو <<. صحيح متغير قيمة إدخال yباستعمال cin و <<.صحيح متغير قيمة تمهيد i1 عند.صحيح متغير قيمة تمهيد power1 عند.المتغير قيمة ضرب x المتغير في powerوتعيد
.power للمتغير النتيجةالمتغير قيمة زيادة y1 بـ.المتغير قيمة كانت إذا ما اختبار yتساوي أو من أقل
x.المتغير قيمة طباعة power.
مخرجات هي ماy = 11 وx = 9 أن / بافتراض2البرنامج: من التالي الجزء
if ) x < 10(if ) y > 10(
cout << “* * * * *” << endl;elsecout << “# # # # #” << endl;cout << “$ $ $ $ $” << endl;
32
األسئلة
الوحدة الثالثةII(serutcurtS lortnoC(( - IIبنيات التحكم)
.30
33
األهــداف:بنهاية هذه الوحدة:
ستتمكن من استعمال عوامل التزايدIncrement Logical والعوامل المنطقية Decrementوالتناقص operators .
ستتمكن من استعمال حلقات التكرار while وdoو for.لتكرار تنفيذ عبارات في برنامجك
ستتمكن من استعمال العبارتينbreak و continue
يمكن إعادةالحسابيباستعمال عوامل التعين كتابة تعبير مثل:
x=x+2على النحو
x+=2 =+ القيمة الموجودةالحسابييأخذ عامل التعين
على يمينه ويضيفها إلى المتغير الموجود على يساره. هنالك لكل من العوامل الحسابية:-حسابيتعين
a+= b a= a+ b
a-= b a= a- b
a*= b a= a* b
a/= b a= a/ b
a%= b a= a% b مثال:
//Program 3-1: #include<iostream.h>main ) ({int n;cin >> n;cout<< “ n after adding 2 = “ << a+= 2 <<endl;cout<< “ n after a subtracting 2 = “ << a-= 2 <<endl;cout<< “ n after dividing by 2 = “ << a/= 2 <<endl;cout<< “ n after multiplying by 2 = “ << a*= 2 <<endl;cout<< “ n mod 2 = “ << a %= 2 <<endl;return 0;}
n =10الخرج من البرنامج إذا أدخلنا
34
1.3عوامل التعيين الحسابي
10n after adding 2 = 12 n after a subtracting 2 = 8n after dividing by 2 = 5n after multiplying by 2 = 20n mod 2 = 0
; حاجة أو طرح1 البرمجة إلى زيادة فيهناك دائما تتضمن عاملين++C هذه الحاالت شائعة لدرجة أن . 1
خاصين ينفذان هذه المهمة، يقوم عامل التناقص )--( بطرح إليه ، المثال1 من المتغير ويضيف عامل التزايد )++(1
:-االستعمال يبين طريقة اآلتي ++a a++
ويمكن كتابته بصورة،a إلى 1معناه إضافة وبالطريقة نفسها يمكن إنقاصa=a+1مكافئة على النحو
.a=a-1 وهو يكافئ --a أو a-- على النحوa من قيمة 1 ++ومما يجب التنبيه إليه هنا أن هنالك فرق بين
a أو a++ إلى 1 فعلى الرغم من كليهما يجمع aإال أنه a قيمة باستعمال تستخرج قيمة التعبير a++ استعمالعند
; على .--a وa--الحالية قبل زيادتها وينطبق هذا أيضا//Program 3-2:#include<iostream.h>main ) ({int c;c = 5;cout << c << endl;cout << c++ <<endl;cout << c <<endl;c=5;cout << c << endl << endl;cout << ++c << endl;cout << c << endl;return 0;//Continued}
35
2.3عوامل التزايد والتناقص
الخرج من البرنامج:
556
566
يمكن العمل على القيم صحيح/خطأ بواسطة ++C فيالعوامل المنطقية ، هنالك ثالثة عوامل منطقية
الجدول أدناه:-في كما موضح Not,Or,And هيمثال معناه المنطقيالعامل
x>0 &&x<10 (and))و( &&x= = 0|| x=
= 1(or)( أو) ||
!x (not) )نفى( !; فقط إذا كان التعبيرين andيكون التعبير صحيحا
العامل && صحيحين بينما يؤدىجانبيالموجودان على التعبيرين أو كليهماأحد إلى نتيجة صحيحة إذا كان orالعامل
;. العامل يليه لذاالذي )!( يبطل تأثير المتغير notصحيحا x خطأ وخطأ إذا كان x صحيح إذا كان المتغير x!التعبير .; صحيحا
:- ( Operator Precedence ) أولوية العوامل يتم تنفيذ عمليات الضرب والقسمة في التعابير الرياضية قبل عمليات الجمع والطرح . في التعبير التالي
: ; مثال10*10+2*3
وبعدها يتم جمع3*2 ثم يتم ضرب 10*10يتم ضرب نتيجتي الضرب مما يؤدى إلى القيمة
100+6=106. له أولوية*يتم تنفيذ عمليات الضرب قبل الجمع ألن العامل
.+أعلى من أولوية العامل نجد أن أولوية العوامل مهمة في التعابير الرياضية العادية
; عند استعمال عوامل المختلفة ،++ Cكما أنها مهمة أيضا
36
العوامل المنطقية3.3
من++Cالجدول التالي يبين ترتيب أولويات العوامل في األعلى إلى األدنى.
األولويةأنواع العواملالعواملأعلىمضاعفة% , / , *
جمعية- , +<, > ,<= ,>= ,
==,!= عالئقية
منطقية!&& || أدنى تعيين=
; من أساليب التكرار )حلقات(++Cتوفر عددا قدر ما تدعوأجزاء من البرنامج تستخدم لتكرار التي
الحاجة، لتحديد عدد مرات تكرار الحلقة تفحص كل حلقاتC++ ما إذا كان تعبير ما يساوى صحيح (true ) أو خطأ (
false)يبلغها هذا ما إذا كان عليها التكرار مرة إضافية أخرى .; أو التوقف فورا
:-+ +C فيهنالك ثالثة أنواع من الحلقات
جزء من البرنامج تكرار فعل whileتتيح الحلقة إلى أن يتغير شرط ما .
;مثلف :-اwhile )n<100(n=n*2
إلىn مضاعفة المتغيرفيستستمر هذه الحلقة . تتكون عندها تتوقف100 من كبر أn قيمة تصبح أن
بيناختبار يليها تعبير whileالحلقة من الكلمة األساسية ; بين أقواس حاصرة {أقواس ويكون جسم الحلقة محصورا
( يبين3-1 الشكل ) إال إذا كان يتألف من عبارة واحدة.} :-whileطريقة عمل الحلقة
37
بنيات التحكم التكرارية4.3
( SPOOL الحلقات) .4.31
elihwالحلقة .4.312
تعبير االختبار
جسم الحلقة
إنهاء
صحيح
خطأ
( – طريقة عمل 3-1شكل )elihwالحلقة
مما يجدر التنويه إليه هنا أنه يتم فحص تعبير االختبار قبل تنفيذ جسم الحلقة، وعليه لن يتم تنفيذ جسم; إذا كان الشرط خطأ عند دخول الحلقة وعليه الحلقة أبدا
في المثال السابق يجب تمهيده عند قيمة أقلnالمتغير .100من
مثال :
//Program 3-3: #include<iostream.h>main ) ({int counter, grade, total ,average;total = 0;counter = 1;while )counter <= 0( {cout<< “ Enter grade : “;cin >>grade;total = total + grade;counter = counter + 1;}cout<<endl;average = total /10;//Continuedcout << “ Class average is: “ << average <<endl;return 0;
الخرج من البرنامج:
Enter grade: 75 65 50 89 71 54 86 79 81 90
Class average is : 74
38
اآلتية: الحلقة في الخطأ هو ماwhile)c<5( { product *=c; ++c;
; تسمى doتعمل الحلقة …do…while) )غالبا بعد تنفيذ جسماالختبار أنها تفحص تعبير إال ،whileكالحلقة ; عندما نريد القيام بجزء من البرنامجالحلقة. وتستخدم أيضا
مرة واحدة على األقل..do( يبين كيفية عمل الحلقة 2-5الشكل)
يليها جسم do بالكلمة األساسية doتبدأ الحلقة while األساسية ثم الكلمة { }الحلقة بين أقواس حاصرة
بين أقواس ثم فاصلة منقوطة.اختبارثم تعبير مثال:-
.10 إلى 1البرنامج التالي يقوم بطباعة األعداد من
//Program 3-4: //using do repetition structure
#include<iostream.h< main) (
}int counter = 1;do
cout << counter; '' ''>> while )+ + counter <= 10(;
//Continuedreturn 0;
{
بطباعة مسافة خالية بين كل رقم<< “ “;coutتقوم واآلخر وعليه الخرج من البرنامج يكون كالتالي:
39
خطأ
جسم الحلقة
تعبير االختبار
صحيح
إنهاء
– طريقة عمل (3-2)شكل odالحلقة
odالحلقة .4.33
1 2 3 4 5 6 7 8 9 10
40
عدد مراتwhile و doعادة ال تعرف الحلقات يكون عدد مرات تنفيذ for الحلقة في لكن .تكرار الحلقة
; عادة بدايتها.فيالحلقة مذكورا counterالمتغير قيم يقوم بطباعة التاليالمثال
.10 إلى 1 من
//Program 3-5: //using the for repetition structure
#include<iostream.h<main) (
}for ) int counter = 1; counter<= 10; counter++(
cout << counter <<endl; return 0;
{
الخرج من البرنامج
12345678910
for الكلمة األساسية تلي التيتحتوى األقواس على ثالثة تعابير مختلفة تفصلها فاصلة منقوطة. تعمل هذه
أغلب األوقات على متغير يدعى متغيرفيالتعابير الثالثة المثال السابق.في counterالحلقة ، وهو المتغير
:-هيهذه التعابير int يمهد قيمة متغير الحلقة عادةالذيتعبير التمهيد، counter = 1;.
41
rofالحلقة .4.35
يفحص عادة قيمة متغير الحلقة ليرىالذي، االختبارتعبير ما إذا كان يجب تكرار الحلقة مرة أخرى أو إيقافها
counter <= 10;. ( قيمةإنقاص يقوم عادة بزيادة )أو الذيتعبير التزايد، . ++ counter متغير الحلقة
كلما1المثال التالي يقوم بإنقاص متغير الحلقة بـ تكررت الحلقة
//Program 3-6:#include <iostream.h>main ) ({
for ) int j=10; j>0; -- j(cout <<j;' '>>
return 0;{
ستعرض هذه الحلقة
1 2 3 4 5 6 7 8 9 10
; زيادة أو إنقاص متغير الحلقة بقيمة أخرى . ويمكن أيضاالبرنامج التالي يوضح ذلك :
//Program 3-7:#include<iostream.h>main ) ({
for )int j=10; j<100; j+=10(cout <<j<<' ';return 0;
{
ستعرض :-
10 20 30 40 50 60 70 80 90 100
42
يمكن استعمال عدة عبارات في تعبير التمهيد وتعبيراالختبار كما في البرنامج التالي :-
//Program 3-8:#include<iostream.h>main ) ({for ) int j=0;int total=0; j<10; ++ j;total+=j( cout <<total<<' ';return 0 ;}
تعرض:-
0 1 3 6 10 15 21 28 36 45
; يمكن في الحلقة تجاهل أحد التعابير أوforأيضا; مع المحافظة على الفواصل المنقوطة فقط. ثالثتها كليا
.for( يبين كيفية عمل الحلقة 2-6الشكل)
43
44
جسم الحلقة
تعبير التزايد
تعبير التمهيد
تعبير االختبار
إنهاء
( – طريقة عمل 3-3شكل )rofالحلقة
خطأ
صحيح
:-التالي المتداخلة الشكل العام forتأخذ الحلقات for)..........(
for)..........( for )..........(
statements;
مثال://Program 3-9:// An Example of 2 nested loops#include<iostream.h>main) ({int i,j;for )i=1 ; i<3;++i({ for )j=1 ; j<4;++j(cout << i*j<<’ ‘ <<endl;}return 0;}
مرات لكل4نالحظ هنا أن الحلقة الداخلية تتكرر )عداد الحلقة الخارجية(.iقيمة من قيم
الخرج من البرنامج:
1 2 3 42 4 6 8
3 6 9 12
يمكننا وضع أي نوع من الحلقات ضمن أي نوع آخر، ويمكن مداخلة الحلقات في حلقات متداخلة في
حلقات أخرى وهكذا.
45
الحلقات المتداخلة .4.36
التحكم بالحلقات 7.4.3
بعضفيتعمل الحلقات عادة بشكل جيد إال أننا وbreak نحتاج للتحكم بعمل الحلقات ، العبارتين األوقات
continue.توفران هذه المرونة المطلوبة :- break العبارة
أي في الخروج من الحلقة breakتتيح لنا العبارة وقت.
:break العبارة يبين لنا كيفية عمل التاليالمثال
//Program 3-10://An Example on break as a loop exit
#include<iostream.h<main) (
}int isprime ,j ,n;isprime = 1;cin>>n;
for )j=2,j<n;++j(}if )n%j== 0(}isprime =0;break;
{{{
إذا1 عند isprime قيمة المتغير يجعلهذا البرنامج إذا لم يكن كذلك0يجعل قيمته prime عدد أولى nكان
هو رقم يقبل القسمة على نفسه وعلىاألولي) الرقم ; أم ال تتماالرقم واحد فقط(.لمعرفة ما إذا ك ن الرقم أوليا
; إلى n ، إذا قبل الرقم n-1قسمته على كل األرقام وصوال يكون فإنه الباقيالقسمة على أحد هذه القيم من دون
; لكن إذا قبل الرقم القسمة على أحد هذه القيم nأوليا إلكمال الحلقة فحالما يجد البرنامجداعيبشكل صحيح ال
بشكل صحيح يجب أن يضبط n يقسم الذيالرقم األول ; من الحلقة. 0 عند isprimeقيمة المتغير ويخرج فورا
:-break( يبين طريقة عمل العبارة 3-4الشكل)
46
الصورة العادية للحلقة
الشرط ضمن الحلقة
kaerb
نهاية الحلقة
صحيح
خطأ
– طريقة عمل (3-4)شكل kaerbالعبارة
:- continue العبارة التنفيذ إلى أعلى الحلقة. continueتعيد العبارة
:-continue يوضح كيفية عمل العبارة التاليالمثال
//Program 3-11://An Example on continue statement
#include<iostream.h<main) (
}int dividend , divisor;do//Continued{
cout << ''Enter dividend;'' :cin>>dividend;
cout<< ''Enter divisor;'' ://Continuedcin>>divisor;if) divisor == 0(}
cout<<" divisor can't be zero\n; "continue;
{cout <<"Quotient is "<< dividend/divisor;
cout<<" do another )y/n(;"?cin>>ch{while )ch! = 'n'(;
{
47
أمر غير مرغوب فيه لذا إذا كتب0القسمة على على أنه القاسم يعود التنفيذ إلى أعلى الحلقة0المستخدم
ويطلب من البرنامج إدخال قاسم ومقسوم جديدين.
If ) divisor == 0({cout << “divisor can’t be zero\n”;continue;}
.nيستمر تنفيذ الحلقة إلى أن يدخل المستخدم الحرف while) ch ! =’n’ ( ;
.continue( يبين طريقة عمل العبارة 3-5الشكل )
48
49
الشرط ضمن الحلقة
unitnoce
العودة للحلقة العادية
بداية الحلقة
طريقة عمل (3-5)شكل eunitnocالعبارة
توفر لغةC++عوامل تسمى عوامل التعيين .%= و /=، *= ، - = ، +=الحسابي وهي
توفرC++ عاملي التزايد ++ والتناقص – واللذين يقومان بزيادة وإنقاص قيمة متغير ما
.1بمقدار تأخذ الحلقةfor :الشكل العام التالي
for) expression1; expression2; expression3(statement
حيث يمثل: expression1تعبير التمهيد الذي يمهد قيمة متغير
الحلقة.expression2 تعبير االختبار الذي يفحص قيمة متغير
الحلقة ويحدد ما إذا كان يجب تكرار الحلقة مرة أخرى أمال.
expression3 يمثل تعبير التزايد الذي يقوم بزيادة أو إنقاص قيمة متغير الحلقة.
تأخذ الحلقةwhile :الشكل العام التالي while) condition(statement
تأخذ الحلقةdo: الشكل التالي dostatementwhile) condition(
الحلقةdoتفحص تعبير االختبار بعد تنفيذ جسم الحلقة مرة واحدة علىdo، وعليه يتم تكرار جسم الحلقة
األقل. تستعمل العبارةbreakللخروج من الحلقة في أي
وقت. تعيد العبارةcontinue.التنفيذ إلى بداية الحلقة تستعمل العبارةswitchلالختيار بين عدة خيارات
; على قيمة متغير ما. مختلفة بناءاتستعمل العوامل المنطقية لكتابة تعابير مركبة وهي
على التوالي.not و and، or&&، || و ! والتي تعني
50
الملخص:
/استعمل العبارات في السؤال األول من الوحدة1 x يقوم برفع المتغير ++Cالسابقة لكتابة برنامج
.whileباستخدام الحلقة yلألس / ما هو الخطأ في اآلتي:2
cin << value; التالية:- while/ ما هو الخطأ في الحلقة 3
while )z>= 0(sum += z;
/أكتب برنامجاb يستقبل عدد من لوحة المفاتيح4 ثم يحدد ما إذا كان الرقم زوجياb أم فردياb. )تلميح:
(.)%(استخدم العامل / ما هي مخرجات البرنامج التالي:5
#include <iostream.h>main ) ({int y, x = 1, total =0;while )x<= 10( {y = x+x;cout <<y << endl;total +=y;++x;}cout << “ total is: “ << total << endl;return 0;}
يعرف كاآلتي:n/ مضروب العدد الموجب 6n! = n. )n –1(. )n –2( …. 1
يقوم باستقبال رقم من المستخدم.++Cأكتب برنامج ويقوم بحساب وطباعة مضروبه.
/ أوجد الخطأ في الجزء التالي:7 for ) x = 100, x >= 1, x++(
cout << x << endl;
الجزء التالي يقوم بطباعة األعداد الزوجية 1 إلى 19من
for ) x = 19 ; x >= 1 , x+=2(cout << x << endl;
51
األسئلة
/ ما هو الغرض من البرنامج التالي:8
#include <iostream.h>main ) ({int x ,y ;cout << “Enter two integers in the range 1-20”;cin >> x>> y;for )int I = 1; I < = y ; I++( { for ) int j = 1; j <= x; j++(
cout << “ “;cout << endl;}
return 0;}
52
الوحدة الرابعةsnoitcnuFالدوال
.40
بنهاية هذه الوحدة :ستتمكن من تقسيم برنامجك إلى أجزاء صغيرة تسمى
.(Functions)دوال ستتعرف على أغلب الدوال الرياضية الجاهزة والمعرفة
والتي تقوم بالعمليات الرياضية.math.hفي الملف ستتعرف على كيفية كتابة الدوال فيC++.
مكتبة ضخمة وغنيةC من اللغة ++Cورثت اللغة بدوال تقوم بتنفيذ العمليات الرياضية، التعامل مع السالسل واألحرف، اإلدخال واإلخراج، اكتشاف األخطاء والعديد من العمليات األخرى المفيدة مما يسهل مهمة المبرمج الذي
; له في عملية البرمجة. ; كبيرا يجد في هذه الدوال معينا يمكن للمبرمج كتابة دوال تقوم بأداء عمليات يحتاج
لها في برامجه وتسمى مثل هذه الدوال Programmer- defined functions
اختصار ذاكرة الحاسب على في/ تساعد الدوال المخزنة 1 باستدعائها باسمها فقط لتقوم بالعمليكتفيالبرنامج إذ المطلوب .
يكتبهاالتي ذاكرة الحاسب أو في/ تساعد البرامج المخزنة 2 خطواتفيالمستخدم على تالفى عمليات التكرار
; لعمل تلك الدوال.التيالبرنامج ; مشابها تتطلب عمال تسهيل عملية البرمجة.في/ تساعد الدوال الجاهزة 3 في/ يوفر استعمال الدوال من المساحات المستخدمة 4
الذاكرة. شكل دوال واضحة المعالمفي + +C/ كتابة برنامج الـ 5
; لكل من المبرمج والقارئ على حد يجعل البرنامج واضحاسواء.
تحتوى مكتبة الدوال الرياضية على العديد من الدوال; التي تستخدم في تنفيذ العمليات الرياضية الحسابية. فمثال
المبرمج الذي يرغب في حساب وطباعة الجذر التربيعي قد يكتب عبارة كالتالية:900للعدد
cout << sqrt ) 900(; عند تنفيذ هذه العبارة يتم استدعاء الدالة المكتبية
sqrt (900) لحساب الجذر التربيعي للعدد بين القوسين. وعليهargumentيسمى العدد بين القوسين وسيطة الدالة
sqrt ، تأخذ الدالة 30فالعبارة السابقة تقوم بطباعة العدد
53
المقدمة 1.4
2.4فوائد استخدام الدوال في البرمجة
مكتبة الدوال الرياضية )snoitcnuF yrarbiL htaM ( 3.4
وتكون النتيجة قيمة من نفسdoubleوسيطة من النوع النوع وينطبق هذا على جميع الدوال الرياضية.
++Cعند استعمال الدوال الرياضية في أي برنامج بلغة والذي يحتوى على هذهmath.hيجب تضمين الملف
الدوال.الجدول التالي يلخص بعض الدوال الرياضية:
Function Description Examplesqrt)x( xالجذر التربيعي لـ sqrt )9.0( is 3exp)x( exp)1.0( is 2.718282 ex
fabs)x( xالقيمة المطلقة لـ if x > 0 fabs)x( = x = 0 fabs)x( = 0 < 0 fabs)x( = -x
ceil)x( ألصغر عدد صحيحxتقرب xأكبر من
ceil)9.2( is 10.0ceil)-9.8( is 9.0
floor)x( ألكبر عدد صحيحxتقرب xأصغر من
floor)9.2( is 9floor)-9.8( is –10.0
54
الدوال تمكن المبرمج من تقسيم البرنامج إلى وحداتmodules،كل دالة في البرنامج تمثل وحدة قائمة بذاتها ،
ولذا نجد أن المتغيرات المعرفة في الدالة تكون متغيرات ونعنى بذلك أن المتغيرات تكون معروفة(Local)محلية
فقط داخل الدالة. (Parameters)أغلب الدوال تمتلك الئحة من الوسائط
; متغيرات محلية. والتي هي أيضا هنالك عدة أسباب دعت إلى تقسيم البرنامج إلى
داالت وتسمى هذه العملية (Functionalizing a program):وهي اختصار ذاكرة الحاسب على في/ تساعد الدوال المخزنة 1
باستدعائها باسمها فقط لتقوم بالعمليكتفيالبرنامج إذ المطلوب .
التي ذاكرة الحاسب أو في/ تساعد البرامج المخزنة 2 خطواتفييكتبها المستخدم على تالفى عمليات التكرار
; لعمل تلك الدوال.التيالبرنامج ; مشابها تتطلب عمال تسهيل عملية البرمجة.في/ تساعد الدوال الجاهزة 3 في/ يوفر استعمال الدوال من المساحات المستخدمة 4
الذاكرة. شكل دوال واضحة المعالمفي + +C/ كتابة برنامج 5
; لكل من المبرمج والقارئ على حد يجعل البرنامج واضحاسواء.
كل البرامج التي رأيناها حتى اآلن تحتوى على وهي التي تنادى الدوال المكتبية لتنفيذ مهامها.mainالدالة
كتابة دوال++Cسنرى اآلن كيف يستطيع المبرمج بلغة الـ خاصة به.
ما فإنه،عندما يولد المصرف تعليمات الستدعاء دالة يحتاج إلى معرفة اسم الدالة وعدد وسيطاتها وأنواعها ونوع
لدالة قبلل (تصريح كتابة نموذج أو )لذا علينا، قيمة اإلعادة استدعاء لها وتصريح الدالة هو سطر واحد يبلغأيإجراء
المصرف عن اسم الدالة وعدد وسيطاتها وأنواعها ونوع
55
الدوال المعرفة بواسطة المستخدم snoitcnuF denifed-remmargorP 4.4
نموذج الدالة epytotorP noitcnuF 5.4
السطر،القيمة المعادة بواسطة الدالة. يشبه تصريح الدالةلكن تليه فاصلة منقوطة.، تعريف الدالةفياألول
فمثال في تصريح الدالة التالي:-int anyfunc)int(;
بين القوسين يخبر المصرف بأن الوسيطintالنوع int و intالذي سيتم تمريره إلى الدالة سيكون من النوع
التي تسبق اسم الدالة تشير إلى نوع القيمة المعادةبواسطة الدالة.
الشكل العام التالي:++Cيأخذ تعريف الدوال في return-value-type function-name )parameter list(
{declarations and statements
}حيث:
:return-value-typeنوع القيمة المعادة بواسطة الدالة . وإذا++Cوالذي يمكن أن يكون أي نوع من أنواع بيانات .voidكانت الدالة ال ترجع أي قيمة يكون نوع إعادتها
function-nameاسم الدالة والذي يتبع في تسميته قواعد : .(identefiers)تسمية المعرفات
parameter listهي الئحة الوسيطات الممرة إلى الدالة : أو تحتوى على وسيطة(void)وهي يمكن أن تكون خالية
واحدة أو عدة وسائط تفصل بينها فاصلة ويجب ذكر كلوسيطة على حدة.
declarations and statementsتمثل جسم الدالة والذي : . يمكن أن يحتوى الـblockيطلق عليه في بعض األحيان
blockعلى إعالنات المتغيرات ولكن تحت أي ظرف ال السطريمكن أن يتم تعريف دالة داخل جسم دالة أخرى.
والذي declarator تعريف الدالة يدعى المصرح فياألول تعيدها الدالة وأسماءالتي الدالة ونوع البيانات اسميحدد
وأنواع وسيطاتها.
56
تعريف الدالةnoitinifeD noitcnuF 6.4
إستدعاء الدالةllaC noitcnuF 7.4
الدالة )التسبب بتنفيذها من جزء آخراستدعاءيتم استدعاء الدالة(هي تفعل ذلك التيمن البرنامج، العبارة
بداية الدالة.إلي انتقال التنفيذ إلي الدالة استدعاءيؤدى يمكن تمرير بعض الوسيطات إلى الدالة عند استدعائها وبعد تنفيذ الدالة يعود التنفيذ للعبارة التي تلي استدعاء
الدالة.
التي العبارة إليبإمكان الدالة أن تعيد قيم معرفها وإذافي ويجب أن يسبق اسم الدالة .استدعتها
; يجب استعمال الكلمة األساسيةكانت الدالة ال تعيد شيئاvoidذلك إليلإلشارة كنوع إعادة لها .
هنالك ثالث طرق يمكن بها إرجاع التحكم إلى النقطة التيتم فيها استدعاء الدالة:
; عند/1 إذا كانت الدالة ال ترجع قيمة يرجع التحكم تلقائياالوصول إلى نهاية الدالة
;return باستخدام العبارة /2 return إذا كانت الدالة ترجع قيمة فالعبارة /3
expression; تقوم بإرجاع قيمة التعبير expressionإلى النقطة التي استدعتها .
; يستخدم دالة تدعى لحساب مربعاتsquareخذ برنامجا. 10 إلى 1األعداد من
مثال://Program 4-1:#include<iostream.h>int square)int(;//function prototypemain)({
for)int x=1;x<=10;x++( cout<<square)x(<<" "; cout<<endl;}//now function definitionint square)int y({
return y*y;}
:كاآلتيالخرج من البرنامج يكون
57
قيم اإلعادة seulaV denruteR 8.4
1 4 9 16 25 36 49 64 81 100
وذلكmain داخل الدالة squareيتم استدعاء الدالة فيx بنسخ قيمة square تقوم الدالة )square)x.بكتابة
ويتم إرجاع النتيجة إلىy*y . ثم تقوم بحساب yالوسيط ، حيث يتم عرضsquare مكان استدعاء الدالة mainالدالة
النتيجة وتتكرر هذه العملية عشر مرات باستخدام حلقة .forالتكرار
يدل على أنها تتوقع وسيطة) (squareتعريف الدالة التي تسبق اسم الدالة تدل على أنint . و intمن النوع
; .int هي من النوع squareالقيمة المعادة من الدالة أيضا.main تقوم بإرجاع ناتج الدالة إلى الدالة returnالعبارة السطر:
int square )int( .(function prototype)هو نموذج أو تصريح الدالة
اآللية المستخدمة لتمريرهيالوسيطات الدالة نفسها حيث يتمإليالمعلومات من استدعاء الدالة
الدالةفي متغيرات منفصلة فينسخ البيانات وتخزن القيم ; في تعريف الدالة.فيتتم تسمية هذه المتغيرات فمثال
في; )cout<< square)aالمثال السابق تؤدى العبارة main) ( إلى نسخ القيمة a إلى البارمتر yالمعرف في
تعريف الدالة. يعنى القيمArgumentالمصطلح وسيطات
المحددة في استدعاء الدالة بينما يعنى المصطلح بارمتراتparametersالمتغيرات في تعريف الدالة والتي تم نسخ
; ما يتم استعمال المصطلح تلك القيم إليها، ولكن غالباوسيطات لقصد المعنيين.
( يوضح هذا.4-1الشكل )
58
الوسيطات sretemaraP 9.4
والتيmaximumالبرنامج التالي يستخدم دالة تدعى نرجع العدد األكبر بين ثالثة أعداد صحيحة.
يتم تمرير األعداد كوسائط للدالة التي تحدد األكبر ويتمreturn باستخدام العبارة mainبينها وترجعه للدالة
الذيlargestتعيين القيمة التي تمت إعادتها إلى المتغير تتم طباعته.
//Program 4-2:#include <iostream.h>int maximum )int, int, int(;main) ({int a, b, c;cout << "Enter three integers: " ;cin >> a >> b >> c ;cout << " maximum is : " << maximum )a, b, c( << endl;return 0;}int maximum )int x, int y, int z({int max = x;if )y > x( max = y;if )z > max( max = z;//Continuedreturn max;}
الخرج من البرنامج بافتراض أن المستخدم قد أدخل األرقام22 ،85 ،17.
59
يوضح كيفية (4-1)شكل .تمرير الوسائط
بارمترa
niam
i y
aوسيط
erauqS) (
Enter three integers: 22 85 17Maximum is: 85
60
تكتب الدالة التي ال تمتلك++Cفي لغة الـ بين القوسين الذين يتبعان اسمvoidوسيطات إما بكتابة
; اإلعالن الدالة أو تركهما فارغين ، فمثالvoid print ) (;
ال تأخذ أي وسيطات وهي ال printيشير إلى أن الدالة ترجع قيمة .
المثال التالي يبين الطريقتين اللتين تكتب بهما الدوال التيال تأخذ وسيطات:
//Program 4-3:// Functions that take no arguments#include <iostream.h>void f1 ) (;void f2 )void(;//Continuedmain) ({ f1 ) (; f2 ) (;return 0;}
void f1 ) (
61
رغم أنها غير ضرورية إال أنه يتم ذكر أسماء أن تكونالضروري التصريح ومن غير فيالوسيطات
تعريففي نفسها المستعملة هيهذه األسماء الواقع، المصرف يتجاهلها لكنها تكونفيالدالة .
; لنفترض ; للذين يقرأون البرنامج . فمثال مفيدة أحيانا دالةفي تمثالن إحداثيات الشاشة y و xأن الوسيطين
تفرض نقطة على الشاشة. void draw_dot )int,int(; [تصريح الدالة]
للمعرف لكن المبرمج قد الكافيهذا التصريح .الصادي اإلحداثي وأيهما السيني اإلحداثييعرف أيهما
; لو كتبنا : لذا سيكون مفيداvoid draw_dot )int x,int y(;
تصريحفيإذا لم يذكر المبرمج نوع إعادة الدالة .intالدالة يفترض المصرف أن نوع الدالة هو
تعريف الدالة إذافيعدم كتابة نوع إعادة الدالة .intكان اإلعالن عن الدالة يتطلب نوع إعادة غير
إرجاع قيمة من دالة تم اإلعالن عن نوع إعادتها void .
دوال بدون وسيطات stsiL retemraraP ytpmE htiw snoitcnuF 1.4
0
خطأ
{ cout << "Function f1 takes no arguments" << endl;}void f2 )void({ cout << "Function f2 also takes no arguments" << endl;}
الخرج من البرنامج:
Function f1 takes no argumentsFunction f2 also takes no arguments
يعتبر فيها وقت تنفيذالتيتحتاج بعض التطبيقات ;، إلبدال عملية استدعاء ; وحاسما ; حيويا البرنامج أمرا
وهى عبارة عن. دالة بما يسمى دالة سياقيةواستخدام شفرة تقوم بالعمل المطلوب نفسه، يتم تعريف الدالة
المستخدمالنحويالسياقية باستعمال نفس التركيب ; من وضع شفرة الدالة لتعريف الدالة االعتيادية ، لكن بدال
الطبيعي السياق في مكان مستقل يضعها المصرف في للبرنامج مكان ظهور استدعاء الدالة. يتم جعل الدالة
في inlineسياقية عن طريق استخدام الكلمة األساسية تعريف الدالة.
inline void func1) (}statements{
تستخدم الدالة السياقية فقط إذا كانت الدالة البرنامج.فيقصيرة وتستخدم مرات عديدة
مثال:
//Program 4-4:#include<iostream.h>inline float cube)float s({return s*s*s;}
62
الدوال السياقية snoitcnuF enilnI 1.4
1
main)({ cout<<"\nEnter the side length of your cube : ";
float side; cin>>side; cout<<"volume of cube is " <<cube)side( <<endl;}
الخرج من البرنامج:
Enter the side length of your cube : 5volume of cube is 125
مثال آخر على الدوال السياقية :
// Program 4-5:#include <iostream.h>inline int mult) int a, int b({return )a*b(;}//Continuedmain) ({int x, y, z;cin >> x >> y >> z;cout << "x = " << x << " y = " << y << " z = " << z << endl;cout << "product1" << mult )x ,y( << endl;cout << "product2" << mult )x +2, y( << endl;return 0;}
:(x = 3, y =4, z = 5الخرج من البرنامج إذا أدخلنا )
x = 3 y =4 z = 5product1 12product2 32
63
يعنى استعمال االسم تحميل الداالت بشكل زائد لعدة داالت لكن كل دالة يجب أن يكون لها تعريف مستقل. عند استدعاء دالة يبحث المصرف عن نوع وسيطات الدالة
يميز المصرف بينولكي .وعددها لمعرفة الدالة المقصودة يقوم بعملية تعرف بتشويه،دالة وأخرى تحمل نفس االسم
، تتألف هذه العملية من إنشاء(names mangling) األسماء اسم جديد خاص بالمصرف عن طريق دمج اسم الدالة مع
أنواع وسيطاتها.مثال:
بشكل زائدsquareالبرنامج التالي يقوم بتحميل الدالة :-double وللنوع intلحساب الجذر التربيعي للنوع
//Program 4-6:#include <iostream.h>int square)int x({return x*x;}//Continueddouble square)double y({return y*y;}main )({cout<< " The square of integer 7 is"<<" "<<square)7(<< endl<<"The square of double 7.5 is"<<" "<<square)7.5(<< endl;return 0;}
الخرج من البرنامج:
The square of integer 7 is 49The square of double 7.5 is 56.25
; يقوم بتحميل دالة تدعى لحسابabsإليك اآلن برنامجا.long و int ، doubleالقيمة المطلقة ألعداد من النوع
64
تحميل الداالت بشكل زائدsnoitcnuF gnidaolrevO 1.4
2
//Program 4-7:#include <iostream.h>// abs is overloaded three waysint abs )int i(; double abs)double d(;long abs)long l(;
int main) ({cout<< abs )-10(<<"\n";cout<< abs )-11.0(<<"\n";cout<< abs )-9L(<<"\n";return 0;}int abs )int i(//Continued{cout<<"using integer abs) (\n";return i<0 ? -i :i ;}double abs )double d({cout<<" using double abs) (\n";return d<0.0 ? -d : d ;}long abs)long l({cout<<" using long abs) (\n";return l<0.0 ? -l : l ;}
الخرج من البرنامج:
using integer abs) (10using double abs) (11.0using long abs) (9L
65
تجاهل وسيطة أو أكثراالفتراضيةتتيح الوسيطات وعند وجود وسيطة ناقصة يزود، عند استدعاء الدالة
; ثابتة لتلك الوسيطات المفقودة . تصريح الدالة قيمامثال:-
//Program 4-8:#include <iostream.h>inline box_volume )int length=1,int width=1,int height=1({return length*width*height;}main)({cout<<"The default box volume is "<<box_volume)( <<endl<<"width 1 and height 1 is "<<box_volume)10(<<endl;return 0;}
الخرج من البرنامج:
The default box volume is 1Width 1 and height1 is 10
box_volumeتم استعمال تصريح الدالة لتزويد الدالة عالمةتلي التي وتحدد القيمة افتراضيةبثالث وسيطات
لكل وسيطة .1المساواة قيمة هذه الوسيطات وهى box_volume الدالة main فييستدعى البرنامج
بطريقتين:-;: بدون وسيطات لذا تم box_volume احتسابأوال
1 للوسيطات لتعيد الدالة القيمة االفتراضيةباستخدام القيم كحجم للمربع.
; : بوسيطة واحدة وهى حجم للمربع10 لتعيد الدالة 10ثانيا.length = 10، في هذه الحالة
يبين كيف يزود تعريف الدالة الوسيطات(2-4)الشكل االفتراضية:
66
الوسيطات االفتراضية stnemugrA tluafeD 1.4
3
;)1=thgieh tni,1=htdiw tni ,1=htgnel tni(emulov xoB
01(emulov xob >> tuoc ;)
)1,1,01(emulov xoB
( يوضح كيفية تزويد 4-2شكل )الوسيطات اإلفتراضية
إعطاؤها يمكن الوسيطات الئحة نهاية في الموجودة الوسيطات فقط
افتراضية وسيطة لها فقط واحدة وسيطة هنالك كانت ،فإذا افتراضية وسيطات
الئحة وسط في افتراضية وسيطة وضع يمكننا وال األخيرة تكون أن يجب
كتابة يمكننا ال آخر بمعنى عادية وسيطات
int box_volume)int length, int width=1,int height(;ألن الوسيطة االفتراضية ليست الوسيطة األخيرة.
لنفرض أننا لدينا متغيرين صحيحين في برنامج ونريد استدعاء دالة تقوم بتبديل قيمتي الرقمين ،لنفرض أننا
عرفنا الرقمين كاآلتي:int x=1;int y=2;
:-(pass-by-value) أ/ التمرير بالقيمةترى هل تقوم الدالة التالية بتبديل القيمتين:
void swap )int a, int b(}int temp =a;a=b.b=temp;
{ ، لكن إذاb و aتقوم هذه الدالة بتبديل قيمتي
استدعينا هذه الدالة كاآلتي:swap) x,y(;
لم تتغير وذلك ألن الوسيطات y و xسنجد أن قيمتي االعتيادية للدالة يتم تمريرها بالقيمة وتنشئ الدالة متغيرات
; هي في هذا المثال لتخزين القيم الممررةb و aجديدة كليا ثم تعمل على تلك المتغيرات الجديدة( 1,2)إليها وهي
67
1.4التمرير بالقيمة والتمرير بالمرجع4
و2 إلى aوعليه عندما تنتهي الدالة ورغم أنها قامت بتغيير b لكن المتغيرات 1 إلى x و yفي استدعاء الدالة لم
تتغير.:(pass-by-refrence)ب/ التمرير بالمرجع
من) (swapالتمرير بالمرجع هو طريقة تمكن الدالة ;y و xالوصول إلى المتغيرات األصلية والتعامل معها بدال
من إنشاء متغيرات جديدة . وإلجبار تمرير الوسيطة بالمرجع نضيف الحرف & إلى نوع بيانات الوسيطة في
تعريف الدالة وتصريح الدالة . وتمرير swap يبين كيفية كتابة الدالة (3-4)المثال
وسيطاتها بالمرجع:
//Program 4-9:#include <iostream.h>void swap )int & , int&(;main ) ({int x= 1;int y= 2; swap )x, y(;return 0;}void swap )int& a, int & b({cout <<"Original value of a is " << a<<endl;int temp =a;a=b;b=temp;cout <<"swapped value of a is " << a<<endl;}
.1 إلى y و 2 إلى xبعد تنفيذ هذه الدالة تتغير قيمة ويكون الخرج من البرنامج كالتالي:
Original value of a is 1Swapped value of a is 2
68
(يبين الفرق بين التمرير بالمرجع والتمرير4-3الشكل )بالقيمة.
69
في التصريح والتعريف وهو يبلغintالحرف & يلي المصرف أن يمرر هذه الوسيطات بالمرجع، أي أن
والy هي مرجع إلى b وx هي مرجع إلى aالوسيطة يستعمل & في استدعاء الدالة.
بعد التمرير بالقيمة b a
y x
التمرير بعد بالمرجع
b a
y x
21
12
21
قبل التمرير بالقيمة b a
y x
قبل التمرير بالمرجعb a
yx
12
12
12
يوضح طريقتي التمرير (4-3)شكل بالمرجع والتمرير بالقيمة.
أفضل طريقة لتطوير وصيانة البرامج الكبيرة هو تقسيمها لوحدات صغيرة تسمى دوال.
. يتم تنفيذ الدوال عن طريق استدعائها; استدعاء الدالة يكون بكتابة اسم الدالة متبوعا
بوسيطاتها وأنواع تلك الوسائط.-:الصورة العامة لتعريف الدالة هو
return-value-type function-name) parameters-list({
declarations and statements}
حيث:-return-value- typeيمثل نوع البيانات الذي تعيده
.voidالدالة ، إذا كانت الداللة ال تعيد قيمة يكون function nameيمثل اسم الدالة ويتبع في تسميته قواعد
تسمية المتغيرات .parameters_listهي الئحة من المتغيرات تفصلها فاصلة
وتمثل الوسيطات التي سيتم تمريرها إلى الدالة. نموذج أو تصريح الدالة(function prototype)يمكن
المصرف من معرفة ما إذا تم استدعاء الدالة بالصورةالصحيحة.
يتجاهل المصرف أسماء المتغيرات المذكورة في تصريح الدالة.
يمكن استعمال نفس االسم لعدة داالت ، لكن يجب أن يكون لكل دالة تعريف مستقل ويسمى هذا بتحميل
.(function overloading)الداالت بشكل زائد تسمحC++بتمرير وسيطات افتراضية وعليه عند
تجاهل وسيطة أو أكثر في استدعاء الدالة يزود تصريحالدالة قيم تلك الوسيطات المفقودة.
70
الملخص:
1
1 bأكتب تصريحا /(prototype) لدالة smallest z و x ، yوالتي تأخذ ثالث أعداد صحيحة
.intكوسيطات لها وترجع قيمة من النوع
/ أكتب تعريفاb لدالة ترجع األكبر من بين ثالثة2أرقام صحيحة.
3bلدالة تحدد ما إذا كان الرقم رقما bأكتب تعريفا / أولياb أم ال.
تلميح: الرقم األولى هو الذي ال يقبل القسمة إال.1على نفسه والرقم
/ جد الخطأ في الدالة اآلتية:4void product ) ( {
int a, b, c, result;cout << “ Enter three integers: “;cin >> a>> b >>c;result = a*b*c;cout << “Result is : “ << result;return result;
}/ جد الخطأ في الدالة اآلتية:-5
void f)float a(; {
cout << a << endl;}
والتي الinstructions/ أكتب تصريحاb لدالة تدعى 6قيمة. تأخذ أي وسيطات وال ترجع أي
/ أكتب تعريفاb لدالة تستقبل عدداb من المستخدم7 المستخدم ثم ترجع العدد معكوساb فمثالb إذا أدخل
.4321 ترجع الدالة العدد 1234العدد
71
األسئلة
الوحدة الخامسةsretnioP & syarrAالمصفوفات والمؤشرات
0.5
الوحدة: هذه بنهاية ستتعرف على بنية المصفوفات(Arrays). ستتمكن من اإلعالن عن وتمهيد والوصول إلى أي
عنصر من عناصر المصفوفة ..ستتعرف على المصفوفات متعددة األبعاد ستتمكن من استعمال المؤشرات(Pointers). .ستتمكن من استعمال مصفوفات السالسل
لها عدد، نوع من أنواع بنية البياناتهيالمصفوفة تكون جميعها من نفس النوعالتيمحدود ومرتب من العناصر
type، يمكن أن تكون جميعها صحيحة ; أو عائمةint فمثالfloat نفسفي ولكن ال يمكن الجمع بين نوعين مختلفين
المصفوفة . عنصر13 تحتوى على C يبين مصفوفة التاليالشكل
من هذه العناصر بذكرأي إلي ويمكن الوصول ،intمن النوع ; برقم موقع العنصر المصفوفةفياسم المصفوفة متبوعا
; ب قواس [ ] .األمحاطا المصفوفة بفهرس العنصرفييرمز لرقم العنصر
index ولهذا يشار0 المصفوفة هو في . فهرس العنصر األول C[1] والثاني C[0] بـ C المصفوفة في العنصر األول إلي
; يحمل العنصر C[6]والسابع C المصفوفة في i وعموما . C[i-1] الفهرس
تتبع تسمية المصفوفات نفس قواعد تسمية المتغيرات.C[0] -45C[1] 6C[2] 0C[3] 72C[4] 1543C[5] -89C[6] 0C[7] 62C[8] -3C[9] 1
C[10] 6453C[11] 78C[12] 15
; يسمى فهرس العنصر برمز منخفض subcriptأحيانا تكون نتيجتهجبري أو تعبير integerويجب أن يكون الفهرس
integer إذا كانت ; فالعبارة:b=6 وa=5 . فمثالC[a+b]+=2,
عشر الثاني العنصر إلي 2تقوم بإضافة C[11] في .Cالمصفوفة
72
مقدمة 1.5
المصفوفة في 0يحمل العنصر C 1 والعنصر 45- القيمة .6القيمة
المصفوفةفيلطباعة مجموع الثالثة عناصر األولى C :يمكن كتابة
cout<<C[0]+C[1]+C[2]<<endl;
73
اإلعالن عن المصفوفات:- ; الذاكرة لذا يجب علىفيتحتل المصفوفات حيزا
المبرمج تحديد نوع عناصر المصفوفة وعددها حتى يتسنى ،للمعرف تخصيص الحيز الالزم من الذاكرة لحفظ المصفوفة
; لـ عنصر من النوع12وحتى تخبر المصرف بأن يخصص حيزاint مصفوفة في C ، اإلعالن:استخدم
int C[12]; يمكن تخصيص الذاكرة لعدة مصفوفات باستخدام
:كاألتينفس اإلعالن وذلك int b[100], x[20];
; يمكن اإلعالن عن مصفوفات من نوع بياناتأيأيضا; لإلعالن عن مصفوفة عناصرها من النوع charآخر ، فمثال
نكتب:char ch[20];
مثال عن استخدام المصفوفات: n لتمهيد عناصر المصفوفةfor حلقة التالييستخدم البرنامج
وطباعة عناصر المصفوفة.0عند
//Program 5-1: //initializing an array
#include <iostream.h<#include <iomanip.h<
main) (}int n[10];
for )int i=0; i<10;i++( // initialize arrayn[i] = 0; cout << “Element” << setw)13( << “ value” << endl;for )i=0 ; i< 10; i++( // print arraycout << setw)7( <<i<<setw)13( <<n[i]<<endl;return 0;}
74
syarrA 2.5المصفوفات
الخرج من البرنامج:
Element Value 0 0 0 0 0 0 0 0 0
9 0
iomanip.hفي البرنامج السابق تم تضمين الملف والذي يعني ضبط )setw)13وذلك ألننا استخدمنا المناور
) أي أن القيمة التي ستتم طباعتها 13عرض الحقل عند مسافة من القيمة التي تمت طباعتها13ستكون على بعد
قبلها ( . يمكن تمهيد عناصر المصفوفة باتباع اإلعالن عن
المصفوفة بعالمة المساواة )=( تليها الئحة من القيم ويتم الفصل بين،المطلوب تمهيد عناصر المصفوفة عندها
وتحيط هذه الالئحة األقواس الحاصرة { }.،القيم بفواصل integer يقوم بتمهيد عناصر من النوع التاليالبرنامج قيم محددة عند اإلعالن عن المصفوفة، وطباعة هذهلتحتويالقيم.
//Program 5-2: //initializing an array with a declaration
#include <iostream.h<#include <iomanip.h<
main) (}int n[10] = {32,27,64,18,95,14,90,70,60,37};
cout << “Element” << setw)13( << “ value” << endl;
75
for )i=0 ; i< 10; i++( // print arraycout << setw)7( <<i<<setw)13( <<n[i]<<endl;return 0;}
الالئحة أكثر منفيإذا كانت قيم التمهيد الموجودة حجم المصفوفة المحدد سيعترض المصرف، وإذا كانت أقل
لذا إذا كنا نريد تمهيد،سيمأل المصرف بقية العناصر أصفار عناصر مصفوفة مهما كان حجمها بأصفار كل ما علينا فعله
:-كاآلتيهو كتابة إعالن int anyarray[10]={0};
التالي 0سيتم تمهيد العنصر األول عند القيمة كوننا لم نحدد قيمة لها. 0كتبناها والعناصر المتبقية عند
مصفوفةفي عنصر 12 يقوم بجمع التاليالبرنامج .intمن النوع
//Program 5-3:// compute the sum of the elements of the array#include <iostream.h>main) ({const int arraysize =12;int a[arraysize] = {1, 3, 5, 4, 7, 2, 99, 16, 45, 67, 89, 45};int total = 0;for )int i= 0; i<arraysize ; i++(total += a[i];cout <<” total of array element values is “ << total << endl;return 0;}
الخرج من البرنامج:
total of array element values is 383
نالحظ أننا في العبارة:const int arraysize = 12;
76
ماذا يحدث إذا تم تحديد حجم مصفوفة ال يتوافق مع الالئحة؟فيعدد قيم التمهيد الموجودة
. يتم استعمال هذهconstاستعملنا كلمة جديدة هي الكلمة األساسية في تعريف المتغير الذي ال يمكن تغيير قيمته في البرنامج ولذلك يجب تمهيده عند قيمة أولية عند تعريفه )
(12في البرنامج السابق تم تمهيده ليساوى
77
نوعأيكما ذكرنا أنه يمكن تعريف مصفوفات من مصفوفةفيبيانات آخر، سنقوم اآلن بتخزين سلسلة حروف
.charمن النوع باستخدام ماcharيتم تمهيد المصفوفة من النوع
(string literal) ييسمى بالثابت السلسلchar string1[ ]="first";
هنا يتم تحديده بواسطةstring1حجم المصفوفة ; على طول الثابت السلسل ".first"ي المصرف بناءا
" تحتوىfirstمن المهم هنا أن نذكر أن السلسلة "; يشير ; خامدا ; حرفا نهايةإلىعلى خمسة عناصر زائدا
ويتم تمثيلهnull characterالسلسلة ويسمى الحرف الخامد كل السالسل بهذا الحرفوتنتهي 'o'\باستخدام تتابع الهروب
تحتوى على ستةstring1الخامد وعليه فإن المصفوفة عناصر.
; تمهيد السلسلة " " باستخدام الئحةfirstيمكن أيضاقيم تفصلها فواصل لذا اإلعالن:-
char string1[ ]="first;"يكافئ:
char string1[ ]={'f','i','r','s','t','\o'} مصفوفة أحرف ،هي الواقع فيوبما أن السلسلة
حرف من حروف السلسلةأي إلىعليه يمكن الوصول ; مباشرة باستخدام الفهرس واسم المصفوفة ،فمثال
string1[0]='f'.ومثلما يمكن تمهيد السلسلة عند اإلعالن ; إدخال السالسل عن طريق لوحة المفاتيح،عنها يمكن أيضا
; اإلعالن :->> وcinباستعمال فمثالchar string2[20];
;19ينشئ مصفوفة أحرف تسمح بتخزين حرفاإضافة إلى الحرف الخامد والعبارة
cin>>string2; تقوم بتخزين السلسلة المدخلة عن طريق لوحة
.string2 المصفوفة فيالمفاتيح وتخزينها
78
sgnirtSالسالسل 3.5
تعلنالتاليةيجب أن نتذكر دائماb أن المصفوفة يجب أن تكون كبيرة لماسلسليةعنها ثوابت
الحرفإلى حروف السلسلة إضافة يكفى لتخزينالخامد.
مصفوفة األحرففييمكن خرج السلسلة المخزنة string2 وعليه يمكن طباعة المصفوفة << وcoutباستخدام
باستخدام العبارة:-cout << string2 << endl;
cout مثل cinتهتم بحجم المصفوفة حيث تقوم ال الذي الحرف الخامد إلىبطباعة حروف السلسلة حتى تصل
يحدد نهاية السلسلة. يقوم بتمهيد مصفوفة أحرف عند ثابت التاليالبرنامج للوصول إلىfor ويقوم باستعمال حلقة التكرار سلسلي
عناصر المصفوفة وطباعتها .
//Program 5-4://Treating character arrays as strings#include<iostream.h>main) ({char string1[20], string2[ ] = “ stringliteral” ;cout << “Enter a string: “;cin>> string1;cout << “string1 is : “ << string1<<endl << “string2 is : “ << string2<<endl << “string1 with spaces between characters is: “ << endl;for )int i= 0; string1[i] ; = ‘\0’ ; i++( cout << string1[i]<< ‘ ‘;cout << endl;//Continuedreturn 0;}
79
مع السالسل يتم فقط ذكر cinعند استعمال سيتم فيها تخزين حروفالتياسم المصفوفة
السلسلة المدخلة دون ذكر حجمها هنا تأتى التي المصفوفة أمثلة فيمسئولية المبرمج
سيتم تعريفها لتخزين السلسلة يجب أن تكون يدخلهاالتيكبيرة لما يكفى تخزين السلسلة
المستخدم عن طريق لوحة المفاتيح ويجب أن حالما يجد فراغاb يتوقف عن cinنذكر هنا أن
الخرج من البرنامج:Hello there بافتراض أن المستخدم قد أدخل السلسلة
Enter a string: Hello therestring1 is : Hellostring2 is : string Literalstring1 with spaces between characters is : H e l l o
لوصول إلى حروفforاستخدمت حلقة التكرار وطباعتها مع طباعة مسافة بين كل حرفstring1السلسلة
\‘ =! o’ ) string1[i]‘\واآلخر حتى تصل إلى الحرف الخامد o’; (.والذي يحدد نهاية السلسلة
توجد عدة داالت تعمل على السالسل، إذا أردنا استعمال أي من هذه الدوال في برنامج يجب أن نقوم
. من هذه الداالت :string.hبتضمين ملف الترويسة 1/strlen) (-:
طول السلسلة الممررة) ( strlenتعيد الدالة كوسيطة لها ،البرنامج التالي يوضح ذلك :-
//Program 5-5:// using strlen#include<iostream.h>#include<string.h>main ) ({char *string1= “ abcdefghijklmnopqrstuvwxyz”;//Continuedchar *string2 = “four”;char *string3 = “Boston”;cout << “ The length of \ “ “ << string1 << “ \” is << strlen )string1( <<endl << “ The length of \” << string2 <<” \” is << strlen )string2( << endl << “The length of\ “ “<< string3 << “ \” is << strlen) string3( <<endl;return 0;}
الخرج من البرنامج:
80
مكتبة داالت السالسل4.5
The length of “abcdefghijklmnopqrstuvwxyz” is 26The length of “four” is 4The length of “Boston” is 6
غير محسوب في الطول الذي\ 0الحظ أن الحرف ويحتلs1 على الرغم من أنه موجود في strlenتعيده الدالة
; في الذاكرة. مكانا
2 /strcpy) (-: لنسخ سلسلة إلى سلسلة أخرى strcpyتستعمل الدالة
//Program 5-6:// using strcpy#include<iostream.h>#include<string.h>main ) ({char x[ ] = “Happy Birthday to you”;//Continuedchar y[25];cout<<” The string in array x is : “<< x << endl;cout<<” The string in array y is : “<< strcpy)y, x(<< endl;return 0;}
y ستحتوى السلسلة )strcpy)y, xبعد تنفيذ العبارة strcpy. الحظ هنا أن الدالة Happy Birthday to youعلى
تنسخ السلسلة الممررة كالوسيطة الثانية إلى السلسلةالممررة كالوسيطة األولى.
وعليه الخرج من البرنامج:
The string in array x is : Happy Birthday to youThe string in array y is : Happy Birthday to you
3 /strcat) (-:
81
بإلحاق السالسل ، الذي يمكن) (strcatتقوم الدالة ; إذا ألحقنا السلسلة scienceأن يسمى جمع السالسل فمثال
computer ستكون نتيجة السلسلة computerبالسلسلة science-:
//Program 5-7:// using strcat#include<iostream.h>#include<string.h>int main ) ({
char s1[20]=”computer; ”char s2[ ]=”science” ;cout<<”s1= “ <<s1 << endl << “s2= “ << s2 <<endl;cout<< “strcat)s1, s2( = “ << strcat )s1, s2( << endl;//Continuedreturn 0;}
الخرج من البرنامج:
s1= computers2 = sciencestrcat)s1, s2(= computerscience
4 /strcmp) (-: تقارن السلسلة الممرة إليهاstrcmp الدالة
كوسيطة أولى مع السلسلة الممرة إليها كوسيطة ثانية، إذا كانتا متطابقتين وقيمة سالبة إذا كانت السلسلة0وترجع
األولى أصغر من السلسلة الثانية وقيمة موجبة إذا كانتالسلسلة األولى أكبر من السلسلة الثانية.
البرنامج التالي يوضح ذلك:
//Program 5-8:// using strcmp#include<iostream.h>
82
#include<string.h>int main ) ({char *s1 = “ Happy New Year”;char *s2 = “ Happy New Year”;char *s3 = “ Happy Holidays”;cout << “s1= “ << s1<< endl<< “s2= “ <<s2<<endl << “s3= “ << s3<< endl<< endl<< ”strcmp)s1, s2(= “ << strcmp)s1, s2( <<endl<< ”strcmp)s1, s3(= “ << strcmp)s1, s3( <<endl<< ”strcmp)s3, s1(= “ << strcmp)s3, s1( <<endl<< endl;return 0;}
الخرج من البرنامج:
s1= Happy New Years2= Happy New Years3 = Happy Holidays
strcmp )s1, s2( = 0strcmp )s1, s3( = 6strcmp )s3, s1( = 6
يمكن تمرير مصفوفة كوسيطة لدالة وذلك بذكراسم المصفوفة.
; إذا تم اإلعالن عن مصفوفة hourlyTemperatureمثال:-كاآلتي
int hourlyTemperatures[24];عبارة استدعاء الدالة:-
modify_Array)Int hourlyTemperatures,24(;
وحجمهاhourlyTemperatureتمرر المصفوفة ; أنه عند تمريرmodify Arrayكوسائط للدالة وتذكر دائما
83
تمرير المصفوفات كوسائط للدوالsnoitcnuF ot syarrA gnissaP 5.5
مصفوفة ما كوسيطة لدالة يجب تمرير حجم المصفوفة حتىيتسنى للدالة معالجة كل عناصر المصفوفة.
أن تكون متعددة+ +C فييمكن للمصفوفات األبعاد ويمكن كذلك أن يكون كل بعد بحجم مختلف ،
الشائع للمصفوفات متعددة األبعاد هو تمثيلاالستعمال صورةفي على بيانات مرتبة تحتوي التالي Tablesالجداول
صفوف وأعمدة ولتمثيل الجدول نحتاج لبعدين األول يمثل يمثل األعمدة.والثانيالصفوف
تحتوى على ثالثة صفوفA يبين مصفوفة التاليالشكلوأربع أعمدة.
Column 0 Column1 Column2 Column 3Row 0 A[0][0] A[0][1] A[0][2] A[0][3]Row 1 A[1][0] A[1][1] A[1][2] A[1][3]Row 2 A[2][0] A[2][1] A[2][2] A[2][3]
A[i][j] على الصورة A المصفوفة في عنصر أييتم تمثيل حيث:-
A.اسم المصفوفة : i العنصر.إليه ينتمي الذي : رقم الصف j: العنصر.إليه ينتمي الذي رقم العمود
; يكونفيالحظ أن كل العناصر الموجودة الصف األول مثال العمودفي وكل العناصر الموجودة 0الفهرس األول لها هو .3 لها هو الثانيالرابع يكون الفهرس
عمودy صف و x تحتوى على aيتم اإلعالن عن مصفوفة هكذا:
int a[x][y]; يمكن تمهيد قيمة المصفوفة المتعددة األبعاد عند اإلعالن عنها
:كاآلتيوذلك int b[2][2]={{1,2},{3,4}};
حيث:b[1][1]=4, b[1][0]=3, b[0][1]=2, b[0][0]=1
; هنا عند قيمها المصفوفة متعددة األبعاد إذا تم تمهيدفيأيضا ال يتوافق عددها مع حجم المصفوفة فإن المصرف سيمأل بقية
العناصر أصفار.
84
المصفوفات متعددة األبعادsyarrA lanoisnemiditluM 6.5
يوضح كيفية تمهيد مصفوفات متعددة األبعادالتاليالبرنامج عند اإلعالن عنها:
//Program 5-9:// initializing multidimensional arrays#include<iostream.h>void printarray)int [ ] [3](;int main) (//continued{int array1[2] [3] = { {1, 2, 3}, {4, 5, 6}}, array2[2] [3] = {1, 2, 3, 4, 5}, array3[2] [3] = { {1, 2}, {4} };cout << “values in array1 by row are : “ << endl;printArray)array1(;//Continuedcout << “values in array2 by row are : “ << endl;printArray)array2(;cout << “values in array3 by row are : “ << endl;printArray)array3(;return 0;}void printArray)int a[ ][3]({for )int i=0; i<1; i++( { for )int j=0; j<2; j++(cout << a[i][j] <<’ ‘;cout << endl; } }
الخرج من البرنامج:
values in array 1 by row are:1 2 34 5 6values in array 2 by row are:1 2 34 5 0values in array 3 by row are:1 2 0
85
4 0 0
86
في كعنوان لمتغير + +C لغة فييستخدم المؤشر المهمة للمؤشرات هو التخصيصاالستعماالتالذاكرة ، أحد
للذاكرة حيث يتم استعمال المؤشرات إلنشاء بنيةالديناميكي الذاكرة.يتم اإلعالن عنفيبيانات لتخزين البيانات
; العبارة :فيالمؤشرات قبل استخدامها البرنامج فمثالint *countptr;
متغير منإلى ليشير countptrتعلن عن مؤشر ذلك( وكلل المذكورة قبل اسم المؤشر تشير * )intالنوع
;فيمتغير يعلن عنه كمؤشر يجب أن يكتب اإلعالن مسبوقا; اإلعالن :*بـ فمثال
float *xptr, *yptr;; من ليشير مؤشراتموقعي yptr و xptrأن كال
ويمكن أن تستخدم المؤشرات لتشيرfloatقيم من النوع ل نوع بيانات آخر.ألي
; عند اإلعالن عن كل* مؤشر أن تسبق أيتذكر دائما; اإلعالن : مؤشر على حدة فمثال
Int *xptr, yptr;; . ليس صحيحا:كاآلتييجب أن تعلن عن هذه المؤشرات
int *xptr, *yptr; 0يمكن تمهيد المؤشرات عند اإلعالن عنها عند قيمة
يحملالذي الذاكرة . المؤشر في أو عند قيمة عنوان nullأو 0 متغير . تمهيد المؤشر عند ألي ال يشير null أو 0القيمة
يفضل تمهيد+ +C في ولكن nullيكافئ تمهيده عند .0المؤشر عند القيمة
عوامل المؤشرات:-:-& / عامل العنوان1
يسمى عامل العنوان وهو عامل أحادى&العامل يرجع عنوانيستعمل لمعرفة العنوان الذي يحتله متغير ما [
; إذا استعملنا اإلعالن:]معامله فمثالint y= 5;int *yptr;
;yptr =&yالعبارة: yptr ويقال أن yptrلمؤشر ل yتقوم بتعيين عنوان المتغير
.y لـيشير
87
sretnioPالمؤشرات 7.5
:* العامل /2; عامل أحادى وهو يرجع القيمة *العامل يحملهاالتي أيضا
معامله ، وعليه العبارة cout << * yptr << endl ;
.5 والتي هي yتقوم بطباعة قيمة المتغير والتي314,701 تقوم بطباعة القيمة ;cout<<yptrوالعبارة:
.yptr إلى y ، بعد أن تم تعيين المتغير yهي عنوان المتغير ( يبين هذا:5-1الشكل)
على يسار اسم المتغير كما*وعندما يتم استعمال العامل فإنه يسمى عامل المواربةyptr*حصل في التعبير
indirection.
Int *yptr ; )إعالن (*yptr=5; )مواربة(
.* والعامل &البرنامج يوضح استعمال العامل
//Program 5-10:// using the & and * operators#include<iostream.h>main ) ({ int a ; //a is an integer
88
عند استعماله كعامل مواربة له معنى*العامل مختلف عن معناه عند استعماله لإلعالن عن
المتغيرات المؤشرة. يسبق عامل المواربة اسم *المتغير ويعنى قيمة المتغير المشار إليه. أما
المستعملة في اإلعالن فتعنى مؤشر إلى.
إنتبه للفرق بين عامل العنوان & الذي يسبق وبين عامل المرجع الذي يلي اسم اسم المتغير،
النوع في تعريف الدالة.
5
yptr
*rtpy يساوى 5
5 y
جزء من
الذاكرة التي يحتلها البرنام
ج
07,4130
07,4131
07,4132
07,4133
( يوضح 5-1شكل )rtpy*المخرج من
int *aptr; // aptr is apointer to an integer a = 7; aptr = &a; // aptr set to address of a cout <<” The address of a is “ << &a <<endl << “The value of aptr is “ << aptr<< endl<< endl;
cout << “The value of a is “ << a<< endl << “The value of *aptr is “ << *aptr<< endl<<endl; cout<<” Proving that * and & are complement of “ << “each other.” <<endl<< “ & *ptr = “<< & *aptr << endl<< “ *&aptr = “ << *&aptr <<endl; return 0;}
الخرج من البرنامج:
The address of a is oxfff4The value of aptr is oxfff4
The value of a is 7The value of *aptr is 7
Proving that * and & are complements of each other&* aptr = oxfff4
&*aptr = oxfff4
:- void مؤشرات إلى عادة العنوان الذي نضعه في المؤشر يجب أن يكون
; ال يمكننا تعيين عنوان متغير من نفس نوع المؤشر، فمثالfloat إلى مؤشر intلكن هنالك نوع من المؤشرات يمكنها ،
voidأن تشير إلى أي نوع من البيانات وتسمى مؤشرات إلى ويتم تعريفها كاآلتي:-
void * ptr;
89
لهذا النوع من المؤشرات استعماالت خاصة فهو يستخدم ; لتمرير المؤشرات إلى داالت تعمل على عدة أنواع مثال
بيانات. voidالمثال التالي يبين أنه إذا لم يتم استعمال مؤشرات إلى
; من نفس نوعها: يجب أن نعين للمؤشر عنوانا
//Program 5-11:#include<iostream.h>
void main) (int intvar;float flovar;int* ptrint;void* ptrvoid;ptr* ptrflovar;ptrint=&intvar;
//ptr int = &flovar; //Error //ptr flo = &intvar; //Error
ptrvoid=&intvar;ptrvoid=&flovar;
{
في المثال السابق يمكن تعيين عنوان المتغيرintvar إلي المؤشر ptr int ألنهما من النوع int*لكن ال
ألن ptrint إلى المؤشر flovarيمكننا تعيين عنوان المتغير . لكن يمكن* int والثانى من النوع *floatاألول من النوع
ألنه مؤشر إلىptrvoidتعيين أي نوع مؤشرات إلى المؤشر void.
90
لدوال :-لهنالك ثالث طرق لتمرير الوسائط . call-by-valueالتمرير بالقيمة -1 . call-by-referenceالتمرير بالمرجع -2 call by reference withالتمرير بالمرجع مع مؤشر -3
pointer arguments.; أن العبارة تستعمل إلعادة returnكما ذكرنا سابقا
; أنه يمكن تمرير قيمة من دالة مستدعاة ورأينا أيضا فيلدوال بالمرجع حتى يتسنى للدالة التعديل لالوسائط
++Cالبيانات األصلية للوسائط ،يستخدم مبرمجو المؤشرات لمحاكاة استدعاء الدوال بالمرجع . عند
استدعاء الدالة يتم تمرير عنوان الوسيطة ويتم ذلك بكتابة عامل العنوان للوسيطة المطلوب معالجتها . عندما يتم
*تمرير عنوان الوسيطة للدالة يتم استعمال العامل قيمة المتغير .لللوصول
البرنامجان أدناه يحتويان على إصدارين من دالة تقومبتكعيب عدد صحيح.
//Program 5-12:// Cube a variable using call-by-value#include<iostream.h>int cubeByValue)int(; // prototypeint main) ({int number = 5;cout <<” The original value of number is “
<<number<<endl;number = cubeByValue)number(;cout << “ The new value of number is “ << number<< endl;return 0;}int cubeByValue)int n({return n*n*n; // cube local variable n}
الخرج من البرنامج:
91
8.5المؤشرات في استدعاء الدوال
The original value of number is 5The new value of number is 125
يقوم هذا البرنامج بتمرير المتغير كوسيطة للدالة; طريقة التمرير بالقيمة حيث تقوم الدالة مستخدما
cubebyvalue المتغير بتكعيب number بإرجاع وتقوم .return باستخدام العبارة main لدالة لالنتيجة
يتم تمرير عنوان المتغيرالتالي في البرنامجnumber كوسيطة للدالة cube by referenceحيث تقوم
.nptr المؤشر إلي يشير التيالدالة بتكعيب القيمة
//Program 5-13:// cube a variable using call-by-reference with a pointer argument#include<iostream.h>void cubeByReference )int *(; // prototypemain) ({int number = 5;cout<< “ The original value of number is “ << number <<endl;cubeByReference)&number(;cout<< “ The new value of number is “ << number <<endl;return 0;}void cubeByReference )int *nPtr({*nPtr = *nPtr * *nPtr * *nPtr; // cube number in main}
الخرج من البرنامج:
The original value of number is 5The new value of number is 125
92
يتم تمرير عنوان متغيرالتينذكر هنا أن الدالة تعريف مؤشر يحمل قيمةفيها كوسيطة لها يجب أن يتم
; :-cubeByReference الدالة فيالعنوان ، فمثالvoid cubeByReference )int *nptr(
يشير إلى cubeByReference الدالة فيالمصرح كوسيطةintegerسيتم تمرير عنوان لمتغير من النوع أنه
وهى ال ترجعnptr المؤشر فيلها ويتم تخزين العنوان .mainلدالة لقيمة
; أنه اإلعالن عن الدالة يكفىفيوكما ذكرنا سابقا سيتم تمريره كوسيطة للدالةالذيفقط ذكر نوع المتغير
cube byدون ذكر اسم المتغير ثم اإلعالن عن الدالة reference كاآلتي-:
void cubeByReference )int *(
93
; كيف يمكن الوصول إلى العناصر المخزنة عرفنا سابقا في المصفوفات باستعمال اسم المصفوفة وفهرس العنصر.
المثال التالي يوضح هذا:int array1[3]={1,2,3};
for )int j=0;j<3;j++(cout<<endl<<array1[j];
كاآلتي:array1يعرض الجزء السابق عناصر المصفوفة 123
; باستخدام يمكن الوصول إلي عناصر المصفوفات أيضاالمؤشرات.
المثال التالي يوضح كيف يمكن الوصول إلى عناصرنفس المصفوفة السابقة باستعمال المؤشرات:
int array1[3]={1,2,3};for )int j=0;j<3;j++(cout<<endl<< *)array1+j(;
; يعرض هذا الجزء: أيضا123
array1[j] له نفس تأثير التعبير (;array1+j*)التعبير وذلك لآلتي:; للتعبير(array1+j*) لذا يكون التعبير j=1افرض أن مرادفا
(*array1+1)ويمثل هذا محتويات العنصر الثاني في وإن اسم المصفوفة يمثل عنوانهاوهوarray1المصفوفة
array+1عنوان أول عنصر في المصفوفة، ولهذا فالتعبير يعنىarray1+2يعنى عنوان العنصر الثاني في المصفوفة و
عنوان العنصر الثالث في المصفوفة ، ولكننا نريد طباعة قيم وليس عناوينها، لهذا استعملنا عامل arrayعناصر المصفوفة
المواربة للوصول إلى قيم عناصر المصفوفة.
94
المؤشرات والمصفوفات 9.5
; السالسل هي مجرد مصفوفات من كما ذكرنا سابقا لذا يمكننا استخدام المؤشرات مع أحرفcharالنوع
السالسل مثلما يمكن استخدامه على عناصر أي مصفوفة. المثال التالي يتم فيه تعريف سلسلتين واحدة باستعمال
المصفوفات كما في أمثلة السالسل السابقة واألخرىباستعمال المؤشرات:
char str1[ ] =”with array";char str2[ ] =”with pointer";cout <<endl<<str1;cout <<endl<<str2;str2++;cout <<endl<<str2;
تتشابه السلسلتان السابقتان في عدة نواحي إال أن str2 هو عنوان أي ثابت مؤشر بينما str1هنالك فرق مهم :
هو متغير مؤشر.( يبين كيف يبدو هذان النوعان في الذاكرة:5-2الشكل )
ألنه مؤشر ولكن بزيادته سيشير str2لذا يمكننا زيادة إلى الحرف الثاني في السلسلة وعليه الخرج من المثال
السابق:-with arraywith pointerith pointer
95
المؤشرات والسالسل 01.5
W
I
T
H
A
R
W
I
T
H
A
R
2rtS
1rtS
سلسلة معرفة كمؤشر retniop htiw" = 2rts *rahc”
سلسلة معرفة كمصفوفةyarra htiw" = 1rts rahc”
(يوضح محتوى الذاكرة في حالتي 5-2شكل )التعريف كسلسلة والتعريف كمؤشر
التعابيرفييمكن أن تكون المؤشرات معامالت الحسابية وفى تعابير التعيين والتعابير العالئقية . سنتطرق
يمكن أن تكون المؤشرات معامالت لهاالتيهنا للعوامل وكيفية استعمال هذه العوامل مع المؤشرات .
أو نقصان المؤشرات يمكن استعمال )++( أو )--( لزيادة; إضافة متغير صحيح للمؤشر بمقدار واحد كما يمكن أيضا عن طريق استعمال العامل )+( أو العامل )=+( ويمكن
نقصان متغير صحيح من مؤشر عن طريق استعمال )-( أو; نقصان أو زيادة مؤشر مؤشر آخر.ل)=-( كما يمكن أيضا
،int v[10] أنه تم اإلعالن عن مصفوفة افترض في 3000 المصفوفة العنوان فييحمل العنصر األول
الذاكرة.; أنه تم تمهيد مؤشر افترض لعنصرل ليشير vptr أيضا
هي vptr وعليه قيمة المؤشر v[0] المصفوفة فياألول يبين هذا:-(5-3) ، الشكل 3000
بإحدىvلمصفوفة ل ليشير vptrيمكن تمهيد المؤشر العبارتين التاليتين:
vptr = v;vptr = & v[0];
3000 هو v المصفوفة في v[0]عنوان العنصر وذلك ألن عناصر3004 هو v[1]وعنوان العنصر
integer عبارة عن متغيرات صحيحة هي vالمصفوفة من الذاكرة، وعليه عند إضافة أو4bytes تمثل واستخدام
من مؤشر تتم إضافة المتغيرintegerطرح متغير صحيح ; يعتمد علىوالثاني الذاكرة في حجم المتغير فيمضروبا
4bytesنوع المتغير حيث يحتل المتغير الصحيح كما ذكرنا
96
11.5استعمال العوامل الحسابية مع المؤشرات
]0[V ]1[V ]2[V ]3[V .………
2103 80030003 4003
.rtpv
ليشير للعنصر rtpv( تمهيد 5-3شكل )األول في المصفوفة
; يعتمد ذلك1byte يحتل char الحرفيوالمتغير وعموما; العبارةالتالي bytesعلى عدد الـ يحتلها المتغير ، فمثال
التالية :vptr +=2;
بافتراض أن المتغير vptrلمؤشر ل 8إضافة لتؤدى من الذاكرة.4bytesالصحيح يحتل
:- delete و new إدارة الذاكرة باستعمال العوامل تستعمل المصفوفة لتخزين عدد من الكائنات أو المتغيرات
فالعبارة:int ar1[50];
أسلوبهي عدد صحيح فالمصفوفات 50تحجز الذاكرة ل مفيد لتخزين البيانات لكن لها عائق مهم : علينا معرفة
معظمفي وقت كتابة البرنامج . فيحجم المصفوفة أثناءإلي سنحتاج التاليالحاالت قد ال نعرف كمية الذاكرة
تشغيل البرنامج.; للحصول على كتل من الذاكرة ++Cتزود ; خاصا : أسلوبا :- new العامل
كتل ذاكرة ذات حجم معين ويعيدnewيخصص العامل ; newنقطة بداية كتلة الذاكرة تلك، يحصل العامل لمؤشرا
; أثناء تشغيل البرنامج . على الذاكرة ديناميكيا:هي newالصورة العامة لكتابة العامل
p-var = new type;حيث:-
p-varمتغير مؤشر يتم فيه تخزين عنوان بداية كتلة : تسمح بتخزينnewالذاكرة المخصصة بواسطة العامل
.typeمتغير من النوع :- delete العامل
إذا تم حجز العديد من كتل الذاكرة بواسطة العاملnew النهاية حجز كل الذاكرة المتوفرةفي سيتم
وسيتوقف الحاسوب عن العمل . لضمان استعمال آمن delete عامل يسمى newوفعال للذاكرة يرافق العامل
نظام التشغيل .ليعيد تحرير الذاكرة يبين كيف يتم الحصول علىالتالي الجزء من البرنامج
ذاكرة لسلسلة :char * str=” It is the best;”.
int len = strlen)str(;char*ptr;ptr= new char[len+1];
97
strcpy)ptr,str(;cout<<”ptr=”<<ptr;delete[ ] ptr ;
يليها نوع new األساسية الكلمة تم استعمال يقوم،المتغيرات التي سيتم تخصيصها وعدد تلك المتغيرات
len+1 إلى ويحتاج charالمثال بتخصيص متغيرات من النوع ينشئ1 الرقم ،str طول السلسلة lenمنها حيث تساوي
; للحرف الخامد ; إضافيا ينهي السلسلة ويعيد العاملالذيبايتاnew يشير ; التي تم بداية قطعة الذاكرة إلى مؤشرا
تخصيصها.تم استعمال المعقفات للداللة على أننا نخصصذاكرة لمصفوفة .
ptr =new char[len+1]; :العبارة
delete [ ] ptr;.ptr المؤشر إليها يشير التيتعيد للنظام كمية الذاكرة
أننا نقومل تشير delete العامل التي تليالمعقفات [ ] استعمالها إذا كنا نقوم بحذفلبحذف مصفوفة، ال نحتاج
.deleteمتغير واحد بواسطة العامل
: This المؤشر ; يسمى ; خاصا يشيرthisيمتلك كل كائن في فئة مؤشرا
إليه، وباستخدام هذا المؤشر يستطيع أي عضو دالي في الفئةمعرفة عنوان الكائن الذي استدعاه .
المثال التالي يوضح هذا :-
//Program 5-14:#include<iostream.h>class where { private:
char chararray[10]; public://Continued
void reveal) ({ cout <<”My Objects address is “<<this;}; main) ({
98
where w1,w2; w1.reveal) (; w2.reveal) (;}
، ويطلبwhereينشئ هذا البرنامج كائنات من النوع ، والتي) (revealمن كل منها عرض عنوانه باستعمال الدالة
.thisتعرض قيمة المؤشر الخرج من البرنامج يبدو كالتالي:
My object’s address is ox8f4effecMy object’s address us ox8f4effe2
عن عنوان Bytes 10 يبتعد w2نالحظ إن عنوان الكائن w1وذلك ألن البيانات في كل كائن تتألف من مصفوفة من ، 10 Bytes.
كأي مؤشر كائنات آخر، لذاthisيمكن معاملة المؤشر يمكن استخدامه للوصول إلى بيانات الكائن الذي يشير إليه
كما هو مبين في البرنامج أدناه.
//Program 5-15:#include<iostream.h>class test { public: test)int=0(; void print) ( const; private: int x; };void test::print) ( const//Continued{ cout <<” X=”<<x<<endl<<”this-> x= “<<this->x<<endl; <<”)*this(.x=”<<)*this(.x<<endl;}
main ) ({ test a)12(; a.print) (; return 0;
99
}
; بطباعة printوللتوضيح فإن العضو الدالي x يقوم أوال باستعمالxمباشرة، ثم يستعمل طريقتين للوصول إلى
:-thisالمؤشر .)->(باستعمال العامل األولى: .).(باستعمال العامل الثانية:
، عندما نقومthis*الحظ األقواس التي تحيط بـ للوصول إلى أعضاء الفئة نستعمل).(باستخدام العامل
،* له أولوية أعلى من العامل ).(األقواس، وذلك ألن العامل كاآلتي:this.x *وعليه بدون األقواس يتم تقييم التعبير
*)this.x( والذي ينتج عرض رسالة خطأ من المصرف ألن العامل
ال يستخدم مع المؤشرات.).( سنتطرق لها عندthisهنالك استعماالت أخرى للمؤشر
تحميلنا للعوامل بشكل زائد.
100
المصفوفة هي عبارة عن مجموعة متتابعة من العناصر المحدودة التي تكون جميعها من نفس نوع البيانات.
يعلن عن المصفوفات تحديد نوع عناصر المصفوفة ثم ; بعدد العناصر فيها بين قوسين اسم المصفوفة متبوعا
; لتخزين مائة عنصر من النوع [ ] في مصفوفةint، فمثالb: نكتب
int b[100]; تستخدم المصفوفات من النوعcharلتخزين سالسل
األحرف.:يمكن تمهيد مصفوفة أحرف عند ثابت سلسلي كاآلتي
char a[10] = “computer”;يسمى بالحرف ; ; خاصا تنتهي كل السالسل بحرفا
.’(0)‘\الخامد والذي يتم تمثيله بتتابع الهروب :يمكن تمهيد السالسل باستخدام الئحة قيم كاآلتي
char a[10] = {‘c’, ‘o’, ‘m’, ‘p’, ‘u’, ‘t’, ‘e’, ‘r’ , ‘\0’}; تعيد الدالةstrlen) (طول السلسلة الممرة كوسيطة
لها. تستخدم الدالةstrcpy) (لنسخ سلسلة إلى سلسلة
أخرى. تقوم الدالةstrcat) (.بإلحاق السالسل تقارن الدالةstrcmp) (.بين سلسلتين المؤشرات هي عبارة عن متغيرات تستخدم كعناوين
للمتغيرات في الذاكرة.
101
الملخص:
1
تقوم باآلتي:++C/ أكتب عبارات 1.fطباعة العنصر السابع في مصفوفة أحرف تدعى -1 إدخال قيمة العنصر الرابع في مصفوفة أعداد صحيحة-2
b.
/ ما هو الخطأ في العبارات التالية:2a\ char str [5];
cin >>str; // user types hellob\ int a[3];
cout <<a[1] << “ “ << a[2]<<“ “<< a[3] <<endl;c\ float f[3] = { 1.1 , 10.01, 100,001, 1000.0001 } ;d\ double d[2][10]; d[1, 9] = 2.345;
/ ما الغرض من البرنامج التالي:3#include <iostream.h> int WhatIsThis )int[ ] ,int(;main{const int arraysize = 10;int a[arraysize] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int result = WhatIsThis )q, arraysize(;cout << “ Result is: “ << result << endl;return 0;}
int WhatIsThis )int b[ ], int size({
if )size == 1(return b[0];else return b[size –1] +WhatIsThis[b, size –
1];}
/ أكتب إعالناb لمصفوفة أعداد صحيحة تدعى4intArrayوالتي تحتوي على ثالثة صفوف
وعمودين.
102
األسئلة
/ أكتب برنامجاb يقوم بطباعة العنصر األصغر من5 عناصر مصفوفة تحتوي على ثالثة صفوف وثالثة
أعمدة. صحيحة لكل من اآلتي++C/ أكتب عبارة 6
)إفترض أنه تم اإلعالن عن عددين صحيحينValue1 و Value2 وتم تمهيد قيمة المتغير value1
( :200000عند اإلعالن عن مؤشرiptr ليشير إلى متغير من النوع int. تعيين عنوان المتغيرvalue1 إلى المؤشر iptr. طباعة القيمة التي يشير إليها المؤشرiptr. تعيين القيمة التي يشير إليها المؤشرiptrإلى المتغير
value2. طباعة قيمة المتغيرvalue2. طباعة عنوان المتغيرvalue1. طباعة العنوان المخزن في المؤشرiptrهل تتساوى( .
؟(value1هذه القيمة مع عنوان المتغير
103
الوحدة السادسة
I( sessalC(( - Iالفئات)0.6
الوحدة: هذه بنهاية ستتعرف على كيفية إنشاء الفئات في لغةC++..ستتعرف على كيفية إنشاء واستعمال كائنات الفئاتستتعرف على كيفية الوصول إلى األعضاء البيانية
والدالية في الفئة. ستتعرف على مفهوم البنيات في لغةC++.
هو الكائنات التي++Cأساس البرامج المكتوبة باللغة عندما يكونيتم إنشاؤها بواسطة فئة تستعمل كقالب ف
البرنامج ال يكونفيهنالك الكثير من الكائنات المتطابقة ; وصف كل واحد منها على حدة ، من تطويراألفضلمنطقيا
مواصفات واحدة لكل من هذه الكائنات وبعد تحديد تلك المواصفات يمكن استخدامها إلنشاء قدر ما نحتاج إليه من
OOP فيالكائنات تسمى مواصفات إنشاء الكائنات هذه بالمالمح األربعة++C تتميز الفئة في .(Class)فئة
التالية :-/اسم الفئة والذي يعمل كنوع البيانات الذي ستمثله الفئة.1 data)/مجموعة من األعضاء البيانية في الفئة 2
members)حيث يمكن أن تحتوى الفئة على صفر أو أكثر .++Cمن أي نوع من أنواع البيانات في
member)/مجموعة من األعضاء الدالية 3 -1functions)معرفة داخل الفئة وهي تمثل مجموعة
/4العمليات التي سيتم تنفيذها على كائنات الفئة. وتكتب قبل(access specifiers)محددات وصول
األعضاء البيانية واألعضاء الدالية لتحدد إمكانية الوصول إلى هذه األجزاء من األجزاء األخرى في
البرنامج.
104
مقدمة 1.6
يليهاclassيتألف تعريف الفئة من الكلمة األساسية ويجب{ }اسم الفئة ثم جسم الفئة بين قوسين حاصرين
أن ينهي تعريف الفئة فاصلة منقوطة أو عبارة إعالن عن:; class anyclass { /* classكائنات تنتمي إلى الفئة فمثال
body*/ };أوclass anyclass { /* class body */ } obj1, obj2; ما تكتب الفئة ; التالي في على النحو++C فيغالبا
class class_name{private: data :البرنامجmemberspublic: member functions}; التاليالمثال
stack :-// This creates theيوضح كيفية تعريف فئة تدعى class stack >class stack {private: int stck[SIZE]; int tos;public: void init ) (; void push)int i(;
int pop ) (;};
105
هي طريقة كما عرفنا سابقاb أن المصفوفة لتخزين البيانات ولكنها غير مناسبة في الكثير من
يمكن إنشاء بنيات تخزين أخرى كاللوائحالحاالت . (stacks) والمكدسات (linked lists)المرتبطة
. كل من بنيات التخزين هذه(queues)والصفوف لها حسناتها ومساوئها وتختلف فيها الطريقة
التي يتم استخدامها للوصول إلى البيانات المخزنة هو نوع من بنيات التخزين ( stack ) المكدس فيها .
يستخدم عندما نريد الوصول إلى آخر عنصر تمb لـlifoتخزينه . يشار إلى هذه البنية عادة اختصارا
last in first outهو bوالتي تعنى )المدخل آخرا .)bتستطيع المكدسات المخرج أوال(stacks)تخزين
أي نوع من البيانات . لكن كما هو الحال مع المصفوفات يخزن كل مكدس نوعاb واحداb من
عندما نضعالبيانات ، ولكن ليس خليطاb من األنواع. في(push)قيمة في المكدس ، يقال أننا دفعناها
المكدس ، وعندما نخرج القيمة منه يقال أننا . يبين الشكل التالي كيف يبدو هذا:(pop)سحبناها
تستعمل عادة لتمثيل المكدس مصفوفة يتم فيها تخزين البيانات ، ومؤشر يشير إلى أعلى المكدس
داخل جسم الفئة يتم)آخر عنصر في المكدس ( . اإلعالن عن األعضاء البيانية واألعضاء الدالية ومحددات
يتمالوصول لها وفيما يلي سنتعرف على هذه األجزاء . اإلعالن عن األعضاء البيانية في الفئة بنفس الطريقة التي يتم بها اإلعالن عن المتغيرات باستثناء أنه ال يمكننا تمهيد األعضاء البيانية عند اإلعالن عنها، يمكن أن تكون األعضاء
; في الفئة++Cالبيانية من أي نوع بيانات في الـ فمثالstack: تم اإلعالن عن األعضاء البيانية كما يلي int
stck[SIZE];int tos; تحتوى الفئةstack على بندى بيانات من tos ومتغير int عناصرها من النوع stckهما مصفوفة
; . الحظ أن هذه التعريفات ال تعطى intالنوع أيضا; وتحدد أنهاهي قيمة أيالمتغيرات فقط تعطيها اسما
تتطلب مساحة معينة من الذاكرة حيث يتم تخصيص مساحة stackيمكن لمستخدمي الفئة الذاكرة بعد إنشاء الكائنات.
إنجاز العديد من العمليات على الكائنات التابعة لها ، يتم اإلعالن عن هذه العمليات داخل جسم الفئة ويطلق عليها
106
دفع 4hsup
سحب pop
23
1
ويتم تصريحها(member functions) األعضاء الدالية أو:; في الفئة تم تصريح األعضاءstackداخل جسم الفئة ، فمثال
void init ) (;void push )int i(;int popالدالية كاآلتي : و) ( stack ،Pop مواصفات الفئة فيهنالك ثالث داالت ) (;
Push ) (و int) (. ال تعيد الدوال int) ( , Push) ( قيمةأي . تسمى الدوالint قيمة من النوع ) (Popبينما تعيد الدالة
يتم .member functionsالمعرفة داخل الفئة أعضاء دالية تحديد إمكانية الوصول إلى أعضاء الفئة )بيانات ، أعضاء
وهي ++Cدالية( باستخدام ثالث كلمات أساسية في public عام( و( private )خاص( وprotected)محمي(
العضو.) : (والتي تتم كتابتها داخل جسم الفئة تليها نقطتان في الفئة يمكن الوصول إليه من أي مكانpublicالعام
داخل البرنامج.
العضو المحمىprotectedفي الفئة يمكن الوصول إليه فقط من فئته أو الفئات المشتقة منها كما
. ; سنرى الحقا العضو الخاصprivateيمكن الوصول إليه فقط من
األعضاء الدالية في فئته والفئات الصديقة لها كما.; سنرى الحقا
كل البيانات خاصة وكل األعضاءstack الفئة في ألننا نريد أن ++cالعامة فى الحالة هيالدالية عامة وهذه
تكون محميةأن ال يمكن الخارجينخفى البيانات عن العالم بينما نريد أن تكون األعضاء الدالية عامة حتى تستطيع
األجزاء األخرى من البرنامج استدعائها.
من الفئة هو استعمالهااألساسيعرفنا أن الهدف ولكن كيف يتم إنشاء الكائنات ؟.كأساس إلنشاء الكائنات
يمكن إنشاء الكائنات باستعمال نفس التركيب; وذلك int كـ أساسيالمستخدم إلنشاء متغير من نوع مثال
تتم معاملتها كأنواع متغيرات كما تتم++C في الكائنات أن
107
إذا لم يتم ذكر محدد وصول لعضو في فئة ما سيفترض المصرف أن محدد الوصول
.privateلهذا العضو هو
معاملة الفئات كأنواع بيانات وعليه إلنشاء كائن تابع للفئةstack-:نكتب
stack stack1; عند تنفيذ العبارة يحسب البرنامج حجم الكائن
ويخصص مساحة كافية له من الذاكرة ويعطى مساحة ; . وبنفس الطريقة يمكننا إنشاءstack1الذاكرة هذه اسما
قدر ما نشاء من الكائنات :-stack stack1, stack2 ,stack3;
التفاعل مع الكائنات:- يتم التفاعل مع الكائنات من خالل استدعاء أحد
الكائن.إلى يبدو كإرسال رسالة والثانيأعضاءها الدالية تركيب مؤلف من قسمين : اسم الكائن واسمإلىنحتاج ويتم ربط اسم الكائن واسم الدالة بواسطةالداليالعضو
أعضاء الفئة.إلىنقطة).( تسمى عامل الوصول
scope resolution operator عامل دقة المدى:- يتم تصريح األعضاء الدالية داخل جسم الفئة ولكن قد
تعريف أحد األعضاء الدالية خارج جسم الفئة،إلىتحتاج تبع لها وإالي التي الفئة اسم اسمهعندها يجب أن يتضمن من معرفة المصرفلكي يتمكنلن تكون هنالك طريقة
. يتم ربط اسم الدالةالدالي إليها العضو ينتمي التيالفئة مع اسم الفئة باستعمال ما يسمى بعامل دقة المدى.
التالييتألف هذا العامل من نقطتين مزدوجتين :: ، المثال .stack الفئة إلى التي تنتمي Pushيوضح تعريف الدالة
void stack::push)int i({ if)tos==SIZE( {
cout << “stack is full.\n”;return;
} stck[tos] = i; tos++;}
قمناالتي stack يوضح كيفية استخدام الفئة البرنامج التالي.بتعريفها
//Program 6-1:
108
#include<iostream.h>const int SIZE= 100;// This creates the class stack.//Continuedclass stack {private: int stck[SIZE]; int tos;public: void init ) (; void push )int i(; int pop ) (;};
void stack:: init ) ({ tos = 0;}void stack::push )int i({if )tos == SIZE ( {
cout << “Stack is full.\n”;return;
} stck[ tos] = I; tos++;}
int stack::pop) ({ if)tos == 0( {
cout << “Stack underflow.\n” ;return 0;
}tos--; return stck[tos];}//Continuedint main ) ({ stack stack1, stack2; // create two stack objects
109
stack1.init ) (; stack2.init ) (;
stack1.push )1(; stack2.push )2(;
stack1.push )3(; stack2.push )4(;
cout << stack1.pop) ( << “ “; cout << stack1.pop) ( << “ “; cout << stack2.pop) ( << “ “; cout << stack2.pop) ( << “\n“;
return 0;}
عندما نسحب البيانات التي قمنا بدفعها في المكدستظهر بترتيب معكوس وعليه الخرج من البرنامج :
3 1 4 2
(tos)++الحظ أننا استعملنا العاملين المتصدر . يمثلstck لمعالجة فهرس المصفوفة --(tos)والالحق . 0 أعلى المكدس وقد تم تمهيده عند tosالمتغير
; ثمtosعند دفع البيانات في المكدس تتم زيادة أوال; إلى مكانtosيتم استعماله كفهرس لذا نجد أن يشير دائما
واحد قبل بند البيانات األخير المدفوع في المكدس.; ثم يتم عند سحب البيانات يتم الوصول إليها أوال
يشير مباشرة إلىtos لذا فإن --(tos)إنقاص الفهرس أعلى المكدس.
110
تذكر أن البيانات الخاصة ال يمكن الوصول إليها إال من قبل األعضاء الدالية التابعة للفئة وعليه
:-++C فيعبارة كالتالية غير مقبولة stack1.tos=0 // Error tos is private
كيفية الوصول إلى األعضاء العامة فيالفئة:
للوصول إلى األعضاء العامة في فئة ما، يمكن استخدام:
. ).(إسم كائن تابع للفئة وعامل النقطة -1مرجع إلى كائن في الفئة وعامل النقطة.-2.)->(مؤشر إلى كائن في الفئة والعامل -3
البرنامج التالي يوضح هذا:
//Program 6-2:#include<iostream.h>class count {public: int x; void print) ( { cout <<x<<endl;}};main) ({ count counter;//Continued*countrptr=&counter;cout<<”assign 7 to x and pring using the object’s name: “;counter.x=z;counter.print) (;cout<<”assign 8 to x and print using a reference: “;countref-x=9;cout <<countref.print) (;cout<<”assign 10 to x and print using a pointer: “;counterptr->x=10;counterptr->print) (;return 0;
111
هي طريقة لتجميع عدة بنود بيانات++Cالبنية في يمكن أن تكون من أنواع مختلفة . يتم استعمال البنيات
عادة عندما تشكل عدة بنود بيانات وحدة متميزة لكنها غير تنفذ++Cمهمة لتصبح فئة . وعلى الرغم من أن الفئة في
كل المهام التي تقوم بها البنيات لكن ال يزال هنالك الكثير من الحاالت التي تكون فيها البنيات مفيدة . وكمثال على
بنية:-struct part{int modelnumber;int partnumber;float cost;};
يليها اسمstructتتألف البنية من الكلمة األساسية البنية وأقواس حاصرة تحيط بجسم البنية. تنهى البنية
فاصلة منقوطة. يتألف جسم البنية عادة من عدة بنود بيانات يمكن أن
membersتكون من أنواع مختلفة تسمى هذه البنود أعضاء .
نكتب: partلتعريف متغيرات من النوع البنيوي part cp1,cp2;
; طريقة مختصرة لتعريف المتغيرات البنيوية هنالك أيضا حيث يتم وضع أسماء المتغيرات في مواصفات البنية
كاآلتي:struct part{int modelnumber;int partnumber;float cost;}cp1,cp2;
112
البنيــات
serutcurts7.6
شبيهة البنية ; والبنيات الفئات لكن المنطقي التركيب ناحية من بالفئة جدا; مختلفة بطرق تستعمل بينما وداالت بيانات على الفئة تحتوى عادة ، جدا
فقط. بيانات على البنية تحتوىإنها الفئات مع الحال هو كما بنية أي إنشاء إلى البنية مواصفات تؤدى ال،
إنشاؤها. يتم عندما البنية لشكل مواصفات مجرد
عامل النقطة للوصول إلى أعضاء البنيةيتم استعمال; مثلما يتم استعماله للوصول إلى األعض اء الدالية منتماما
; يمكننا أن نكتب:-ال كائنات ،فمثالcin>> cp1.part number;
ويكون اسم المتغير قبل النقطة بينما يكون اسم العضوالبياني بعدها.
تمهيد المتغيرات البنيوية:; كما يمكن تزويد قيم أولية للمتغيرات البنيوية تماما
; لتمهيد متغير بنيوي من النوع نفعل مع المصفوفات ، فمثالpart:نكتب
part cp1 = {6244,15,217.1};
عندcp1.modelnumberتؤدى هذه العبارة إلى تمهيد وتمهيد15 عند القيمة cp1.partnumber و6244القيمة
cp1.cost 217.1 عند القيمة.
إستعمال البنية: التي قمنا بتعريفها في األمثلة السابقةstackفي الفئة
نجد أن المصفوفة التي يتم فيها تخزين بنود البيانات مرتبطانstack الذي يشير إلى أعلى المكدس tosوالمتغير
ببعضهما إلى حد كبير لذلك من األنسب دمجهما في بنية ، stackويتم استعمال هذه البنية كعضو بياني واحد في الفئة
فيما يلي سنوضح كيف يكون هذا:
//Program 6-3:# include<iostream.h># define size 100sruct stackette//Continued{int stck[size];int tos;};
113
الوصول إلى أعضاء البنيةstcurts gnisseccA 8.6
class stack{ private:stackette st;public:void init) (;void push) int i(;int pop) (;};void stack :: init) ({st.tos=0;}void stack:: push)int i (;{if)st.tos== size({cout <<”stack is full.\n”;return;}st.stck[st.tos] = i;st.tos ++;}int stack:: pop) ({if)st.tos== 0( {cout <<”stack under flow.\n”;return 0;}st.tos--;return st.stck[st.tos];//Continued}int main) ({stack stack1;stack1.init) (;stack1.push)1(;stack1.push)2(;stack1.push)10(;cout<< stack1.pop) (<< “ “ ;
cout<< stack1.pop) (<< “ “ ;
114
return 0;
الخرج من هذا البرنامج :
2
هنا مصفوفة أعداد صحيحةstacketteتخزن البنية ومتغير يشير إلى أعلى المكدس. العضو البياني الوحيد في
وتشيرstackette اآلن هو متغير تابع للبنية stackالفئة st اآلن إلى األعضاء البيانية في stackاألعضاء الدالية للفئة
st.tos=0باستعمال عامل النقطة
يمكن القول أن البنية هي تجميع هامد لبنود البنيات بينما الفئة هي آلية نشطة للبيانات والداالت ، فالفئات
تشكل أساس البرمجة الكائنية المنحى بينما البنيات هي . نجد أن التركيب++Cجزء صغير في استعماالت
; ،إال أن أعضاء المنطقي للفئات والبنيات متطابق تقريبا الفئة تكون أعضاء خاصة بشكل افتراضي . أي إذا لم يتم
تكونprivate أو publicاستعمال الكلمات األساسية أعضاء الفئة خاصة.
115
البنيات مقابل الفئاتsessalC .sv stcurtS 9.6
أساس البرامج المكتوبة باللغةC++.هو الكائنات تأخذ الفئة فيC++:الشكل العام التالي
class classname {تحتوى الفئة على بيانات معرفة داخله وتسمى أعضاء
وعلى داالت تسمى أعضاء دالية(data members)بيانية (function members). يتم إنشاء الكائنات باستعمال نفس التركيب المستخدم
إلنشاء متغير من نوع أساسي . تعامل الكائنات فيC++كأنواع متغيرات كما تتم
معاملة الفئات كأنواع بيانات. إلنشاء كائنanyobj تابع للفئة anyclass:نكتب
anyclass anyobj;يتم التفاعل مع الكائنات باستدعاء أحد أعضائها الدالية
والذي يبدو كإرسال رسالة إلى الكائن.للتفاعل مع الكائنات تتم كتابة اسم الكائن واسم
العضو الدالي ويتم ربط اسميهما بواسطة نقطة ) . (تسمى عامل الوصول إلى أعضاء الفئة.
إذا تم تعريف عضو دالي خارج فئته يتم ربط اسم فئته بواسطة العامل ) :: ( والذي يسمى بعامل دقة المدى.
البيانات الخاصة ال يمكن الوصول إليها إال من قبل األعضاء الدالية التابعة للفئة.
البنية فيC++هي طريقة لتجميع عدة بنود بيانات يمكن أن تكون من أنواع مختلفة.
يتم استعمال البنيات عندما تشكل عدة بنود بيانات وحدة متميزة لكنها غير مهمة لتصبح فئة.
تتألف البنية من الكلمة األساسيةstructيليها اسم البنية وأقواس حاصرة تحيط بجسم البنية وتنهى البنية
فاصلة منقوطة.يتألف جسم البنية من عدة بنود بيانات يمكن أن تكون
من أنواع مختلفة وتسمى تلك البنود أعضاء.يتم استعمال عامل النقطة للوصول إلى أعضاء البنية
; مثلما يتم استعماله للوصول إلى األعضاء الدالية تمامامن الكائنات.
116
الملخص:
تقوم بإجراء complex/ أنشئ فئة تدعى 1العمليات الحسابية على األعداد المركبة.
العدد المركب يكون على الصورة :real part + imaginary part*i
i= √-1حيث لتمثيل البياناتfloatاستخدم متغيرات من النوع
complexالخاصة في الفئة، على أن تحتوى الفئة على الدوال اآلتية:
.دالة تقوم بجمع عددين مركبين.دالة تقوم بطرح عددين مركبيندالة تقوم بطباعة األعداد المركبة على
b يمثل الجزء الحقيقي ، a حيث (a, b)الصورة تمثل الجزء التخيلي.
كامالb الختبار الفئة التي++Cقم بكتابة برنامج قمت بإنشائها.
والتي تجرىRational/ أنشئ فئة تدعى 2.fractionsالعمليات الحسابية على الكسور
لتمثيل البياناتintاستخدم متغيرات من النوع الخاصة في الفئة) البسط والمقام (.
على دوال تقوم بالعملياتRationalتحتوى الفئة اآلتية:-
جمع عددين من النوعRational. طرح عددين من النوعRational. ضرب عددين من النوعRational. قسمة عددين من النوعRational. طباعة الكسور على الصورةa/b حيث يمثل a
المقام.bالبسط و
/ أوجد الخطأ في اآلتي:-3 البرنامج التالي هو جزء من تعريف فئة تدعى
Time:class Time {public: // function prototypesprivate:
117
األسئلة
int hour = 0;int minute = 0;int second = 0;};
scope/ ما هو الغرض من عامل دقة المدى ::4resolution operator.
.++C/ قارن بين مفهومي البنيات والفئات في 5
118
الوحدة السابعة
II( sessalC(( - II)الفئات
0.7
بنهاية هذه الوحدة: ستتعرف على المشيداتconstructors. ستتعرف على المهدماتdestructors. ستتمكن من إنشاء كائنات ثابتةConstant objects
.Constant member functionsوأعضاء دالية ثابتة ستتمكن من استعمال أعضاء بيانية ساكنة
Static data members وأعضاء دالية ساكنةStatic member functions.
بعض األحيان نحتاج لتمهيد الكائنات عند قيم معينةفي; فيقبل استعمالها تموالتي stack الفئة في البرنامج ،فمثال
; المتغير وذلك0 تم تمهيد قيمته عند tosتعريفها سابقا . ) (intباستعمال الدالة
) (int باستعمال دالة كـ 0 عند tosإن تمهيد المتغير ; في ; مفضال ; ليس أسلوبا ، أحد أسباب هذا أنOOPمثال يجب أن يتذكر ضرورة) ( mainالمبرمج الذي يكتب الدالة
stackاستدعاء هذه الدالة كلما تم استدعاء كائن تابع للفئة للكائنات بتمهيد نفسها عند إنشائها هذا++Cتسمح ، لذلك
التمهيد يتم استعمال دوال خاصة تسمى المشيدات. خاص يحمل نفس اسم الفئة ويتمدالي هو عضو المشيد:
استعماله لتمهيد الكائنات . عند استعمالstackيوضح كيف تبدو فئة النموذج التالي
.tosمشيد لتمهيد المتغير
//Program 7-1:// This creates the class stack.const int SIZE= 100;class stack { int stck[size]; int tos; public: stack) (; //constructor void push )int i(; int pop) (; };
. إعادة قيمةأي ال يحمل stackالحظ أن المشيد هي قيم عند استدعائها أي ال ترجع المشيدات ++C في
فقط تقوم بتمهيد الكائنات عند قيم معينة.
119
المشيداتsrotcurtsnoC
1.7
إن كل كائن يتم إنشاؤه سيتم تدميره في وقت ما لذا بإمكان كاتب الفئة كتابة مهدم بنفسه، يعمل هذا++Cفي
المهدم على إلغاء تخصيص الذاكرة التي كان المهدم قد; نفس اسم الفئة لكن خصصها للكائن . يحمل المهدم أيضا
; ال يملك المهدم قيمة إعادة.~تسبقه العالمة .أيضا لنرى كيفية عمل دوال المشيدات والمهدمات . المثال
stackالبرنامج يوضح إصدار جديد من الفئة
//Program 7-2:// using a constructor and destructor.#include<iostream.h>const int SIZE=100;//This creates the class stack.class stack {int stck[SIZE];int tos;public:stack) (; // constructor~stack) (; //destructorvoid push)int i(;int pop) (;};// stack’s constructor functionstack::stack) ({tos=0;cout<<”stack Initialized\n”;}// stack’s destructor functionstack::~stack) ({cout << “stack Destroyed\n”;//Continued}void stack :: push)int i({if)tos == SIZE( {cout << “stack is full.\n”;
120
المهدمات srotcurtseD 2.7
return;}stack[tos] = i;tos++;}int stack::pop) ({if)tos== 0( {cout<<”stack underflow.\n”;return 0;}tos--;return stck[tos];}int main) ({stack a, b; // create two stack objectsa.push)1(;b.push)2(;a.push)3(;b.push)4(;cout <<a.pop) (<<" ";cout <<a.pop) (<<" ";cout <<b.pop) (<<" ";cout <<b.pop) (<<"\n ";return 0;}
الخرج من البرنامج
Stack InitializedStack Initialized3 1 4 2Stack DestroyedStack Destroyed
Parameterized وسائط المشيدات
constructor -: المشيدات التي ال تأخذ وسيطات كالمشيد المستخدم
تسمى مشيدات اشتقاق ولكن من الممكنstackفي الفئة
121
تمرير وسائط إلى المشيدات بنفس الطريقة التي تمرر بهاإلى الدوال األخرى.
المثال البرنامج يحتوى على مشيد مع وسيطات.
//Program 7-3:#include <iostream.h>class myclass {int a, b;public:myclass)int i,int j( {a=i; b=j;}void show ) ( {cout <<a<<" " <<b;}};int main) ({myclass ob)3, 5(;ob.show) (;return 0;}
تم تمرير ) (myclassالحظ في تعريف المشيد واستعملت هاتين الوسيطتين لتمهيدj و iوسيطتين هما
.b و aالقيم يوضح المثال كيفية تمرير الوسائط عند إنشاء الكائن
فالعبارة :-myclass ob)3,4(;
وتقوم بتمرير القيمobتتسبب في إنشاء كائن يدعى ; تمرير قيم الوسائط باستعمال4 و 3 كوسائط. يمكننا أيضا
العبارة التالية:myclass ob= myclass )3,4(;
. ; ولكن العبارة األولى هي األكثر استخداما
Constructor المشيد أحادى الوسيطات :-with one parameter
في المشيد أحادى الوسيطات هنالك طريقة ثالثةلتمرير الوسيطة إليه. المثال التالي يوضح كيف يكون هذا:
//Program 7-4:#include<iostream.h>class X {int a;public:
122
X)int j( {a= j;}Int geta) ( {return a; }};int main) ({X ob = 99; //passes 99 to jcout<<ob.geta) (; // outputs 99return 0;}
يأخذ وسيطة واحدة . الحظ الطريقة xهنا المشيد . تم) (main داخل الدالة obالتي تم بها تعريف الكائن
وذلك بكتابة :-99 عند xتمهيد قيمة وسيطة المشيد x ob= 99
; إذا كنا نتعامل مع مشيد ذو وسيطة واحدة يمكننا وعموماتمرير الوسيطة إما بكتابة
ob)i( أو ob=i .; في ; مميزا يلعب المشيد أحادى الوسيطات دورا
البرمجة كائنية المنحى حيث يمكن استعماله لتحويل كائن منحى من فئة إلى فئة أخرى وذلك بتمرير الكائن كوسيطة
للمشيد يطلق على هذه مشيدات دالة تحويل.
متى يتم تنفيذ المشيدات والمهدمات :- يتم استدعاء المشيدات كلما تم إنشاء كائن ، ويتم
استدعاء المهدم لكل كائن قبل تدميره ، ولمعرفة متى يتمتنفيذ المشيدات والمهدمات أدرس البرنامج :
//Program 7-5:#include<iostream.h>class myclass {public:int who;myclass)int id(;~myclass) (;} glob_ob1)1(, glob_ob2)2(;
myclass::myclass)int id({cout<<”Initializing”<<id<<”\n”;who = id
123
}myclass::~myclass) (//Continued{cout<<”Destructing”<<who<<”\n”;}int main) ({myclass local_ob1)3(;cout <<"this will not be first line displayed.\n”;myclass local_ob2)4(;return 0;}
الخرج من البرنامج:
Initializing 1Initializing 2Initializing 3This will not be first line displayed.Initializing 4Destructing4Destructing3Destructing2Destructing1
كما رأينا في البرنامج السابق الكائنات المعرفة داخل يتم تنفيذ مشيداتها بترتيب إنشاء الكائنات) (mainالدالة
بينما يتم تنفيذ مهدماتها بعكس ترتيب إنشاء الكائنات وعليه local ob 2 يليه الكائن local ob 1 يتم تنفيذ مشيد الكائن
قبل مهدم الكائنlocal ob 2بينما يتم تنفيذ مهدم الكائن local ob 1.
يتم تنفيذ مشيدات الكائنات المعرفة داخل الفئة قبل تنفيذ; يتم تنفيذ مهدماتها بترتيب معكوس ) (mainالدالة وأيضا
.) (mainولكن بعد نهاية تنفيذ الدالة سنقوم++Cلنبرهن على مدى تنوع استعماالت فئات لغة
في البرنامج التالي بتعريف فئة لشيء مختلف : نوع بيانات ، يتألف هذا الوقت من ثالث(Time)جديد يمثل الوقت
124
بيانات الساعات، الدقائق والثواني، وسنسمى نوع البيانات Timeالجديد هذا
//Program 7-6:// Time class.#include<iostream.h>// Time abstract data type )ADT( definitionclass Time {public://ContinuedTime) (; void setTime )int, int, int( void printMilitery) (;void printStandard) (;private: int hour; int minute; int second;};Time::Time ) ( { hour = minute = second = 0; }void Time::setTime )int h, int m, int s({ hour = )h >= 0 && h < 24( ? h : 0; minute = )m >= 0 && m < 60( ? m : 0; second = )s >= 0 && s < 60( ? s : 0;}void Time::printMilitary) ({cout << )hour < 10 ? “0” : “ “ ( << hour << “:” << )minute < 10 ? “0” : “ “( << minute << “:” << )second < 10 ? “0” : “ “ (<< second;}void Time::printStandard) ({cout<< ))hour ==0 | | hour == 12 (? 12 : hour % 12( << “:” <<)minute < 10 ? “0” : “ “( << minute << “:” <<)second < 10 ? “0” : “ “ (<< second << )hour < 12 ? “ AM” : “PM”(;}int main ) (
125
{Time t;cout<< “The initial military time is: “;
t.printMilitary) (; //Continued cout<< endl <<“The initial standard time is: “; t.printStandard) (;t.setTime)13, 27, 6( ; cout<< endl << endl << “Military time after setTime is “; t.printMilitary) (; cout<< endl << “Standard time after setTime is “; t.printStandard) (; return 0;}
الخرج من البرنامج:
The initial military time is 00:00:00The initial standard time is 12:00:00 AM
Military time after setTime is 13:27:06Standard time after setTime is 1:27:06 PM
; تابع للفئة ; واحدا .t هو Timeينشئ البرنامج كائنا والذيTime يتم استدعاء المشيد tعندما يتم إنشاء الكائن
. يتم طباعة قيمة0 عند tيقوم بتمهيد بيانات الكائن باستخدام تنسيقين :tالكائن Standard ساعة.24: والذي يستعمل التنسيق-Military ساعة.12: والذي يستعمل التنسيق-
مرة أخرىt وطباعة الكائن setTimeثم يستعمل الدالة باستخدام التنسيقين.
لقد رأينا كيف يمكن استعمال متغيرات ثابتة ذات أنواع أساسية ، حيث تم استعمالها لتعريف ثابت كحجم
126
الكائنات الثابتة stcejbO tnatsnoC
3.7
; إذا كنا نريد مصفوفة ، يمكن جعل كائن تابع لفئة ما ثابتا ضمان عدم تغير البيانات في الكائن وكمثال على ذلك في
والتي رأيناها في البرنامج السابق، لنفترض أننا Timeالفئة سيكون من الجيد)noon )12, 0, 0نريد إنشاء كائن يدعى
ضمان عدم تغيير قيمة هذا الكائن لتحقيق هذا نكتب العبارةconst Time noon) 12, 0, 0(;
وتمهدTime في الفئة noonوالتي تعلن عن كائن ثابت .12عند قيمته
باستدعاء الكائنات الثابتة من قبل++Cال تسمح مصرفات األعضاء الدالية في الفئة لضمان عدم تعديل بيانات هذه
الكائنات ، ولكن قد نرغب في بعض األحيان في عرض قيمة هذه الكائنات والتي ال تؤثر بأي حال من األحوال على
بياناتها ، لحل هذه المشكلة يمكن للمبرمج اإلعالن عن وهي عبارة عن أعضاء دالية تضمن أنه(const)داالت ثابتة
لن يتم تغيير بيانات الكائن الذي استدعي من أجلها ، ولجعل; تتم كتابة الكلمة األساسية في تعريفconstعضو دالي ثابتا
العضو الدالي وتصريحه مباشرة بعد األقواس التي تلياسمه .
:-Time التابع للفئة printMilitaryأدناه يبدو العضو الدالي void Time::printMilitary) ( const{cout<< )hour < 10 ? “0” : “ “ ( << hour << “:” << )minute < 10 ? “0” : “ “( << minute << “:” << )second < 10 ? “0” : “ “ (<< second;}
البرنامج التالي يوضح استخدام الكائنات واألعضاءالدالية الثابتة:
//Program 7-7:class Time {public:Time) (;void setTime ) int, int, int(;void printMilitary) ( const;void printStandard) (const;private:int hour;int minute;int second;
127
};void Time:: setTime )int h, int m, int s({//Continuedhour = )h >=0 && h<24( ? h : 0;minute = )m >= 0 && m<60 ( ? m : 0;second = )s >= 0 && s<60( ? s : 0;}void Time::printMilitary) ( const{cout << )hour < 10 ? “0” : “ “ ( << hour << “:” << )minute < 10 ? “0” : “ “( << minute << “:” << )second < 10 ? “0” : “ “ (<< second;}
void Time::printStandard) ( const{cout << ))hour ==0 | | hour == 12 (? 12 : hour % 12( << “:” <<)minute < 10 ? “0” : “ “( << minute << “:” <<)second < 10 ? “0” : “ “ (<< second << )hour < 12 ? “ AM” : “PM”(;}int main ) ({const Time noon)12, 0, 0(;cout <<” noon = “ ;noon.printStandard;Time t;t.setTime )13, 27, 6(;cout<< endl << “military time after setTime is “;t.printMilitary ) (;cout<< endl;return 0;}
الخرج من البرنامج:
noon = 12:00:00 AMmilitary time after setTime is 13:27:06
128
Timeفي البرنامج السابق تم تعريف كائنين في الفئة . العضوانt على عكس اآلخر وهو noonأحدهما ثابت هو
ثابتان ال) (printMilitary و ) (printStandardالداليان يعدل كائنه لذاsetTimeيعدالن كائنهما لكن العضو الدالي
;. يمكننا استدعاء لكنt للكائن ) (setTimeلم يجعل ثابتا.noonليس للكائن
البيانات الساكنة :-أ() (instant)استعملنا حتى اآلن أعضاء بيانية مثيلية
أي أن هنالك نسخة واحدة منها لكل كائن يتم إنشاؤه ولكن قد نحتاج لمتغير ينطبق على كل كائنات الفئة ، لتحقيق ذلك
; ; ساكنا ; بيانيا فعندماstatic data memberنستعمل عضوا staticنعلن عن متغير في بيانات فئة ما على أنه ساكن
نعنى بذلك أنه ستكون هنالك نسخة واحدة فقط من هذا المتغير في الذاكرة وستتشارك كل الكائنات التابعة لهذه
الفئة في هذا المتغير بغض النظر عن عدد هذه الكائنات . قبل إنشاء أي كائن0يتم تمهيد كل المتغيرات الساكنة عند
. يتم تصريح المتغير الساكن ضمن الفئة باستعمال
ويتم تعريفه خارجها ، وذلك ألنه إذاstaticالكلمة األساسية افترضنا أن البيانات المعرفة داخل الفئة هي بيانات مثيلية
مكررة لكل كائن ، إذن لتعريف متغير يتواجد مرة لكل الفئة; علينا تعريفه خارج الفئة وتصريحه داخلها ليكون معروفا
لبقية أعضائها. لتوضيح استعمال وتأثير البيانات الساكنة ادرس المثال
البرنامج:
//Program 7-8:#include<iostream.h>class shared {static int a;int b;//Continuedpublic:
129
األعضاء الساكنة في الفئاتrebmem ssalc citatS 4.7
void set)int i,int j( { a=i; b=j;}void show) (;};int shared :: a; // define avoid shared :: show) ({cout <<” This is static a: "<< a;cout<<”\nThis is non_static b: " << b;cout << "\n";}int main) ({shared x, y;x.set)1, 1(; //set a to 1x.show) (;y.set)2, 2(; //change a to 1y.show) (;x.show) (; /* Here, a has been changed for both x and y because a is shared by both objects.*/return 0;}
الخرج من البرنامج:
This is static a: 1 This is non_static b: 1 This is static a: 2 This is non_static b: 2This is static a: 2 This is non_static b: 1
Static member األعضاء الدالية الساكنة ب()functions -:
يمكننا الوصول إلى البيانات الساكنة من أي عضو دالي في الفئة ولكن من الطبيعي استعمال نوع خاص من الداالت ينطبق على الفئة بأكملها وليس على كائن ما وهو
الداالت الساكنة . يتم تعريف العضو الدالي الساكن لكن استدعاءات هذهstaticبواسطة الكلمة األساسية
130
الدالة تتم من دون استعمال كائن معين بل يشار إلى الدالة من خالل ربط اسمها باسم الفئة بواسطة عامل دقة
المدى:: . ال يستطيع العضو الدالي الساكن اإلشارة إلى أي عضو دالي غير ساكن ألن الداالت ال تعرف أي شئ عن
كائنات الفئة وكل ما تستطيع الوصول إليه هو بيانات ساكنة ترتبط بالفئة ككل ، لذا يمكننا استدعاء الدالة الساكنة حتى
قبل إنشاء أي كائن . ولكن عند استعمال الدوال الساكنةيجب وضع القيود التالية في االعتبار:-
.this/ ال تمتلك األعضاء الدالية الساكنة المؤشر 1 /ال يمكن أن يكون هنالك إصدارين من نفس الدالة أحدهما2
ساكن واآلخر غير ساكن . / العضو الدالي الساكن كما سنرى فيما بعد ال يمكن أن3
.virtualيكون افتراضيا .const/ ال يمكن اإلعالن عن الدالة الساكنة على أنها 4
على أنهاget-resourceففي البرنامج تم تعريف الدالة بذكر اسمهاget-resourceساكنة. يمكن استدعاء الدالة
فقط دون أي كائن.
//Program 7-9:#include<iostream>class cl {static int resource;public:static int get_resource) (;void free_resource) ( {resource = 0;}};int cl :: resource; //define resourceint cl:: get_resource) ({if)resource( return 0 ; // resource alreay in useelse { resource = 1; return 1; //resource allocated to this object //Continued}}int main) ({cl ob1, ob2;
131
/* get_resource) ( is static so may be called independent of any object.*/if) c1 :: get_resource) (( cout << "ob1 has resource\n ";if) ! c1 :: get_resource) (( cout << "ob2 denied resource\n ";ob1.free_resource) (;if)ob2.get_resource) (( // can still call using object syntaxcout<<" ob2 can now use resource\n ";return 0;}
132
المشيد هو عضو دالي خاص يحمل اسم الفئة يستعمل لتمهيد الكائنات عند قيم معينة عند إنشاؤها .
.ال يحمل المشيد أي قيمة إعادةالمهدم هو عضو دالي يعمل على إلقاء تخصيص
الذاكرة التي خصصها المشيد للكائن. يحمل المهدم نفس اسم الفئة لكن تسبقه العالمة~. .ال يحمل المهدم أي قيمة إعادةمن الممكن تمرير وسائط إلى المشيدات ويتم ذلك
بنفس الطريقة التي تمرر بها إلى الدوال األخرى.يتم استدعاء المشيدات كلما تم إنشاء كائن، ويتم
استدعاء المهدم لكل كائن قبل تدميره.لكل ; العضو البياني الساكن هو متغير يكون منطبقا
كائنات الفئة. 0تم تمهيد المتغيرات الساكنة عند.يتم تصريح المتغير الساكن داخل الفئة باستعمال
ويتم تعريفه خارجها.staticالكلمة األساسية .تعريف أعضاء دالية ساكنة ; يمكن أيضايتم تعريف العضو الدالي الساكن باستعمال الكلمة
.staticاألساسية استدعاءات األعضاء الدالية الساكنة تتم من دون
استعمال كائن معين.يشار للدالة من خالل ربط اسمها باسم الفئة من عبر
عامل دقة المدى :: .ال يستطيع العضو الدالي الساكن اإلشارة إلى أي عضو
; إذا كنا دالي غير ساكن.يمكن جعل كائن تابع لفئة ما ثابتانريد ضمان عدم تغير األعضاء البيانية للكائن.
لإلعالن عن الكائنات الثابتة نستخدم الكلمة األساسية const.
يمكن تعريف أعضاء دالية ساكنة ال تغير الكائن الذي أستدعي من أجلها.
تتم كتابة الكلمة األساسية ; constلجعل عضو دالي ثابتا في تعريف العضو الدالي وتصريحه مباشرة بعد األقواس
التي نلي اسمه.
133
الملخص:
/ ما هو الخطأ في الجزء التالي من برنامج افترض:Timeالتصريح اآلتي في فئة تدعى
void ~Time )int( ; مع بيان++C في Friend ship/ ناقش مفهوم الصداقة 7
األوجه السالبة فيها.; لفئة تدعى 8 ; صحيحا Time/ هل يمكن أن يحتوى تعريفا
على كال المشيدين أدناه:-Time ) int h = 0, int m = 0, int s = 0(;Time) (;
/ أوجد الخطأ في تعريف الفئة التالي:9class Example {public:example ) int y = 10( { data = y ; }int get Incrementdata ) ( const {
return ++ data; }static get count ) ({cout << “ data is “ << data << endl;return count;}private:int data;static int count;};
/ ماذا يحدث إذا تم تحديد قيمة إعادة لكل من10.voidالمشيدات والمهدمات حتى ولو كانت
134
األسئلة
الوحدة الثامنةIII( - )III(sessalC(الفئات
0.8
األهداف:بنهاية هذه الوحدة:
الصديقة. الدوال من الغرض على ستتعرفالصديقة. الفئات على ستتعرفلتعمل العوامل تعريف إعادة كيفية على ستتعرف
الجديدة. األنواع معالعوامل تحميل تواجه التي القيود على ستتعرف
زائد. بشكل
; في فئة ما الوصول إلى يمكن لدالة ليست عضوا األعضاء الخاصة بتلك الفئة وذلك بجعل الدالة صديقة
friendلدوال تلك الفئة .عادة تفترض أعمال التغليف وإخفاء البيانات قاعدة أنه يجب أن ال تكون الداالت التي
; في الفئة قادرة على الوصول إلى بيانات ليست عضوا الكائن الخاصة والمحمية ، لكن هنالك حاالت يؤدى فيها هذا
إلى بعض الصعوبات لذا فالداالت الصديقة هي وسيلة لاللتفاف حول هذه القاعدة .لجعل دالة ما صديقة نكتب
; بالكلمة األساسية .friendاإلعالن عنها داخل الفئة مسبوقاالمثال التالى يبين كيف يكون هذا:
//Program 8-1:
#include<iostream.h>class myclass {int a, b;public:friend int sum)myclass x(;void set_ab)int i,int j(;};void myclass :: set_ab)int i, int j({a = i;b =j;}// Note: sum) ( is not a member function of any class.int sum)myclass x({/* Because sum) ( is a friend of myclass, it can directly access a and b. */return x.a + x.b;}int main) ({myclass n;n.set_ab)3, 4(;cout<<sum)n(;return 0;}
الخرج من البرنامج:
135
الدوال الصديقة snoitcnuF dneirF .8
1
7
ومن الجدير بالذكر أنه على الرغم من أن الدوال إال أن ذلك ال يتماشى++Cالصديقة تزيد من مرونة اللغة
مع فلسفة وجوب السماح لألعضاء الدالية التابعة للفئة فقط الوصول إلى البيانات الخاصة بالفئة ،ومن هنا يبرز
السؤال ما هو مدى الخطورة التي تتعرض لها سالمةالبيانات عند استعمال دالة صديقة؟
يجب تصريح الدالة على أنها صديقة من داخل الفئة التي ستصل إليها بياناتها ،لذا فالمبرمج الذي ال يستطيع
الوصول إلى الشيفرة المصدر للفئة ال يستطيع جعل الدالة صديقة ،وعليه ستبقى سالمة البيانات محافظ عليها وعليه
; على سالمة ; خطيرا الداالت الصديقة ال تشكل تهديداالبيانات .
الفئات كما الداالت يمكن أن تكون صديقة والسبب في استعمال داالت صديقة هو تسهيل االتصال بين الفئات حيث يمكن لفئة صديقة لفئة أخرى الوصول لكل األعضاء الخاصة المعرفة في الفئة األخرى . المثال البرنامج يبين
هذا://Program 8-2://using a friend class.#include<iostream.h>class TwoValues {//continueint a;int b;
136
هي) (sumفي البرنامج السابق الدالة ولكن بالرغمmyclassليست عضواb في الفئة
من ذلك يمكنها الوصول إلى األعضاء الخاصة .my classفي الفئة
b دالياb وليس دالة صديقة إال استعمل دائماb عضوا إذا كان هنالك سبب قوى يدفع إلى استعمال
.bدالة صديقة كما سنرى الحقاالفئات الصديقة
sessalC dneirF2-8
public:TwoValues)int i, int j( {a = i, b= j;}friend class Min;};class Min {public:int min)TwoValues x(;};int Min::min )TwoValues x({return x.a< x.b? x.a: x.b;}int main) ({TwoValues ob)10, 20(;Min m;cout<< m.min)ob(;return 0;}
الخرج من البرنامج:
10
كفئة صديقة للفئة Minتم اإلعالن عن الفئة TwoValues:في السطرالتالي
friend class Min;
في الفئةb وaلذلك تم الوصول إلى األعضاء الخاصة TowValues من قبل الفئة Min.
int Min::min )TwoValues x({return x.a< x.b? x.a: x.b;}
; ببعضهما مرتبطتين فئتين هنالك كان إذا الصديقة الفئات تستعمل كثيرا
. مباشر بشكل الخاصة األخرى بيانات إلى الوصول إلى تحتاج أحدهما أن لدرجة
بطريق تعديلها شخص ألي سيتيح هذا ألن عامة البيانات نجعل أن نريد ال أننا
ال وعليه األخرى الفئة مع صفات في مشتركة ليست هي الفئة أن الخطأ. كما
137
الوحيد األسلوب هو الصديقة الفئات استعمال فإن لذا الوراثة استخدام يمكن
األخرى. الفئة في الخاصة األعضاء إلى تصل الفئتين إحدى لجعل
يمكن تعيين قيمة كائن إلى كائن آخر باستعمال عالمة المساواة = شريطة أن تنتمي هذه الكائنات إلى نفس الفئة
ويؤدى هذا إلى أن يحمل الكائن الذي على يسار عالمةالمساواة قيمة الكائن على يمينها.
البرنامج التالي يوضح ذلك:
//Program 8-3:// Assigning objects.#include<iostream.h>class myclass {int i;public:void set_i)int n( {i=n; }int get_i) ( {return i ;}} ;int main) ({myclass ob1, ob2;ob1.set_i)99(;ob2=ob1; // Assign data from ob1 to ob2cout << " This is ob2’s i: " << ob2.get_i) ( ;return 0;}
الخرج من البرنامج
This is ob2’s i: 99
فقط إمكانية استخدام الفئاتCال تضيف ++; إلنشاء أنواع جديدة من البيانات بل وتتيح أيضا
للمستخدم العمل على هذه األنواع باستخدام نفس
138
تحميل العوامل بشكل زائدgnidaolrevO srotarepO .8
4
تعيين الكائنات tnemngissa tcejbO
.83
العوامل التي تستخدمها األنواع األساسية . وعندما; كـ + أو القدرة على–يعطي عامل موجود أصال
العمل على أنواع بيانات جديدة يقال أنه تم تحميله . يتم تحميل العوامل بشكلoverloadedبشكل زائد
;، الكلمة األساسية ; خاصا زائد بكتابة دوال تحمل اسماoperatorمتبوعة بالعامل المراد تحميله بشكل زائد
; لتحميل العامل + بشكل زائد نعرف دالة ، فمثال. +) (operatorتحمل االسم
عند تحميل العوامل بشكل زائد يجب مراعاة اآلتي:
139
بشكل زائد ،++C/ ال يمكن تحميل كل عوامل 1فمثالb العوامل التالية ال يمكننا تحميلها :
. *. :: :? / ال يمكن تغيير عدد المعامالت التي يأخذها2
العامل. / ال يمكن إنشاء عوامل جديدة غير موجودة3
كالعامل ** الذي يستخدم فيCأصالb في ++بعض اللغات للرفع األسى.
العامل المحملprecedence/ ال تتغير أولوية 4بشكل زائد.
خطأخ
طأ
تطبيقه عند زائد بشكل المحمل العامل بإمكان /5 األساسية( االنواع على )ليس الكائنات على
b ، الفئة منشئ يريدها عملية أي تنفيذ فمثال يعرض أن زائد بشكل + المحمل العامل بإمكانb كائنين بطرح يقوم حتى أو الشاشة على نصا
المراد العملية تكون أن المستحسن من ولكن لها تكون أن تنفيذها زائد بشكل المحمل للعامل
b العامل بطبيعة عالقة أصال .
/ بعض الفئات مالئمة الستخدام العوامل6 المحملة بشكل زائد على عكس البعض
اآلخر ،وبشكل عام يتم استعمال العوامل المحملة بشكل زائد مع الفئات التي تمثل أنواع
بيانات رقمية كاألوقات والتواريخ واألرقام ( كما يمكن أن تستفيد فئاتx+iyالمركبة )
السالسل أيضاb من العوامل المحملة بشكل
كيفية تعريف دالة العامل noitcnuf rotarepO .8
5
كعضو ما فئة في زائد بشكل عامل تحميل على تعمل التي الدالة تعريف يمكنللفئة. صديقة كدالة أو الفئة في
عندما تكونoperator functionتأخذ دالة العامل ; في الفئة الشكل العام اآلتي: عضوا
return_type operator#)arg_list({// operations}
:- حيثreturn_type هو قيمة إعادة الدالة : operator#
; للفئة التي تعمل على ; تابعا ; ما ترجع كائنا والتي غالبا من أيreturn_typeكائناتها ولكن يمكن أن يكون
نوع آخر.Operator++ كلمة أساسية في -: C.
# :- تستبدل بالعامل المراد تحميله بشكل زائد ،; إذا كنا نقوم بتحميل العامل + بشكل زائد فمثال
.operatorنكتب Arg_listوهى الئحة الوسيطات الممرة إلى الدالة -:
operator#والتي تحتوى على عنصر واحد إذا كنا نقوم بتحميل عامل ثنائي )+، -، /، ....( وتكون
أحادى )++،Cفارغة إذا كنا نقوم بتحميل عامل++ .).... ، --
Operationsالعمليات المراد من العامل المحمل -: بشكل زائد تنفيذها.
واآلن وبعد ان تعرفنا على كيفية كتابة دالة تقوم; يقوم ; مبسطا بتحميل عامل بشكل زائد ، إليك مثاال
ويقوم بتحميل العامل + ليعملlocبإنشاء فئة تدعى ; على كائنات هذه الفئة، أدرس البرنامج وانتبه جيدا
.+) (operatorإلى كيفية تعريف الدالة
//Program 8-4:#include <iostream.h>class loc {
140
int longitude, latitude;public:loc)( { }loc)int lg, int lt( { longitude = lg;latitude =lt;}void show) ( {cout << longitude <<” ”;cout<< latitude<< "\n ;" }loc operator+ )loc op2(;};
//Continued// Overload +for loc.Loc loc::operator+)loc op2({loc temp;temp.longitude = op2.longitude+ longitude;temp.latitude = op2.latitude+ latitude;return temp;}int main) ({loc ob1)10, 20(, ob2)5,30(;ob1.show) (;ob2.show) (;ob1= ob1+ ob2;ob1.show) (; return 0;}
الخرج من البرنامج:
141
10 205 3015 50
إن العامل + المحمل) ( mainالحظ في الدالة بشكل زائد يجعل عملية الجمع تبدو وكأنها تتم على
أنواع أساسية .ob1= ob1+ ob2;
+) (operatorوكما رأينا في البرنامج الدالة لها وسيطة واحدة على الرغم من أنها تقوم بتحميل
عامل الجمع + الثنائي الذي يعمل على قيمتين والسبب في ذلك أن المعامل على يسار العالمة +
thisيتم تمريره إلى الدالة بواسطة المؤشر والمعامل على يمين العالمة هو الذي يتم تمريره
كوسيطة للدالة ولذلك يتم اإلعالن عن الدالة كاآلتي:loc operator + )loc op 2(;
تعيين قيمة اإلعادة من) (mainيتم في الدالة ويتم هذا األمر في الدالةob1الجمع إلى الكائن
operator) (+ عن طريق إعادة كائن يدعى temp لتخزين نتائجtempبالقيمة حيث يتم استعمال الكائن
العمليات الحسابية وهو الكائن الذي تتم إعادته.وبطرق متشابهة يمكننا تحميل العوامل
و * و / بشكل زائد–الحسابية الثنائية األخرى كـ . ; أيضا
المثال التالي يقوم بتحميل ثالث عوامل إضافية في والعامل = والعامل ++.– : العامل locالفئة
//Program 8-5:#include<iostream.h>class loc {int longitude, latitude;public:loc) ( { }// needed to construct temporariesloc)int lg, int lt({
142
longitude = lg;latitude =lt;}void show) (cout << longitude<< " ";cout<< latitude<< "\n ;"
//Continued}loc operator+)loc op2(loc operator- )loc op2(;loc operator= )loc op2(;loc operator++;}// Overload + for loc.Loc loc:: operator+ )loc op2({loc temp;temp.longitude = op2.longitude+ longitude;temp.latitude = op2.latitude+ latitude;return temp;}// Overload - for loc.Loc loc:: operator- )loc op2({loc temp;// notice order of operandstemp.longitude = longitude- op2.longitude;temp.latitude = latitude- op2.latitude;return temp;}// overload asignment for loc.Loc loc:: operator= )loc op2({temp.longitude = op2.longitude;//Continuedtemp.latitude = op2.latitude;
143
return *this; // i.e., return object that //generated call
}// overload prefix ++ for loc.Loc loc:: operator++ ) ({longitude++ ;latitude++;return *this; }int main) ({loc ob1)10, 20(, ob2)5,30( , ob3)90, 90(;ob1.show) (;ob2.show) (;++ ob1; ob1.show) (; ob2 = ++ob1;ob1.show) (; ob2.show) (; ob1=ob2=ob3; ob1.show) (;ob2.show) (;return 0;}
الخرج من البرنامج:11 2112 2213 2290 9090 90
في البرنامج السابق::--) (operatorالدالة
Loc loc:: operator- )loc op2({
144
loc temp;// notice order of operandstemp.longitude = longitude- op2.longitude;temp.latitude = latitude- op2.latitude;return temp;}
- ) ( ترتيبoperatorالحظ في الدالة المعامالت في عملية الطرح. المعامل على يمين عالمة الطرح يتم طرحه من المعامل على يسار
عالمة الطرح وذلك ألن المعامل على يسار عالمة - ) (operatorالطرح هو الذي يقوم باستدعاء الدالة
يتم طرحها من بياناتob2وعليه بيانات الكائن .thisالكائن المشار إليه بالمؤشر
:-=) (operatorالدالة Loc loc:: operator= )loc op2({temp.longitude = op2.longitude;temp.latitude = op2.latitude;return *this; // i.e., return object that //generated call}
; بشكل زائدCفي ++ يكون العامل = محمال في كل الفئات بشكل افتراضي حتي لو لم تتم كتابة
operatorدالة لتحميله . في المثال السابق الدالة =) ( تقوم بنفس مهمة العامل = االفتراضي ولكن
في بعض األحيان يمكن للعامل = المحمل بشكلزائد تنفيذ مهام أخرى.
وهو الكائن الذي استدعى الدالة.thisتعيد الدالة *:++) (operatorالدالة
loc loc:: operator++ ) ({longitude++;latitude++;return *this;
145
}
كما الحظت في البرنامج ال تأخذ الدالةoperator) (++++ أي وسيطات وذلك ألن العامل
.thisأحادى . يتم تمرير المعامل باستعمال المؤشر و=) (operatorالحظ أن كال الدالتين
operator) (++تقوم بتغيير قيمة الكائن الذي يتم تعيين=) (operatorاستدعى الدالة ففي الدالة
قيمة جديدة للكائن على يسار العالمة = والذي قام يتم++) (operatorباستدعاء الدالة وفي الدالة
.1زيادة الكائن الذي استدعى الدالة بمقدار
++ كـ =- أوCيمكننا تحميل عوامل التعيين في ; الدالة التالية تقوم بتحميل ; . فمثال ; زائدا =+ تحميال
; في الفئة ; زائدا .locالعامل =+ تحميالloc loc:: operator+= )loc op2({loc temp;longitude = op2.longitude+ longitude;latitude = op2.latitude+ latitude;return *this;} الفرق بين العوامل الثنائية العادية كـ + وبين عوامل
التعيين كـ =+ هو أن عوامل التعيين تعدل الكائن; إذا كتبنا: الذي تم استدعاؤها من أجله فمثال
ob1 += ob2; للكائن=+) (operatorسيتم استدعاء الدالة
ob1 ويتم تعديله بجمع ob2.إليه
146
تحميل عوامل التعيين بشكل زائد .86
8.تحميل عامل بشكل زائد باستخدام دالة صديقة7
يمكننا تحميل عامل بشكل زائد باستخدام دالة صديقة لدوال الفئة المراد تحميل العامل ليعمل على كائناتها وبما أن الدالة الصديقة هي ليست
; في الفئة لذا فهي ال تمتلك المؤشر thisعضوا; ونعنى بذلك أن وعليه يتم تمرير وسيطاتها ظاهريا الدالة الصديقة التي تقوم بتحميل عامل ثنائي يتم تمرير وسيطتين لها بينما يتم تمرير وسيطة واحدة
للدالة الصديقة التي تقوم بتحميل عامل أحادى . عندما نقوم بتحميل عامل ثنائي باستخدام دالة
صديقة يتم تمرير المعامل على اليسار في الوسيطة األولى بينما يتم تمرير المعامل على اليمين في
وسيطة الدالة الثانية. المثال التالي يوضح كيفية تعريف دالة صديقة لتحميل
العامل +
//Program 8-6:# include <iostream.h>class loc{
//Continuedint longitude, latitude;public:loc) ( { }// needed to construct temporariesloc)int lg, int lt( {longitude = lg;latitude =lt;}void show) ( {cout << longitude<<" ;"cout<< latitude<< "\n ; "}friend loc operator+ )loc op1, loc op2(; // now a friend loc operator- )loc op2( ;loc operator= )loc op2(;loc operator++) (;
147
};// now , + is overloaded using friend function.loc operator+ )loc op1, loc op2(;{loc temp;temp.longitude =op1.longitude+ op2.longitude;temp.latitude = op1.latitude+ op2.latitude;return temp;}// overload - for loc.Loc loc:: operator - )loc op2({loc temp;// notice order of operandstemp.longitude = longitude - op2.longitude;temp.latitude = latitude- op2.latitude;return temp;}// overload assignment for loc.Loc loc:: operator = )loc op2({longitude = op2.longitude;latitude = op2.latitude;return *this; // i.e., return object that generated call}// overload ++ for loc.Loc loc:: operator++ ) ({longitude++ ;latitude++ ;return *this; }int main) ({loc ob1)10, 20(, ob2)5,30(;
148
ob1 = ob1+ ob2;ob1.show) (; return 0;}
البرنامج: من الخرج
15 50
هنالك بعض عواملC++ال يمكن تحميلها باستخدام دالة صديقة وهي :
، = ، ) ( ، [ ] . - >
* يضيف استعمال الدوال الصديقة مرونة إلى تحميل العوامل بشكل زائد وذلك لآلتي:
أفرض أننا قمنا بتحميل العامل + لجمع كائنات فئةالعبارة التالية ال تعمل:
ob1=3+ ob2;; الدالة +operatorوذلك ألنه وكما ذكرنا سابقا
يتم استدعاؤها من قبل الكائن الموجود على) ( يسار العالمة + وتأخذ الكائن على يمين + كوسيطة
لها ، وبما أن ه يجب استدعاء الدوال من قبل; في الفئة لذلك ال يمكننا3الكائنات و ليست عضوا
كتابة عبارة كالعبارة السابقة. لذلك وعلى الرغم من أنه يمكن جمع عدد
صحيح إلى كائن تابع لفئة ال يمكننا جمع كائن إلىرقم صحيح إال إذا استخدمنا دالة صديقة.
المثال التالي يوضح هذا حيث نقوم في المثال بتعريف إصدارين لدالة صديقة وبالتالي يمكن للكائن
أن يظهر على يمين أو يسار العامل.
//Program 8-7:
149
# include <iostream.h>class loc {int longitude, latitude;public:loc) ({ }loc)int lg, int lt( {longitude = lg;latitude =lt;}void show) ( {cout << longitude<< ; " "cout<< latitude<< "\n " ;}friend loc operator+ )loc op1, loc op2(;friend loc operator+ )int op1, loc op2(; }// + is overloaded for loc + int.loc operator+ )loc op1, loc op2(;{loc temp;temp.longitude =op1.longitude+ op2;temp.latitude = op1.latitude+ op2;return temp;}// + is overload for int + loc.loc operator+ )int op1, loc op2(;{loc temp;temp.longitude =op1 + op2.longitude;temp.latitude = op1 + op2.latitude;return temp;}int main) ({loc ob1)10, 20(, ob2)5,30( , ob3)7, 14(;ob1.show) (; ob2.show) (;
150
ob3.show) (;ob1= ob2 +10; //both of theseob3=10 + ob2; // are validob1.show) (;ob3.show) (;
return 0;}
الخرج من البرنامج:10 205 307 1415 4015 40
151
ليست دالة هي الصديقة الدوال ; ولكنها الفئة في عضواالفئة. بتلك الخاصة األعضاء إلى الوصول تستطيع
عنها اإلعالن نكتب صديقة ما دالة لجعل ; بالكلمة مسبوقا .friend األساسية
لتسهيل وذلك أخرى لفئة صديقة الفئة جعل يمكن الفئات. بين االتصال
عالمة باستعمال آخر كائن إلى كائن قيمة تعيين يمكن الفئة. لنفس الكائنات هذه تنتمي أن شريطة المساواة،
موجود عامل يعطى عندما ; على العمل على القدرة أصالزائد. بشكل تحميله تم أنه يقال جديدة بيانات أنواع
االسم تحمل دوال بكتابة زائد بشكل العوامل تحميل يتم operatorزائد، بشكل تحميله المراد بالعامل متبوعة ; فمثال االسم تحمل دالة نعرف زائد بشكل+ العامل لتحميلoperator) (+.
بشكل عامل تحميل على تعمل التي الدالة تعريف يمكن للفئة. صديقة كدالة أو الفئة في كعضو ما فئة في زائد
العامل دالة تأخذ operator functionتكون عندما ; في عضواالتالي: العام الشكل الفئة
return_type operator#)arg_list({// operations}
:- حيثreturn_type هو قيمة إعادة الدالة : operator#
; للفئة التي تعمل على ; تابعا ; ما ترجع كائنا والتي غالبا من أيreturn_typeكائناتها ولكن يمكن أن يكون
نوع آخر.Operator++ كلمة أساسية في -: C.
# :- تستبدل بالعامل المراد تحميله بشكل زائد ،; إذا كنا نقوم بتحميل العامل + بشكل زائد فمثال
.operatorنكتب Arg_listوهى الئحة الوسيطات الممرة إلى الدالة -:
operator#والتي تحتوى على عنصر واحد إذا كنا نقوم بتحميل عامل ثنائي )+، -، /، ....( وتكون
152
الملخص:
أحادى )++،Cفارغة إذا كنا نقوم بتحميل عامل++ .).... ، --
Operationsالعمليات المراد من العامل المحمل -: بشكل زائد تنفيذها.
++C في Friend ship الصداقة مفهوم ناقش-1فيها. السالبة األوجه بيان مع
رأيناها والتيstack الفئة --& ++ في العوامل حمل-2 - -) (operator الدالتان تعمل بحيث السابقة األمثلة في
;operator و ) ( وpop الدالتان تعمل مثلما ++ ) ( تماماpushالتوالي؟ على
بإجراء تقوم / بحيث * و - ، + ، العوامل بتحميل قم-3 األعداد تمثلcomplex تدعى فئة في الحسابية العمليات الصورة على ( التيcomplex number) المركبة
real part + imaginary part *Ii = √1 حيث
153
األسئلة
الوحدة التاسعةmsihpromyloP & ecnatirehnIالوراثة وتعدد األشكال 0.9
بنهاية هذه الوحدة:
.++Cستتعرف على مفهوم الوراثة في لغة ستتعرف على كيفية توفير الوراثة لقابلية
إعادة استعمال الفئات. ستتعرف على مفهوم الفئة القاعدة(base
class)والفئة المشتقة (derived class).ستتمكن من استعمال الوراثة المتعددة
الشتقاق فئة من فئتين قاعدتين أو أكثر.ستتعرف على مفهوم تعدد األشكال(
polymorphism) في لغة C++. ستتعرف على كيفية اإلعالن عن استعمال الدوال
.(virtual functions)االفتراضية ستتعرف على كيفية اإلعالن عن استعمال الدوال
إلنشاء(pure virtual functions)االفتراضية النقية .(abstract classes)فئات تجريدية
إالOOPالوراثة هي المفهوم الرئيسي بعد الفئات في ; تشكل القوة الدافعة لمبدأ البرمجة كائنية المنحى أنها عمليا وتعتمد فكرة الوراثة على إمكانية إنشاء فئات جديدة تكون
; وذلك بجعل مشتركة في صفات مع فئات موجودة أصال الفئة الجديدة ترث كل صفات الفئة القديمة باإلضافة إلى
; من كتابة البيانات واألعضاء الدالية صفاتها الخاصة بها فبدال المشتركة مرة أخرى في الفئة الجديدة ترث الفئة الجديدة
كل البياناتderived classوالتي تسمى بالفئة المشتقة ; والتي يرمز لها واألعضاء الدالية من الفئة المعرفة أصال
.base classبالفئة القاعدة عادة تضيف الفئة المشتقة بيانات وأعضاء دالية خاصة
بها وعليه تكون الفئة المشتقة أكبر من الفئة القاعدة. نجد أن كل كائن تابع للفئة المشتقة هو بالضرورة تابع
للفئة القاعدة ولكن العكس غير صحيح فكائنات الفئة; المشتقة تحمل صفات أكثر من كائنات الفئة القاعدة ، فمثال
فئة المستطيل هي فئة مشتقة من فئة األشكال الرباعية وعليه يمكن القول أن أي مستطيل هو شكل رباعي وال
يمكننا القول أن أي شكل رباعي هو مستطيل. ( يوضح العالقة بين الفئة القاعدة والفئات8-1الشكل )المشتقة.
154
مقدمة .91
فئة األشكال
فئة األشكال ثالثية األبعاد
فئة األشكال ثنائية األبعاد
فئة المكعب
فئة الشكل الكروي
فئة فئة المربعالمستطي
ل
فئة الدائرة
( يوضح العالقة بين الفئة 8-1)شكل القاعدة والفئات المشتقة
الشكل العام الشتقاق فئة من فئة قاعدة هو:class derived-class-name : access base-class-name{body of class};
و تسمى محدد وصول إمكانية الوصول accessتحدد publicإلى أعضاء الفئة القاعدة ،وهى يمكن أن تكون إما
وإذا لم يتم تحديدها فسيفترضprotected أو privateأو .privateالمصرف أن محدد الوصول هو
تسمى الوراثة عامة،publicعندما يستخدم محدد الوصول تسمى الوراثة خاصةprivateعندما يستخدم المحدد
تسمى الوراثةprotectedوعندما يستخدم محدد الوصول محمية.
تسمى الوراثةpublicإذا كان محدد الوصول عام وراثة عامة وفيها تتم وراثة األعضاء العامة والمحمية في الفئة القاعدة كأعضاء عامة ومحمية في الفئة المشتقة
ولكن في كل األحوال األعضاء الخاصة في الفئة القاعدة تبقى خاصة بالفئة القاعدة وال يمكن الوصول إليها من أعضاء الفئة المشتقة. في البرنامج التالي يتضح لنا أن
الكائنات التابعة للفئة المشتقة يمكنها الوصول إلى األعضاء العامة في الفئة القاعدة إذا كانت الوراثة عامة. لنتابع هذا
.; البرنامج جيدا
155
//Program 9-1:#include <iostream.h>class base {int i , j;public:void set) int a , int b( { i= a; j= b; }void show) ( { cout<<i << " " << j << "\n"; }};class derived : public base {int k;public:derived )int x( { k=x; }void showk) ( { cout << k << "\n" ; }};int main) ({derived ob)3(;ob.set)1 ,2(; // access member of baseob.show) (; // access member of base
ob.showk) (; //uses member of derived classreturn 0;}
الخرج من البرنامج :
1 23
هو كائنobفي البرنامج السابق على الرغم من أن إال أنه استطاع الوصول إلى األعضاء derivedتابع للفئة
وذلك ألنbase في الفئة ) (show و ) (setالدالية العامة الوراثة عامة.
تسمى الوراثةprivateإذا كان محدد الوصول خاص خاصة وعليه كل األعضاء العامة والمحمية في الفئة القاعدة
تصبح أعضاء خاصة في الفئة المشتقة .
البرنامج التالي لن يعمل وذلك ألن كل من الدوالset) (و show) (.هي اآلن خاصة بالفئة القاعدة
156
//Program 9-2:// This program won't compile.#include<iostream.h>class base {//Continuedint i , j;public:void set) int a , int b( { i= a; j= b; }void show) ( { cout<<i << " " << j << " \n "; }};// Public elements of base are private in derived.Class derived : private base {Int k;Public:derived )int x( { k=x; }void showk) ( { cout << k << " \n " ; }};int main) ({derived ob)3(;ob.set)1 ,2(; // error, can’t access set) (ob.show) (; // error, can’t access show) (return 0;}
) (show و) (set الدالية األعضاء ألن يعمل ال السابق البرنامج يمكن ال وبالتالي خاصة الوراثة ألنbase بالفئة خاصة اآلن هي
وعليه ،ob المسمىderived الفئة كائن من إليها الوصولصحيحة. ليست التالية العبارات
ob.set)1 ,2(;ob.show) (;
157
تصبح القاعدة الفئة في والمحمية العامة األعضاء الخاصة الوراثة في
الفئة أعضاء من إليها الوصول يمكن وعليه المشتقة الفئة في خاصة أعضاء
في األعضاء قبل من إليها الوصول يمكن وال فقط القاعدة والفئة المشتقة
البرنامج. من األخرى الفئات
تسمى(protected)إذا كان محدد الوصول محمى الوراثة محمية وعندها كل األعضاء العامة والمحمية في
الفئة القاعدة تصبح أعضاء محمية في الفئة المشتقة، أي يمكن الوصول إليها من الكائنات في الفئة المشتقة،
البرنامج التالي يوضح ذلك://Program 9-3:#include <iostream.h>#include <conio.h>class base {protected:int i ,j ; //private to base , but accessible by derivedpublic:void setij) int a , int b( { i= a; j= b; }void showij) ( { cout<<i << " " << j << "\n"; }};// Inherit base as protected.class derived : protected base {int k;public:// derived may access base's i and j and setij) (.void setk) ( { setij) 10, 12( ; k = i*j; }//may access showij) ( herevoid showall) ( { cout << k<< " "<<endl ; showij) ( ; }};int main ) ({derived ob ;// ob.setij)2, 3( ; // illegal, setij) ( is// protected member of derivedob.setk) ( ; // ok , public member of derived ob.showall) ( ; // ok , public member of derived//ob.showij) (; // illegal, showij) ( is protected // member of derived//Continuedreturn 0 ;}
الخرج من البرنامج :
158
الوراثة المحمية
ecnatirehnI detcetorP 2.9
12010 12
كما رأيت في البرنامج السابق بالرغم من أن الدوالsetij) ( و showij) ( هي أعضاء عامة في الفئة baseإال أنها
أصبحت محمية في الفئة المشتقة ألننا استخدمنا الوراثة المحمية وعليه ال يمكن الوصول إلى هذه األعضاء من قبل
.derivedكائنات الفئة
عندما يتم اإلعالن عن عضو في فئة ما على انه ال يمكن الوصول إلى هذا العضو من قبلprotectedمحمى
; كالعضو الخاص ولكنprivateاألعضاء خارج الفئة تماما هنالك استثناء هام ، ففي الوراثة العامة في حين أن العضو
الخاص ال يمكن الوصول إليه حتى من األعضاء في الفئة المشتقة، يمكن الوصول إلى العضو المحمى في الفئة
القاعدة من قبل األعضاء في الفئة المشتقة. وعليه يمكنك تعريف أعضاءprotectedباستخدام محدد الوصول
خاصة بالفئة يمكن الوصول إليها من الكائنات في الفئاتالمشتقة وإليك البرنامج الذي يوضح ذلك:
//Program 9-4:#include <iostream.h>class base {protected:int i ,j ; //private to base , but accessible by derivedpublic:void set ) int a , int b( { i= a; j= b; }//Continuedvoid show) ( { cout<<i << " " << j << "\n"; }};class derived : public base {int k;public:// derived may access base's i and jvoid setk) ( {k=i*j ;}
159
الوراثة واألعضاء المحميةsrebmem detcetorp dna ecnatirehnI
3.9
void showk) ( { cout <<k << " \n " ;}};int main) ({derived ob;ob.set)2, 3( ; // ok, known to derived ob.show) ( ; // ok, known to derivedob.setk) (;ob.showk) (;int d;return 0;}
الخرج من البرنامج:
2 36
من الفئةderivedفي هذا المثال تمت وراثة الفئة base وراثة عامة و تم اإلعالن عن البيانات i و jعلى أنها
ولذلكderived في الفئة ) (setkمحمية العضو الدالي يمكن للعضو الدالي الوصول إلى هذه البيانات .
160
من المهم أن نعرف ترتيب تنفيذ دوال المشيدات والمهدمات عند إنشاء كائن تابع للفئة المشتقة ، لنبدأ
بدراسة البرنامج:
//Program 9-5:#include <iostream.h>class base {public:base ) ( { cout << "Constructing base \n";}~ base) ( { cout << "Destructing base\n" ; }};class derived : public base {public:derived) ( { cout <<"Constructing derived\n" ; }~derived) ( { cout<< "Destructing derived\n" ; }};int main ) ({derived ob;// do nothing but construct and destruct obreturn 0;}
يتضح لنا أن) (mainمن التعليق المكتوب في الدالة ; يدعى تابع للمشتقةobالبرنامج يشيد ثم يهدم كائنا
derived. فالخرج من البرنامج يكون كالتالي:
Constructing baseConstructing derivedDestructing derivedDestructing base
كما ترى من خرج البرنامج تم تنفيذ مشيد الفئة القاعدة يليه مشيد الفئة المشتقة ،ولكن تم تنفيذ مهدم
الفئة المشتقة قبل مهدم الفئة القاعدة.; القاعدة هي:- يتم استدعاء المشيدات بترتيب وعموما
اشتقاق الفئات ) الفئة القاعدة ثم المشتقة ثم المشتقة
161
4.9المشيدات والمهدمات والوراثة
منها وهكذا( بينما يتم استدعاء المهدمات بعكس ترتيباالشتقاق ، البرنامج التالي يوضح ذلك:
//Program 9-6:#include<iostream.h>class base {public:base ) ( { cout << " Constructing base \n ";}~base) ( { cout << " Destructing base\n " ; }};class derived1 : public base {public:derived1 ) ( { cout " Constructing derived1\n " ; }~derived1 ) ( { cout " Destructing derived1\n " ; }};class derived2 : public derived1 {public:derived2 ) ( { cout " Constructing derived2\n " ; }~derived2 ) ( { cout " Destructing derived2\n " ; }};int main ) ({derived2 ob;// construct and destruct obreturn 0;}
الخرج من البرنامج:
Constructing baseConstructing derived1Constructing derived2Destructing derived2Destructing derived1Destructing base
162
الوراثة المتعددةecnatirehnI elpitluM 5.9
تحدث الوراثة المتعددة عندما ترث فئة ما من فئتينقاعدتين أو أكثر كالتالي:
class base1{ };class base2{ };class derived: public base1, public base2{ };
.base2 وbase1 مشتقة من الفئتين derivedالفئة يتم في مواصفات الفئة المشتقة فصل الفئات القاعدة عن بعضها البعض بواسطة فاصلة . يجب أن يكون هنالك محدد
وصول لكل فئة قاعدة.البرنامج التالي يبين كيفية استعمال الوراثة المتعددة.
//Program 9-7:// An example of multiple base classes.#include<iostream.h>class base1 {protected:int x;public://Continuedvoid showx) ( { cout << x<< " \n " ; }};class base2 {protected:int y;public:void showy) ( { cout << y<< " \n " ; }} ;// Inherit multiple base classes .class derived: public base1 , public base2 {public:void set )int i , int j ( { x=i; y=j ; }} ;int main ) ({derived ob ;ob.set)10, 20( ; // provided by derivedob.showx) ( ; // from base1ob.showy) ( ; //from base2return 0;
163
}
الخرج من البرنامج:
1020
derivedفي البرنامج السابق ورثت الفئة ob وراثة عامة، لذلك يمكن للكائن base2 و base1الفئتين
الوصول إلى األعضاء الدالية العامةderivedالذي يتبع للفئة showx ) ( التابع للفئة base1 و showy ) (التابع للفئة base2.
هنالك ثالثة مفاهيم رئيسية في البرمجة الكائنية المنحى . األول هو الفئات والثاني الوراثة سنناقش هنا
المفهوم الثالث : تعدد األشكال الحقيقي يتم تطبيقه فيC++من خالل الداالت اإلفتراضية virtual functions.
يوجد في الحياة الفعلية مجموعة من األنواع المختلفة من األشياء والتي عند إعطائها تعليمات متطابقة تتصرف
عادة يحدث تعدد األشكال في++Cبطرق مختلفة ، في الفئات المرتبطة ببعضها البعض بسبب الوراثة وهذا يعنى
; أن استدعاء عضو دالي سيؤدى إلى تنفيذ دالة مختلفة وفقالنوع الكائن الذي استدعى العضو الدالي.
; بتحميل الداالت بشكل زائد ، يبدو تعدد األشكال شبيها لكن تعدد األشكال آلية مختلفة وأكثر فعالية فعند تحميل الداالت بشكل زائد المصرف هو الذي يحدد الدالة التي
سيتم تنفيذها بينما في تعدد األشكال يتم اختيار الدالةالمطلوب تنفيذها أثناء تشغيل البرنامج.
هي دوال يتم تعريفها ضمن األعضاء الدالية في فئة ويعاد تعريفها في الفئات المشتقة. إلنشاءbaseقاعدة
164
تعدد األشكالmsihpromyloP
6.9
الداالت االفتراضية snoitcnuF lautriV .9
7
virtual functionتقوم الفئة المشتقة بإعادة تعريف الدالة بما يتوافق مع متطلباتها .
*** عندما يعلن عن مؤشر ليشير إلى كائنات فئة قاعدة يمكن استخدام نفس المؤشر ليشير إلى كائنات الفئات
المشتقة وعليه عندما يشير مؤشر فئة قاعدة إلى كائن في ++C تحدد virtual functionفئة مشتقة منها تحتوى على
; لمحتويات المؤشر )نوع الدالة المطلوب تنفيذها وفقا الكائن المشار إليه بواسطة المؤشر( ويتم هذا التحديد أثناء
تنفيذ البرنامج وعليه عندما يستعمل مؤشر الفئة القاعدة ليشير إلى كائنات الفئات المشتقة يتم تنفيذ عدة إصدارات
; على محتويات المؤشر. من الدالة اإلفتراضية بناءاالبرنامج التالي يوضح ذلك:
Program 9-8:#include<iostream.h>class base {//Continuedpublic:virtual void vfunc) ( {cout << " This is base’s vfunc) ( .\n ";}};class derived1 : public base {public :void vfunc) ( {cout << " This is derived1’s vfunc) ( .\n ";}};class derived2 : public base {public :void vfunc) ( {cout << " This is derived2’s vfunc) ( .\n ";}};int main) ({base *p, b;derived1 d1;derived2 d2;
// point to base
165
p= &b;p->vfunc) ( ; // access base's vfunc) (// point to derived1p= &d1;p->vfunc) ( ; // access derived1's vfunc) (// point to derived2p= &d2;p->vfunc) ( ; // access derived2's vfunc) (return 0;}
الخرج من البرنامج:
This is base’s vfunc) (.
This is derived’s vfunc) (.
This is derived’s vfunc) (.
تم تعريف الدالة اإلفتراضيةbaseداخل الفئة vfunc) ( الحظ أن الكلمة األساسية . virtualتسبق اسم
) (vfuncالدالة في اإلعالن عنها . تم إعادة تعريف الدالة .derived2 و derived1في الفئات المشتقة
تم اإلعالن عن أربعة متغيرات:- mainداخل الدالة
نوعهاسم المتغيرpمؤشر لكائنات الفئة القاعدة
baseb كائن تابع للفئةbase
d1 كائن تابع للفئةderived1d2 كائن تابع للفئةderived2
وتم استدعاءp إلى المؤشر bتم تعيين عنوان الكائن وبما أن المؤشر اآلنp بواسطة المؤشر ) (vfuncالدالة
تم تنفيذ إصدار الدالةbaseيحمل عنوان الكائن التابع للفئة vfunc) ( المعرف في الفئة baseبعدها تم تغيير قيمة.
التابع للفئة المشتقةd1 إلى عنوان الكائن pالمؤشر derived1 اآلن سيتم تنفيذ الدالة
derived1:: vfunc) (
166
; تم تعيين عنوان الكائن إلى derived2 التابع للفئة d2أخيرا وعليه العبارة: pالمؤشر
p -> func) (;أدت إلى تنفيذ الدالة
derived2:: vfunc) ( من النظرة األولى قد تبدو الدوال اإلفتراضية شبيهة
بتحميل الداالت بشكل زائد . ولكن عند تحميل الداالت بشكل زائد يجب أن يختلف اإلعالن عن الدالة من دالة إلى
أخرى في نوع أو عدد الوسائط الممررة إلى الدالة حتى يستطيع المصرف تحديد الدالة المطلوب تنفيذها ، بينما في
الدوال اإلفتراضية يجب أن يطابق إعالن الدالة اإلفتراضية المعرفة في الفئة القاعدة اإلعالن عنها في الفئات
المشتقة.
; في ; قويا . الفئةOOPتشكل الفئات التجريدية مفهوما التي ال يتم إنشاء أي كائنات منها تسمى فئة تجريدية .
الهدف الوحيد لهذه الفئة هو أن تلعب دور فئة عامة يتماشتقاق فئات أخرى منها.
سيكون من الجيد لو استطعنا في حال إنشاء فئة قاعدة تجريدية أن نبلغ المصرف أن يمنع أي مستخدم للفئة
من إنشاء كائن تابع لها ، يتم ذلك من خالل تعريف دالةإفتراضية نقية واحدة على األقل في الفئة.
الدالة اإلفتراضية النقية هي دالة ليس لها جسم ، يتمإزالة جسم الدالة اإلفتراضية في الفئة القاعدة.
الصورة العامة لها:virtual type functionname )parameter-list( = 0;
167
الفئات التجريدية sessalC tcartsbA 8.9
الداالت اإلفتراضية النقية snoitcnuf lautriv eruP
9.9
تذكر دائماb أن الدالة اإلفتراضية:1 في الفئة ; ; ساكنا static/ ال يمكن أن تكون عضوا
member.2 ال يمكن أن تعرف كدالة صديقة/friend function.3 ال يمكن استعمالها كمشيد /constructor.
عالمة المساواة ليس لها أي عالقة بالتعيين فالتركيب هو فقط إبالغ المصرف أن الدالة ستكون(0)=المنطقي
نقية أي لن يكون لها جسم. البرنامج التالي يحتوى على مثال بسيط لدالة
هي فئة تجريدية numberإفتراضية نقية. الفئة القاعدة ، الدالة val يدعى intتحتوى على عضو محمى من النوع
setval) ( الدالة النقية ، show ) (في الفئات المشتقة . hextype ، oct type تم إعادة تعريف الدالة show ) (.
//Program 9-9:#include <iostream.h>//Continuedclass number {protected :int val ;//Continued public :void setval )int i( { val = i ; }// show) ( is a pure virtual function virtual void show) ( = 0 ;};class hextype : public number {public :void show ) ( {cout << hex << val << "\n " ;}};class dectype : public number {public :void show ) ( {cout << val << "\n " ;}};class octtype : public number {public :void show ) ( {cout << oct << val << "\n " ;}};int main ) ({dectype d;
168
hextype h;octtype 0;
d.setval)20( ;d.show) ( ; h.setval)20( ;h.show) ( ; 0.setval)20( ;0.show) ( ;
return 0;}
الخرج من البرنامج:
201424
169
:الشكل العام الشتقاق فئة من فئة قاعدة هوclass derived-class-name : access base-class-name {body of class};
تسمىaccessمحدد وصول ، وهي تتحكم في كيفية طريقة وراثة الفئات حيث يمكن أن تكون الوراثة عامة
(public ) أو خاصة (private) أو محمية (protected) على حسب محدد الوصول المستخدم.
إذا كان محدد الوصول عام تسمى الوراثة عامة وفيها تتم وراثة األعضاء العامة والمحمية في الفئة القاعدة كأعضاء عامة ومحمية في الفئة المشتقة ولكن تبقى
األعضاء الخاصة في الفئة القاعدة خاصة بالفئة القاعدة، وال يمكن الوصول إليها من أعضاء الفئة
المشتقة.إذا كان محدد الوصول خاص تسمى الوراثة خاصة
وعندها كل األعضاء العامة والمحمية في الفئة القاعدةتصبح أعضاء خاصة في الفئة المشتقة.
إذا كان محدد الوصول محمى تسمى الوراثة محمية وعندها كل األعضاء العامة والمحمية في الفئة القاعدة
تصبح أعضاء محمية في الفئة المشتقة.ال يمكن الوصول إلى العضو المحمى من قبل
األعضاء خارج الفئة إال أنه في الوراثة العامة يمكن الوصول إلى العضو المحمى من األعضاء في الفئات
المشتقة.عادة يتم تنفيذ مشيد الفئة القاعدة ثم مشيد الفئة
; قبل المشتقة ولكن يتم تنفيذ مهدم الفئة المشتقة أوالمهدم الفئة القاعدة.
تحدث الوراثة المتعددة عندما ترث فئة ما من فئتين قاعدتين أو أكثر.
يحدث تعدد األشكال عادة في الفئات المرتبطة ببعضها بسبب الوراثة.
الدوال االفتراضية هي دوال يتم تعريفها ضمن األعضاء الدالية في الفئة القاعدة ويعاد تعريفها في
الفئات المشتقة.
170
الملخص:
عندما يشير مؤشر فئة قاعدة إلى كائن في فئة ++Cمشتقة منها تحتوى على دالة افتراضية، تحدد
; لمحتويات المؤشر ويتم الدالة المطلوب تنفيذها وفقاذلك أثناء تنفيذ البرنامج.
يجب أن نطابق إعالن الدالة االفتراضية في الفئة القاعدة باإلعالن عنها في الفئات المشتقة.
الفئة التجريدية(abstract class)هي الفئة التي ال يتم إنشاء أي كائنات منها.
الدالة االفتراضية النقية هي دالة ليس لها جسم يتم تعريفها في الفئات التجريدية.
/ أكتب تعريفاb مختصراb لكل من اآلتي:1 الوراثة(Inheritance). الوراثة المتعددة(multiple inheritance). الفئة القاعدة(base class). الفئة المشتقة(derived class).
2bصحيح / خطأ( : كائن الفئة المشتقة هو أيضا ( / كائن تابع للفئة القاعدة لها.
/ يفضل بعض المبرمجين عدم استعمال محدد3 سالمة ألنه يهدد(protected)الوصول المحمى
بيانات الفئة القاعدة . ناقش هذه العبارة وبين مامدى صحتها .
/ ما هي الدوال االفتراضية ؟ صف األحوال التي تكون4
فيها استعمال الدوال االفتراضية مناسباb؟
/ وضح الفرق بين الدوال االفتراضية والدوال5.( pure )االفتراضية النقية
/ )صحيح / خطأ( كل الدوال اإلفتراضية في6 (abstract base classes)الفئات القاعدة التجريدية
يجب أن تكون دوال افتراضية نقية.
171
األسئلة
172
الوحدة العاشرةالقوالب واإلستثناءات
0.9
ستتمكن من استعمال قوالب داالت إلنشاء مجموعة من الدوال المرتبطة ببعضها.
ستتمكن من استعمال قوالب الفئات(Templates Classes).
ستتعرف على مفهوم االستثناءات في لغةC++. ستتمكن من استعمال كتل المحاولةtry blocks
والتي تحصر العبارات التي يمكن أن تؤدى إلى حدوثاستثناء.
.ستتمكن من رمى االستثناء ستتمكن من استعمال كتل التقاطcatch blocks
والتي تقوم بمعالجة االستثناء.
إذا أردنا كتابة دالة تقوم باستبدال رقمين تتم كتابةهذه الدالة لنوع بيانات معين كاآلتي:
int swap )int &a,int &b({int temp;temp=a;a=b;b=temp;}
وتعيد قيمة من نفس intيتم تعريف الدالة من النوع النوع . لكن لنفترض أننا نريد استبدال رقمين من النوع
long.; سنضطر لكتابة دالة جديدة كلياLong swap )long &a, long &b({long temp;temp=a;a=b;b=temp;}
وسنضطر لكتابة دالة أخرى إذا أردنا استبدال رقمين من .floatالنوع
إن جسم الدالة هو نفسه في كل الحاالت لكن يجب أن تكون داالت منفصلة ألننا نتعامل مع متغيرات ذات أنواع
مختلفة وعلى الرغم من أنه يمكن تحميل هذه الداالت; نضطر إلى بشكل زائد بحيث تحمل نفس االسم لكننا أيضا
كتابة داالت منفصلة لكل نوع وهذه الطريقة بها عدةعيوب :-; ألنواع1 ; وتكرارا / كتابة نفس جسم الدالة مرارا
مختلفة من البيانات يضيع الوقت ويزيد حجم البرنامج . / إذا ارتكبنا أي خطأ في إحدى هذه الداالت يجب2
تصحيح هذا الخطأ في بقية الداالت. كانت هنالك طريقة لكتابة هذه الدالة مرة واحدة
فقط لكي تعمل على أي نوع من أنواع البيانات المختلفة Functions ويتم هذا باستعمال ما يسمى بقالب الداالت
Templatesوالذي يتم إنشاؤها باستخدام الكلمة األساسية template.
173
قوالب الداالت
snoitcnuF etalpmeT 1.9
البرنامج التالي يبين كيفية كتابة دالة تقوم باستبدال قيمتي متغيرين كقالب لكي تعمل مع أي نوع ) (swapargsأساسي .يعرف البرنامج إصدار قالب الدالة
ثالث مرات مع أنواع) (mainثم يستدعى هذه الدالة فيبيانات مختلفة.
//Program 9-1:// Function template example.// Function template example.#include <iostream.h>// This is a function template.template <class x> void swapargs)x &a, x &b({x temp;temp = a;a = b;b = temp;}int main) ({int i=10 , j=20;double x=10.1, y=23.3;char a= 'x' ,b= 'z' ;
cout << " original i, j: ";cout<<i<<" "<<j<< "\n " ;cout << " original x, y:" <<x<<" "<<y<< "\n " ;cout << " original a, b: " << a <<" "<< b << "\n " ;
swapargs)i, j( ; // swap integersswapargs)x, y( ; // swap floatsswapargs)a, b( ; // swap charscout << " Swapped i, j: "<<i<<" "<<j<< "\n " ;cout << " Swapped x, y: "<<x<<" "<<y<< "\n " ;cout << " Swapped a, b: " <<a<<" "<<b<< "\n " ;return 0;}
الخرج من البرنامج:
174
original i, j: 10 20original x, y: 10.1 23.3original a, b: x zSwapped i, j: 20 10Swapped x, y: 23.3 10.1Swapped a, b: z x
كما رأيت في البرنامج أعاله تعمل الدالةswapargs) ( اآلن مع كل أنواع البيانات int، double، char
; مع واستخدام استعملتها كوسائط لها ويمكن أن تعمل أيضا أنواع أساسية أخرى وحتى مع أنواع البيانات المعرفة من
قبل المستخدم ، ولجعل الدالة تقوم بكل هذا كتبنا:template< class x> void swapargs )x& a, x&b({x temp;temp = a;a = b;b = temp;}
االبتكار في قوالب الداالت هو عدم تمثيل نوع; ، بل باسمintالبيانات الذي تستعمله الدالة كنوع معين مثال
يمكنه أن يشير إلى أي نوع من قالب الداالت في المثال وهو يسمى وسيطة قالب.xالسابق ، هذا االسم هو
templateعندما يرى المصرف الكلمة األساسية وتعريف الدالة الذي يليها ال يقوم بتوليد أي شفرة ألنه ال
يعرف بعد ما هو نوع البيانات الذي سيستعمل مع الدالة . يتم توليد الشفرة بعد استدعاء الدالة في عبارة ما في
البرنامج ، يحصل هذا األمر في البرنامج السابق في العبارةswapargs)i,j(;.; مثال
عندما يرى المصرف مثل هذا االستدعاء، فانه يعرف كوننا عرفنا المتغيراتintأن النوع الذي سيتم استعماله هو
iو j على أنها من النوع intللدالة ; .لذا يقوم بتوليد إصداراswapargs) ( بالنوع ; ; االسم int خاصا في كلx مستبدال
) ويسمى هذا استنباط intظهور له في القالب بالنوع
175
المصرف وقوالب الداالت 2.9
instantiating )قالب الداالت. كل إصدار مستنبط للدالة يسمى دالة قوالبية.
إلى)swapargs) x,yبشكل مماثل يؤدى االستدعاء ; للدالة يعمل على) (swapargsجعل المصرف يولد إصدارا
إلى)swapargs)a,b بينما يؤدى االستدعاء doubleالنوع .charتوليد دالة تعمل على النوع
يقرر المصرف كيفية تصريف الدالة على أساس نوع البيانات المستعمل في وسيطات استدعاء الدالة . مما
سبق يتضح لنا أن قالب الداالت هو ليس في الواقع دالة، OOPإنه مخطط إلنشاء عدة داالت ويتالئم هذا مع فلسفة
وهو متشابه للفئة كونها نموذج إلنشاء عدة كائنات متشابهة.
يمكن تعريف أكثر من وسيطة قالب في قالب الداالت وذلك باستعمال فاصلة ),( تفصل بين الوسائط. البرنامج
التالي يقوم بإنشاء قالب داالت له وسيطتين
//Program 9-2:#include <iostream.h>template <class type1,class type2>void myfunc)type1 x, type2 y({cout <<x<< y << '\n' ;}int main) ({myfunc ) 10, " I like C++"(;myfunc)98.6, 19L(;return 0;}
بأنواعtype2 وtype1في البرنامج السابق تم استبدال على التوالي. int، char* ،double ، longالبيانات
الخرج من البرنامج:
10 I like C++98.6 19L
176
قالب داالت مع وسيطتي قالب3.9
والتي سبق أن رأيناها في األمثلة السابقةstackالفئة كان بإمكانها تخزين بيانات من نوع أساسي واحد فقط هو
فيfloat ولذلك إذا أردنا تخزين بيانات من النوع intالنوع ; وبشكلstack فئة سنحتاج إلى تعريف فئة جديدة كليا
مماثل سنحتاج إلى إنشاء فئة جديدة لكل نوع بيانات نريد تخزينه ، لذا علينا كتابة مواصفات فئة واحدة تعمل مع
متغيرات من كل األنواع وليس مع نوع بيانات واحد، بإمكانقوالب الفئات تحقيق ذلك.
باستعمال قالبstackالمثال يقوم بتعريف الفئة داالت:
//Program 9-3:// This function demonstrates a generic stack.#include <iostream.h>#include <conio.h>
const int SIZE = 10;// Create a generic stack classtemplate <class StackType> class stack {StackType stck[SIZE]; // holds the stackint tos ; // index of top_of_stack
public:stack) ( { tos =0; } // initialize stack//Continuedvoid push)StackType ob( ; // push object on stackStackType pop) ( ; // pop object from stack};
//push an object.template <class StackType> void stack <StackType> :: push)StackType ob({if )tos== SIZE( {cout << "Stack is full.\n" ;return ;
177
قوالب الفئات sessalC setalpmeT 4.9
}stck[tos] = ob;tos++;}//pop an object.template <class StackType> StackType stack <StackType> :: pop) ({if )tos== 0( {cout << "Stack is empty.\n" ;return 0; //return null on empty stack}tos--;return stck[tos];}int main) ({// Demonstrate character stacks.stack<char> s1, s2; // create two character stacksint i;
s1.push) 'a' (;s2.push) 'x' (;//Continueds1.push) 'b' (;s2.push) 'y' (;s1.push) 'c' (;s2.push) 'z' (;for )i=0; i<3; i++ ( cout<<" " <<s1.pop) ( ;cout <<endl;for )i=0; i<3; i++ ( cout<< " " <<s2.pop) ( ;cout<<endl;// demonstrate double stacksstack<double> ds1, ds2; // create two double stacksds1.push) 1.1 (;ds2.push) 2.2 (;ds1.push) 3.3 (;ds2.push) 4.4 (;ds1.push) 5.5(;ds2.push) 6.6 (;for )i=0; i<3; i++ ( cout <<" "<<ds1.pop) ( ;
178
cout<<endl;for )i=0; i<3; i++ ( cout<<" " <<ds2.pop) ( ;return 0;}
الخرج من البرنامج:
c b az y x5.5 3.3 1.16.6 4.4 2.2
هنا كقالب فئات، هذا األسلوبstackتم تمثيل الفئة مشابه لألسلوب المستعمل مع قوالب الداالت . تشير
إلى أن الفئة بأكملها ستكون templateالكلمة األساسية ; ويتم عندها استعمال وسيطة قالب تدعى .StackTypeقالبا
الحظ هنا أن اسم الكائنين يتكون من اسم الفئةstack إضافة إلى وسيطة القالب >char<مما يميزها عن
كائنات بقية الفئات التي قد يتم استنباطها من نفس القالب;.>stack <doubleكـ مثال
179
تختلف قوالب الفئات عن قوالب الداالت في طريقة استنباطها. إلنشاء دالة فعلية من قالب داالت يتم
استدعائها باستعمال وسيطات من نوع معين ،لكن الفئات يتم استنباطها بتعريف كائن باستعمال وسيطة
القالب :-stack <char> s1, s2;
stack تابعين للفئة s1، s2تنشئ هذه العبارة كائنين ويزود المصرف مساحة من الذاكرة لبيانات هذين
ليس هذا فقط بلcharالكائنين والتي هي من النوع ; مجموعة من األعضاء الدالية التالي تعمل وينشئ أيضا
; كائني المنحى لمعالجة أخطاء تزود اإلستثناءات أسلوبا;++Cالتشغيل التي تولدها فئات ، ولكي تكون إستثناءا
يجب أن تحدث تلك األخطاء كنتيجة لعمل ما جرى ضمن البرنامج كما يجب أن تكون أخطاء يستطيع البرنامج
اكتشافها بنفسه .التركيب النحوي لالستثناء:-
; ما ينشئ كائنات تابعة لفئة معينة لنفترض أن برنامجا ويتفاعل معها ، ال تسبب استدعاءات األعضاء الدالية أي
مشاكل لكن قد يرتكب البرنامج في بعض األحيان أخطاءمما يؤدى إلى اكتشاف خطأ في عضو دالي ما.
يقوم العضو الدالي عندها بإبالغ البرنامج أن خطأ ما قد حصل، يسمى هذا األمر رمى استثناء ويحتوى البرنامج
على جزء منفصل لمعالجة الخطأ، يسمى هذا الجزء معالج االستثناء أو كتلة االلتقاط ألنها تلتقط اإلستثناءات التي
ترميها األعضاء الدالية. وأي عبارات في البرنامج تستعمل كائنات الفئة تكون موجودة داخل كتلة تسمى كتلة المحاولة
وعليه األخطاء المولدة في كتلة المحاولة سيتم التقاطهافي كتلة االلتقاط .
،throwيستعمل االستثناء ثالث كلمات أساسية جديدة catch، tryالبرنامج يوضح ميزات آلية االستثناء هذه ) هو .
فقط تخطيط عام إلظهار التركيب المنطقي لالستثناء(:-
//Program 9-4:class any class{public:class an error{};void func) ({if ) /* Error condition*/(throw an Error) (;}};void main) (//Continued
180
اإلستثناءات
( snoitpecxE) 5.9
{try{any class obj1;obj1.func) (;}catch)any class:: An Error({// tell user about the Error}}
وهى تمثل أي anyclassيبدأ هذا البرنامج بفئة تدعى فئة يمكن أن تحدث فيها أي أخطاء. يتم تحديد فئة االستثناء
. تقوم األعضاء الداليةany classفي الجزء العام من الفئة ; عن أي خطأ . إذا وجدany classالتابعة للفئة بالتدقيق بحثا
يليهاthrowتقوم برمي استثناء باستعمال الكلمة األساسية . ) (throw AnErrorالمشيد التابع لفئة الخطأ
بحصر العبارات التي تتفاعل مع) (mainقمنا في في كتلة محاولة إذا سببت أي واحدة منany classالفئة
anyتلك العبارات اكتشاف خطأ في عضو دالي تابع للفئة class سيتم رمى استثناء وينتقل التحكم إلي كتلة االلتقاط
التي تلي المحاولة مباشرة.البرنامج التالي يستعمل االستثناءات :-
//Program 9-5:// Demonstrated Exceptions#include <iostream.h>#include <conio.h>const int SIZE =3;class stack{private:int tos;int stck[SIZE];public:class Range { };//Continuedstack) ( { tos = 0; }~stack) ({ };void push )int i(;int pop) (;
181
}; void stack::push)int i({if) tos >= SIZE(throw Range ) (;else{ stck[tos] = i;tos ++;} }stack :: pop) ({ if) tos == 0( throw Range) (; else { tos --;return stck[tos];} }main ) ({ stack s1;try{ s1.push)1(; s1.push)2(;//Continueds1.push)3(;cout << s1.pop ) (<< endl;cout << s1.pop ) (<< endl;cout << s1.pop ) (<< endl; cout << s1.pop ) (<< endl;}catch )stack::Range({cout << "Stack Full or Empty" << endl;}return 0; }
في البرنامج السابق عبارتين تتسببان في رمي استثناء إذا حذفنا رمز التعليق الذي يسبقهما، اختبر الحالتين.سترى في كالهما رسالة الخطأ التالية:-
Stack Full or Empty ; جسم فارغ الدالة ألن كل ما نحتاج يحدد البرنامج أوال
إليه هو فقط اسم الفئة الذي يتم استعماله لربط عبارة بكتلة االلتقاط.throwالرمي
182
إذا حاول البرنامج سحبstackيحدث االستثناء في الفئة ; أو حاول دفع قيمة عندما stackقيمة عندما يكون الـ فارغا
. ; يكون ممتلئا وإلبالغ البرنامج أنه قد ارتكب خطأ عند عمله مع كائن
stack تدقق األعضاء الدالية التابعة للفئة stackعن ; بحثا; إذا حدثت إحدىifخطأ باستعمال عبارات وترمي استثناءا
تلك الحاالت . يتم في البرنامج السابق رمي استثناء فيمكانين كالهما باستعمال العبارة:
throw range) (; باستحضار المشيد )الضمني( التابع) (rangeتقوم
; تابع لهذه الفئة بينما تقومrangeللفئة الذي ينشئ كائناthrow بنقل تحكم البرنامج إلى معالج االستثناءات، كل
والتي قد تتسبب في هذا االستثناء mainالعبارات في محصورة بين أقواس حاصرة وتسبقها الكلمة األساسية
try. الجزء من البرنامج والذي يعالج االستثناء موجود بين
مع وجودcatchأقواس حاصرة وتسبقه الكلمة األساسية اسم فئة االستثناء في أقواس .
يجب أن يشتمل اسم فئة االستثناء على الفئة التي يتواجدفيها.
catch)stack:: range( يدعى هذا المشيد معالج استثناء ويجب أن يلي كتلة
المحاولة مباشرة وهو يقوم في البرنامج السابق بعرض رسالة خطأ فقط لكي يعلم المستخدم عن سبب توقف
البرنامج عن العمل . ينتقل التحكم بعدها إلي ما بعد معالج االستثناء لكي يستطيع
متابعة البرنامج أو يرسل التحكم إلى مكان آخر أو ينهىالبرنامج إذا لم تكن هنالك طريقة أخرى .الخطوات التالية تلخص عملية االستثناء:-
/ يتم تنفيذ البرنامج بشكل طبيعي خارج كتلة المحاولة .1/ ينتقل التحكم إلى كتلة المعالجة.2/ عبارة ما في كتلة المحاولة تسبب خطأ دالي .3/ يرمي العضو الدالي استثناء.4/ ينتقل التحكم إلى كتلة االلتقاط التي تلي كتلة المحاولة.5
; يقوم برمي استثناء إذا حاول البرنامج التالي أيضا.negativeالمستخدم إدخال رقم سالب
183
//Program 9-6:// Catching class type exeptions.# include <iostream.h># include <string.h>#include <conio.h>class MyException {public:char str_what[80];int what;MyException) ( { *str_what =0 ; what = 0; }MyException)char *s, int e ( {strcpy )str_what, s(;what = e;}};int main) ({int i;try { cout << " Enter a positive number: " ;cin >> i ;if )i<0(throw MyException )"Not Positive" ,i( ;}catch )MyException e( { // catch an errorcout <<e.str_what << ": " ;cout << e.what << "\n" ;}getch)(;return 0;}
: i= -4الخرج من البرنامج بافتراض أن المستخدم قد أدخل
Enter a positive number: -4Not Positive: -4
في البرنامج السابق يطلب البرنامج من المستخدم إدخال رقم موجب، ولكن إذا تم إدخال رقم سالب يقوم
184
لوصف هذاMy Exceptionالبرنامج بإنشاء كائن تابع للفئة الخطأ.
185
قوالب الداالت هو وسيلة لجعل الدالة تعمل على أي نوع من أنواع البيانات المختلفة.
يتم إنشاء قالب الداالت باستخدام الكلمة .Templateاألساسية
في قالب الداالت ال يتم تمثيل نوع بيانات معين ; بل باسم يمكن أن يشير إلىintفي الدالة كـ مثال
أي نوع بيانات ويسمى هذا االسم وسيطة قالب.يحدد المصرف كيفية تصريف الدالة على أساس
نوع البنيات المستعمل في وسيطات استدعائها.قالب الداالت هو ليس في الواقع دالة، هو مخطط
إلنشاء عدة داالت.يمكن تعريف أكثر من وسيطة قالب في قالب
الداالت.قالب الفئات هو فئة تعمل على متغيرات في كل
أنواع البيانات. كائني المنحى لمعالجة أخطاء ; تتبع االستثناءات أسلوبا
.++Cالتشغيل التي تولدها الفئات في عند حدوث خطأ في إحدى الفئات تقوم األعضاء
الدالية بإبالغ البرنامج أن خطأ ما قد حدث ويسمى هذااألمر رمى استثناء.
يحتوى برنامجC++على جزء منفصل لمعالجة األخطاء يسمى معالج االستثناء أو كتلة االلتقاط.
أي عبارات في البرنامج تستعمل كائنات الفئة تكون موجودة داخل كتلة تسمى كتلة المحاولة.
:يستعمل االستثناء ثالث كلمات أساسية هيtry, catch, throw.
-:الخطوات التالية تلخص عملية االستثناء.يتم تنفيذ البرنامج بشكل طبيعي خارج كتلة المحاولة.ينتقل التحكم إلى كتلة المعالجةقد تؤدى عبارة ما في كتلة المحاولة ؟؟؟ خطأ في
عضو دالي..يرمى العضو الدالي استثناءينتقل التحكم إلى كتلة االلتقاط التي تلي كتلة
المحاولة.
186
الملخص:
والتي تقارنIsEqualTo/ أكتب دالة قالب تدعى 1 إذا1بين وسيطين باستعمال العامل == وترجع
إذا كانتا غير ذلك.0كانتا متطابقتين و ثم أكتب برنامجاb الختبار هذه الدالة مع أنواع
األساسية.++Cبيانات قم بتحميل العامل == بشكل زائد واختبرها مع
كائنات.
/ ما هي العالقة بين قوالب الداالت وتحميل2الداالت بشكل زائد.
/ وضح العالقة بين قالب الفئات والوراثة.3
/ عرف اإلستثناء.4
/ أكتب الخطوات التي توضح عملية اإلستثناء.5
/ أكتب برنامجاb تستخدم فيه آلية اإلستثناءات.6
187
األسئلة
188
الوحدة الحادية عشرة
++C دفق دخل/خرج0.11
بنهاية هذه الوحدة: )ستتمكن من استخدام )دفق دخل/ خرج(
Input/Output Stream ) في لغة C++..ستتمكن من تنسيق الدخل /الخرجستتعرف على كيفية إدخال وإخراج الكائنات التي
تنشئها بنفسك..ستتمكن من إنشاء مناورات خاصة بك
هو اسم عام يطلق لسيل من البيانات فيالدفق حالة دخل/خرج . يتم تمثيل دفق )الدخل/ الخرج( بكائن تابع
; رأينا في جميع األمثلة السابقة كائنات لفئة معينة ، فمثال والتي استعملناها لعمليات الدخل والخرج.cin, coutالدفق
( التالي:11-1تابع الشكل )
هي الفئة القاعدةiosكما نرى من الشكل الفئة لهرمية دفق الدخل والخرج وهى تحتوى على العديد من
الثوابت واألعضاء الدالية المشتركة بين مختلف األنواع من مشتقاتostream و istreamفئات الدخل والخرج. الفئتان
وهما متخصصتان بأعمال الدخل والخرج .iosمن الفئة )get) ( , getline على أعضاء دالية لـ istreamتحتوى الفئة
على ostream بينما تحتوى الفئة )>>( وعامل الدخل(put) ( و write) ( وعامل الخرج )>>(.
على أغلبية الميزات التي تحتاج إليهاiosتحتوى الفئة ومن أهم هذه الميزات أعالم++Cالستخدام الدفق في
التنسيق.
189
مقدمة .111
maertso
soi
maertsoi
maertsi
يوضح هرمية 11-1الشكل فئات الدفق
هرمية فئات الدفق 2.11
تعمل لتحديد iosهي مجموعة من األعضاء في الفئة خيارات في عمل وتنسيق الدخل والخرج.
هنالك عدة طرق لضبط أعالم التنسيق ، وبما أن يجب عادة وضع اسم الفئةiosاألعالم هي أعضاء في الفئة
iosوعامل دقة المدى قبلها . يمكن ضبط كل األعالم التابعة للفئة) (unsetf و) (setfباستعمال األعضاء الدالية
ios-::-iosالجدول التالي يبين بعض ألعالم تنسيق الفئة
معناهالعلمskipwsتجاهل المسافات البيضاء
الموجودة في الدخلleftمحاذاة الخرج إلى اليسار
rightمحاذاة الخرج إلى اليمينdecتحويل إلى عشري
showbaseاستعمال مؤشر القاعدة في الخرج
showpointإظهار النقطة العشرية في الخرج
uppercaseاستعمال األحرف الكبيرة في الخرج
showposعرض )+( قبل األعداد الصحيحة الموجبة
البرنامج التالي يوضح كيفية استعمال علمي التنسيقshowpos و showpoint-:
//Program 11-1:#include <iostream.h>int main) ({cout.setf)ios:: showpoint(;cout.setf)ios:: showpos(;
cout<< 100.0; // displays + 100.0return 0 ;}
190
أعالم التنسيقsgalf etats tamroF 3.11
الخرج من البرنامج:
+100.00
لمناورات هي تعليمات تنسيق تدرج في الدفقا والثاني يرسلendlمباشرة ، رأينا منها حتى اآلن المناور
; إلى الدفق. ; جديدا سطرا هنالك نوعان من المناورات ، نوع يأخذ وسيطة واآلخر ال يأخذ أي
وسيطة، الجدول التالي يوضح بعض المناورات التي ال تأخذ أي وسيطات:-
هدفهالمناورwsتنشيط ميزة تخطى المسافات
البيضاء الموجودة في الداخلdecالتحويل إلى عشريoctالتحويل إلى ثمانيhexالتحويل إلى ست عشري
endlإدراج سطر جديدendsإدراج حرف خامد إلنهاء سلسلة
خرج; لخرج تدرج هذه المناورات في الدفق مباشرة ، فمثال
في التنسيق الستعشرى نكتب:varالمتغير cout<<hex<<var;
إن الحالة التي تضبطها المناورات ليس لها وسيطات تبقى نشطة إلى أن يتم تدمير الدفق وعليه يمكننا خرج
عدة أرقام في التنسيق الستعشرى من خالل إدراج مناورhex.واحد فقط
الجدول التالي يلخص بعض المناورات التي تأخذ وسيطات لكي نستعملiomanip.hونحتاج إلى إدراج ملف الترويسة
هذه المناورات:-
هدفهالوسيطةالمناورsetw)( عرض الحقل(
int)ضبط عرض الحقل المطلوب عرضه
setfill)( حرف الحشو(int)
ضبط حرف الحشو في الخرج)الحرفاالفتراضي هو المسافة
setprecision)( الدقة(int))ضبط الدقة)كمية األرقام المعروضة
191
المناوراتsrotalupinaM 4.11
set iosflags)( أعالم تنسيق(long)
ضبط األعالم المحددة
Resetiosflags)(
)أعالم تنسيق long)
مسح األعالم المحددة
إن المناورات التي تأخذ وسيطات تؤثر فقط على; إذا استعملنا المناور ) (setwالبند التالي في الدفق فمثال
لضبط عرض الحقل الذي يتم إظهار رقم ما فيه سنحتاج; مع الرقم التالي. إلى استعماله مجددا
المثال التالي يستعمل بعض هذه المناورات :
//Program 11-2:#include <iostream.h>#include <iomanip.h>
int main) ({cout << hex << 100 << endl;cout << setfill)'?'( << setw)10( << 2343.0;return 0;}
الخرج من البرنامج:
64??????2343
192
على عدد من الداالت التي يمكن iosتحتوى الفئة استخدامها لضبط أعالم التنسيق وتنفيذ مهام أخرى .
الجدول التالي يبين معظم هذه الداالت .
هدفهاالدالةch=fill;) (إعادة حرف الحشو)الفراغ
هو االفتراضي(fill)ch(;ضبط حرف الحشو
p=precision;) (الحصول على الدقةprecision)p(;ضبط الدقة
w=width;) (الحصول على عرض الحقل التالي
setf)flags(;ضبط أعالم التنسيق المحددة
unsetf )flags(;إلغاء ضبط أعالم التنسيق المحددة
setf)flags,field(;ثم ضبط ; مسح الحقل أوالاألعالم
يتم استدعاء هذه الداالت بواسطة كائنات الدفق; لضبط عرض الحقل عند 5باستعمال عامل النقطة ،فمثال
يمكننا كتابة :cout.Width)5(;
; تضبط العبارة التالية حرف الحشو عند * :- أيضاcout.fill)‘*’(;
و) (precision و) (widthالبرنامج التالي يستخدم الدوال fill) (.
//Program 11-3:#include <iostream.h>#include <iomanip.h>int main) ({cout.precision )4( ;cout.width)10(;cout<< 10.12345 <<"\n" ; cout<<setfill)'?'(;cout.width)10(;
193
دوال الدفق snoitcnuF maertS 5.11
cout<< 10.12345 <<"\n" ; //Continued// field width applies to strings, toocout.width)10(;cout<< " Hi!" <<"\n" ; cout.width)10(;cout.setf)ios::left(; cout<< 10.12345 ; return 0;}
الخرج من البرنامج:
10.12*****10.12*******Hi!
10.12*****
نشاطاتios المشتقة من الفئة istreamتنفذ الفئة خاصة بالدخل ونشاطات إضافية. الجدول التالي يوضح
.istreamبعض داالت الفئة
هدفهاالدالة إدخال منسق لكل األنواع األساسية>>
والمحملة بشكل زائدget)ch(إدخال حرف واحدget)str( إلى ; ’o‘\إدخال أحرف إلى مصفوفة وصوال
get)str,max( إدخال حتىmaxأحرف إلى المصفوفة peek)ch( قراءة حرف واحد وتركه في الدفق
putpack)ch(إعادة إدراج الحرف األخير المقروء في دفق الدخل
count=gcount
إعادة عدد األحرف التي قرأها استدعاء)( getline و)(getالدالة
194
maertsi 6.11الفئة
; من هذه الداالت كـ ) (getلقد رأينا حتى اآلن بعضا; .معظمها يعمل على الكائن الحقيقي يمثل لوحةcinمثال
المفاتيح.
195
نشاطات الخرج، يبين الجدول التالي أغلبostreamتعالج الفئة الداالت التي تستعملها هذه الفئة:-
هدفهاالدالة إخراج منسق لكل األنواع األساسية<<
والمحملة بشكل زائدput)ch( إخراج الحرفchفي الدفق
flush) (مسح محتويات الدارئ(Buffer )وإدراج سطر جديد
write)str,size( إخراجsize أحرف من المصفوفة str
. يرتبطcoutو cinلقد استعملنا حتى اآلن كائني دفق هذان الكائنان عادة بلوحة المفاتيح والشاشة على التوالي .
.clog و cerrهناك كائنان آخران هما ; ما يتم استعمال الكائن لرسائل الخطأ.cerrغالبا
; وال يمكن تغييرcerrالخرج المرسل إلى يتم عرضه فورا في حال تعطلcerrوجهته لذا ترى رسالة الخرج من
; لـ ; مماثال ;. هنالك كائنا لكن يتمclog هو cerrالبرنامج كليا.cerrوضع خرج الكائن في الدارئ على عكس
بشكل زائد>> و << يمكن تحميل العوامل إلدخال وإخراج كائنات تابعة لفئات عرفها
<<المستخدم .البرنامج التالي يقوم بتحميل عامل اإلخراج .phonebookبشكل زائد وذلك إلخراج كائن تابع للفئة
//Program 11-4:#include <iostream>#include <cstring>
class phonebook {// now privatechar name[80];int areacode;//Continuedint prefix;int num;public:
196
maertsoالفئة 7.11
8.11 بشكل زائد << و >>تحميل العوامل
phonebook)char *n, int a, int p, int nm({strcpy)name, n( ;areacode = a;prefix =p;num = nm;}friend ostream & operator <<)ostream &stream, phonebook o(;};// Display name and phone number.ostream & operator << )ostream &stream, phonebook o({stream<< o.name <<" ";stream << ")" << o.areacode << "( " ;stream <<o.prefix<< "-" << o.num <<"\n" ;return stream; // must return stream}int main) ({phonebook a)"Mohammed", 011, 011, 123456(;phonebook b)"Omer" , 031, 011, 576890(;phonebook c)"Ali" , 261, 011, 999009(;cout<<a<<b<<c;return 0;}
الخرج من البرنامج:
Mohammed )011( 011 –123456Omer )031( 011–576890Ali )261( 011– 999009
مدى سهولة معاملة كائنات) (mainالحظ في الدالة كأي نوع بيانات أساسي آخر باستعمالphonebookالفئة
العبارة:-
197
cout<<a<<b<<c; على أنها صديقة<< ) (operator تم تعريف الدالة
تظهر فيostream وذلك ألن كائنات phonebookللفئة ; للفئة ; تابعا ostreamالجهة اليسرى للعامل وهى تفيد كائنا
(، تسمح قيم اإلعادة هذه خرج أكثر من قيمة<<)العامل البيانات من الكائن<< واحدة في العبارة . ينسخ العامل
المحدد كالوسيطة الثانية ويرسلها إلى الدفق المحددكالوسيطة األولى. بشكل زائد:->> تحميل العامل
بشكل>> وبنفس الطريقة يمكننا تحميل العامل زائد إلدخال الكائنات التي يعرفها المستخدم بنفسه. >>البرنامج التالي يسمح للمستخدم باستعمال العامل
.phonebookإلدخال كائنات تابعة للفئة //Program 11-5:#include <iostream.h>
#include <cstring.h<
class phonebook {char name[80];int areacode;int prefix;int num;public:phonebook) ( { };phonebook)char *n, int a, int p, int nm({strcpy)name, n( ;areacode = a;//Continuedprefix =p;num = nm;}friend ostream & operator<<)ostream &stream, phonebook o(;friend istream & operator>>)istream &stream, phonebook &o(;
};// Display name and phone number.
198
ostream & operator << )ostream &stream, phonebook o({stream<< o.name <<" ";stream << ")" << o.areacode << "( " ;stream <<o.prefix<< "-" << o.num <<"\n" ;return stream; // must return stream}// Input name and telephone number.istream & operator>> )istream &stream, phonebook &o({cout << " Enter name: ";stream>> o.name;cout << " Enter area code: ";stream>> o.areacode;cout << " Enter prefix: ";stream>> o.prefix;cout << " Enter number: ";stream>> o.num;cout<<"\n" ;return stream;}int main) ({phonebook b;cin>> b;cout << b;//Continuedreturn 0;}
الخرج من البرنامج:
Enter name: AhmedEnter area code: 111Enter prefix: 555Enter number: 1010
Ahmed)111(555 –1010
199
; للمستخدم إنشاء مناورات تقوم بتنسيق يمكن أيضاخاص بالمستخدم .
الصورة العامة إلنشاء مناور خرج هي:-ostream & mani-name) ostream & stream(}
//your code herereturn stream;
{ يقومان) (ra و) ( laالمثال التالي يقوم بإنشاء مناورين
(.( و )بإخراج )//Program 11-6:#include <iostream>#include <iomanip>#include <conio.h>
// Right Arrowostream &ra)ostream &stream({stream << "-> " ;return stream;}// Left Arrowostream &la)ostream &stream({stream << "<- " ;return stream;}int main) ({cout << "High balance" <<ra<< 1233.23<<"\n";cout <<"Over draft" << ra<<567.66<< la;getch)(;return 0;}
الخرج من البرنامج:
High balance 1233.23
200
9.11كيفية إنشاء مناورات خاصة بنا
Over draft 567.66
الصورة العامة إلنشاء مناور دخل هي:-istream & mani-name)istream & stream(}
//your code herereturn stream;
{ ) (getpassالمثال التالي يقوم بإنشاء مناور دخل
‘\والثاني يقوم بإخراج صوت جرس باستعمال تتابع الهروب a’ ويطلب من المستخدم إدخال password.
//Program 11-7:#include <iostream>#include <cstring>
// Asimple input manipulator.istream &getpass )istream &stream({cout << '\a' ; // sound bellcout << "Enter password: ";return stream;}int main) ({char pw[80];
do cin>> getpass >>pw; while )strcmp )pw, "password"((;cout <<"logon complete\n";return 0;}
الخرج من البرنامج:
Enter password: passwordLogin complete
201
الدفق هو اسم عام يطلق لسيل من البيانات في حالة دخل /خرج.
الفئةios/ هي الفئة القاعدة لهرمية دفق الدخل الخرج.
الفئاتistream، ostream مشتقتان من الفئة ios وهما مختصتان بأعمال الدخل والخرج.
أعالم التنسيق هي مجموعة من األعضاء في الفئةios تعمل على تنسيق الدخل والخرج.
المناورات هي تعليمات تنسيق تدرج في الدفق مباشرة.
هنالك نوعان من المناورات، نوع يأخذ وسيطة واآلخر ال يأخذ أي وسيطة.
الحالة التي تضبطها المناورات التي ليس لها وسيطات تبقى نشطة إلى أن يتم الدفق.
عند استعمال المناورات يجب إخراج ملف الترويسة iomanip.h.
تحتوى الفئةiosعلى عدد من الداالت التي يمكن استخدامها لضبط أعالم التنسيق.
تنفذ الفئةostream المشتقة من الفئة iosنشاطات خاصة بالدخل.
تعالج الفئةostream.نشاطات الخرج يتم استعمال الكائنcerr.لعرض رسائل الخطأ بشكل زائد إلدخال و بشكل>> و <<يمكن تحميل
زائد إلدخال وإخراج كائنات تابعة لفئات عرفهاالمستخدم.
.يمكن إنشاء مناورات تقوم بتنسيق خاص بالمستخدم
202
الملخص:
قم بكتابة برنامج ينفذ اآلتي:-1 مع محاذاته على اليسار40000طباعة العدد الصحيح
.15على أن يكون عرض الحقل قراءة سلسلة وتخزينها في مصفوفة أحرفstate. بعالمة وبدون عالمة.200طباعة بالنظام السادس عشر.100طباعة العدد
/ أكتب برنامجاb لدخل أعداد صحيحة بالنظام العشري والثماني2
والسادس عشر وخرج هذه األعداد. اختبر البرنامج بالبيانات اآلتية:
010 , 010 , 10
203
األسئلة
الوحدة الثانية عشرة
gnissecorP eliFمعالجة الملفات 0.21
الوحدة: هذه بنهايةالملفات على وتتعرف الدفق مع التعامل من ستتمكن
التتابعية.معها. والتعامل تتابعية، ملفات إنشاء من ستتمكنالمختلفة السجالت إلى الوصول من ستتمكن .; تتابعياالمختلفة السجالت إلى الوصول من ستتمكن .; عشوائيا
تخزين البيانات في المتغيرات أو المصفوفات هو تخزين مؤقت، لذلك نحتاج الى وسيلة تخزين دائمة. وتوفر
هذه الوسيلة.Filesالملفات يخزن الحاسوب الملفات في وسائط التخزين الثانوية
مثل األقراص. في هذه الوحدة، سنوضح كيفية إنشاء ومعالجة
.++Cالملفات من خالل برامج لغة عادة تتكون المفات من مجموعة من السجالت
Recordsوالتي تتكون بدورها من مجموعة من الحقول Fieldsعلى مجموعة من ; . يتكون ملف للموظفين مثال
; السجالت )سجل لكل موظف(، وقد يحتوي السجل مثالعلى الحقول التالية:
رقم الموظف..1إسم الموظف..2العنوان..3المرتب..4
لتسهيل الوصول الى سجل ما في ملف، يتم اختيار . والذي يجب أن يكونRecord Keyحقل مفتاحي للسجل
; في الملف.Uniqueفريدا في ملف الموظفين اعاله، يمكن اختيار رقم الموظف
كحقل مفتاحي للملف. هناك عدة طرق لتنظيم السجالت داخل الملف، أشهر
Sequential Filesالطرق المستخدمة هي الملفات التتابعية والتي يتم فيها تخزين السجالت بترتيب حقولها المفتاحية،
; في ملف الموظفين، يكون أول سجل هو السجل فمثالالذي يحمل أقل رقم موظف.
الملفات كفيض متتابع من الثمانيات++Cتعامل Bytes الشكل التالي يوضح ملف يتكون من .n Byte
عند فتح ملف يتم إنشاء كائن يقترن معه الدفق. لقد;، وهي ، coutرأينا من قبل أربعة كائنات منشأة أتوماتيكيا
cin ، cerr و clog.
204
مقدمة .211
الملفات والدفقmaertS dna seliF 2.21
0 1 2 3 4 5 6 7 8 9 -n1dne…………
……
إلدخال بيانات من لوحة المفاتيح،cinيستخدم الكائن يستخدم إلخراج بيانات إلى الشاشة، والكائنانcoutوالكائن
cerr وclogيستخدمان إلخراج رسائل األخطاء إلى الشاشة.
عند التعامل مع الملفات، يجب تضمين ملفي حيث يحتوي الملفfstream.h و iostream.hالترويسة
fstream.h على فئات الدفق ifstreamوالتي تستخدم في ( )والتي تستخدمofstreamإدخال بيانات إلى الملفات( و )إلدخال وإخراجfstreamإلخراج بيات من المفات(، و
بيانات من الملفات(.لفتح ملف، نحتاج إلنشاء كائن يتبع إلحدى هذه الفئات.
أي هيكلية معينة للملف، وعليه ال++ Cال تتطلب لذا يجب على++Cيوجد مصطلح سجالت في ملفات
المبرمج تحديد الكيفية التي يتم بها تنظيم الملف.البرنامج التالي يوضح كيفية إنشاء ملف تتابعي:
//Program 12-1//Creating a sequential file#include<iostream.h>#include<fstream.h>#include<stdlib.h>main) ({ ofstream outclientfile)“clients.dat”,ios::out(; if )!outclientfile({ cerr<<”File could not be opened”<<endl; exit )1(;} cout<<”Enter the account, name, and balance.”
<<endl <<”)Enter EOF to end input(”<<endl <<”? “; int account; char name[10];//Continued float balance;while)cin>>account>>name>>balance({
205
إنشاء ملف تتابعيelif laitneuqeS a gnitaerC 3.21
outclientfile<<account<<” “<<name<<” “<<balance
<<endl;cout<<”? “;} return 0;}
الخرج من البرنامج:
Enter the account, name, and balance.)Enter EOF to end input(? 100 Ahmed 24.98? 200 Ali 345.67? 300 Hassan 0.00? 400 Omer –42.16? 500 Abbas 224.62? ^Z
;، حيث يمكن ; تتابعيا البرنامج السابق ينشئ ملفا; ليساعد في إدارة استخدامه في نظام حسابات مثال
حسابات العمالء. لكل عميل من العمالء، يتحصل البرنامج على رقم
ورصيدname وإسم العميل accountحساب العميل . البيانات التي يتحصل عليها البرنامج لكلbalanceالعميل
عميل تمثل سجل ذلك العميل. يستخدم رقم حساب العميل كحقل مفتاحي، وعليه
; بترتيب أرقام حسابات العمالء. يكون الملف مرتبا تم فتح الملف للكتابة فيه، لذلك ينشئ البرنامج كائن
، وتم تمريرoutclientfile يدعى ofstreamخرج تابع للفئة وسيطتين لمشيد ذلك الكائن وهما إسم الملف
Clients.dat طريقة فتح الملف ،(File open mode) ios::out
يقوم البرنامج، باستقبال البيانات المدخلة وحفظها في.(ctrl> Z)<الملف، إلى أن يتم إدخال رمز نهاية الملف
206
خرج البرنامج يفترض أنه تم إدخال بيانات خمسة.Z^عمالء، ثم تم إدخال رمز نهاية الملف
الذيstdlib.hنالحظ أننا قمنا بتضمين ملف الترويسة ، والتي تنهي البرنامج فيexitيحتوي على تعريف الدالة
حالة عدم فتح الملف بصورة صحيحة.
سنقوم اآلن بكتابة برنامج يقوم بقراءة الملفالسابق، وطباعة محتوياته على الشاشة:
Program 12-2://Reading and printing a Sequential file#include<iostream.h>#include<fstream.h>#include<iomanip.h>#include<stdlib.h>
void outputline)int, char *, float(;main) ({ ifstream inClientFile)“clients.dat”,ios::in(; if )!inClientFile( { cerr << “File could not be opened” <<endl; exit)1(; }int account;char name[10];
//Continuedfloat balance;cout <<setiosflags)ios::left( <<setw)10( <<”Account”
<<setw)13( <<”Name” <<”Balance”<<endl;
while)inClientFile >> account >.name >>balance( outputline)account, name, balance(; return 0;}
207
قراءة البيانات من ملف تتابعيelif laitneuqeS a morf ataD gnidaeR 4.21
void outputline)int acct, char *name, float bal({
cout << setiosflags)ios::left( << setw)10(<< acct << setw)13( << name<< setw)7( << setprecision)2(
<< setiosflags)ios::showpoint | ios::right(<< bal << endl;
}
الخرج من البرنامج:
Account Name Balance100 Ahmed 24.98200 Ali 345.67300 Hassan 0.00400 Omer -42.16500 Abbas 224.62
يتم فتح الملفات لقراءة بيانات منها بإنشاء كائن يتبع والذي يتم تمرير وسيطتين له هما إسمifstreamللفئة
.File Open mode وطريقة فتح الملف clients.datالملف فاإلعالن:
ifstream inClientFile)“clients.dat”,ios::in(; ،inClientFile يدعى ifstreamينشئ كائن تابع للفئة
ليقوم بفتح الملف clients.dat.للقراءة منه
يملك كل كائن ملف، مؤشرين مقترنين به يسميان ،put pointer ومؤشر الوضع get pointerمؤشر الحصول
; مؤشر الحصول الحالي ومؤشر الوضع ويسميان أيضاالحالي.
في بعض األحيان، قد نرغب في بدء قراءة الملف من بدايته ومتابعته إلى نهايته، وقد ترغب عند الكتابة البدء من
البداية وحذف أي محتويات موجودة ،لكن هنالك أوقات نحتاج فيها إلى التحكم بمؤشرات الملفات. لكي نتمكن من
القراءة أو الكتابة في مواقع عشوائية من الملف.
208
الوصول العشوائي لمحتويات ملف تتابعيelif laitneuqeS a ot sseccA modnaR 5.21
6
ضبط مؤشري الحصولseekp و seekgتتيح الدالتان والوضع على التوالي.
بطريقتين :-) (seekp و ) (seekgيمكن استخدام الدوال / مع وسيطة واحدة هي موقع البايت المطلق في الملف )1
(.0بداية الملف هي البايت / مع وسيطتين األولى إزاحة من موقع معين في الملف2
والثانية الموقع الذي تم قياس اإلزاحة منه.هنالك ثالثة احتماالت للوسيطة الثانية:-
وهى بداية الملف.begأ() وتعنى الموقع الحالي للمؤشر.Cur ب() وتعنى نهاية الملف.End ت()
; العبارة :- فمثالseekp) -10,ios:: end(;
بايتات قبل نهاية الملف.10ستضع مؤشر الوضع مع وسيطةseekgالبرنامج التالي يستخدم الدالة
واحدة:Program 12-3:#include<iostream.h>#include<fstream.h>#include<iomanip.h>#include<stdlib.h>void outputline)int, char *, float(;main) ({//Continued ifstream inClientFile)“clients.dat”, ios::in(; if )!inClientFile({ cerr<< “File could not be opened” <<endl; exit)1(; }cout <<”Enter request “<<endl
<<” 1 – List accounts with zero balances” << endl
<<” 2 – List accounts with credit balances”<<endl
<<” 3 – List accounts with debit balances”<<endl
<<” 4 – End of run” <<endl<<”?”;int request;//Continued
209
cin>> request;while)request !=4( {
int account;char name[10];float balance;inClientFile >>account >>nam>>balance;switch )request( { case 1: cout <<endl <<”Account with zero
balances:”<<endl;
while)!inClientFile.eof)(( { if )balance==0( outputline)account, name, balance(; inClientFile >>account >>name
>>balance;}break;case 2: cout<<endl<<”Accounts with credit
balance:” <<endl;
while)!inClientFile.eof)(( { if )balance <0( outputline)account, name, balance(;//Continued inClientFile>>account >>name >>balance;}break;case 3: cout<<endl<<”Accounts with debit
balances:” <<endl; while)!inClientFile.eof)(( { if )balance > 0( outputline)account, name, balance(;inClientFile >>account>>name>>balance;}break;
} inClientFile.clear) (; //reset eof for next input
210
inClientfile.seekg)0(; //position to beginning of file cout<<endl <<”? “; cin>>request;}
cout << “End of run.” <<endl;
return 0;}cout << setiosflags)ioa::left( << setw)10( << acct << setw)13( << name <<setw)7( <<setprecision)2( << setiosflags)ios::showpoint | ios::right( <<bal <<endl;}
:الخرج من البرنامج
Enter request1 – List accounts with zero balances2 – List accounts with credit balances3 – List accounts with debit balances4 – End of run?1Accounts with zero balances:300 Hassan 0.00
?2
Accounts with credit balances:400 Omer -42.16
?3Accounts with debit balances:100 Ahmed 24.98200 Ali 345.67
211
500 Abbas 224.62 ?4End of run.
212
.الملفات هي وسيلة دائمة لتخزين البيانات.تتكون الملفات عادة من مجموعة من السجالت.تتكون السجالت من مجموعة من الحقول.يكون لكل سجل حقل مفتاحيفي الملفات التتابعية يتم تخزين السجالت بترتيب
حقولها المفتاحية.عند التعامل مع الملفات يجب تضمين الملف
fstream.h.عند فتح ملف للكتابة فيه يجب إنشاء كائن تابع للفئة
ofstream.يتم فتح الملفات لقراءة بيانات منها بإنشاء كائن يتبع
.ifstreamالفئة إلسترجاع بيانات من ملف تتم قراءة الملف من بدايته
وقراءة كل محتويات الملف بالتتابع حتى نصل إلىالبيانات المطلوبة.
يملك كل كائن ملف مؤشرين مقترنين به يسميان .Put pointer ومؤشر الوضع get pointerمؤشر الحصول
تضبط الدالتانseekg ) ( و seekp) (مؤشري الحصول والوضع على التوالي.
213
الملخص:
على Employeeأنشئ ملف للموظفين يدعى -1 أن يحتوي كل سجل في الملف على الحقول
التالية:-.رقم الموظف.إسم الموظف.العنوان
ثم قم بإدخال بيانات خمسة موظفين.
تأكد من إدخال البيانات في السؤال السابق-2 بصورة صحيحة وذلك بكتابة برنامج لقراءة
محتويات الملف.
قم بكتابة برنامج يقوم باستقبال معلومات-3 عن طالب كلية ويضعها في ملف يسمى
Studentsبحيث يحتوي ملف الطالب على ، اآلتي:
.رقم الطالب.إسم الطالب.تخصص الطالب.درجة الطالبومن ثم قم بكتابة برنامج يقوم بقراءة هذا
الملف.
214
األسئلة