Professional Documents
Culture Documents
المرجع السريع للبرمجة بلغة C++ PDF
المرجع السريع للبرمجة بلغة C++ PDF
3
فهرس انمحتىٌاث
9 مقدمة إلى البرمجة
10 البداٌة مع البرمجة
10 لغة البرمجة
11 لمحة تارٌخٌّة عن C++
11 لمن هذا الكتاب ؟
11 كٌف أقرأ هذا الكتاب ؟
23 فصول الكتاب
14 التعامل مع المترجم visual c++ 6.0
17 الفصل األول :بنٌة البرنامج فً لغة الـ C++ القسم األول
18 تنسٌق الكتابة
19 التعلٌقات
19 تمارٌن
20 الفصل الثانً :المتغ ٌّرات ( ( Variables
21 حساسٌة اللغة لحالة األحرف
21 أنواع البٌانات )(Data types
24 مقدّمة إلى السبلسل ) ( strings
25 تمارٌن
26 الفصل الثالث :اإلدخال و اإلخراج ) ( Input and Output
26 تعلٌمة اإلخراج )(cout
28 تعلٌمة اإلدخال )(input cin
28 بعض الرموز الخاصة
29 تمارٌن
30 الفصل الرابع :الثوابت ()Constants
31 الفصل الخامس :المعامالت )(Operators
31 اإلسناد )=(
31 المعامبلت الرٌاضٌّة ) ( + , - , * , / , %
32 معامبلت اإلسناد المركبة ) =| ( += , -= , *= , /= , %= , &= , ^= ,
32 معامبلت الزٌادة والنقصان )(++ , --
32 معامبلت المقارنة ) => ( == , != , < , > , <= ,
33 المعامبلت المنطق ٌّة ) || ( ! , && ,
33 المعامل الشرطً ) ؟ (
34 معامل تحوٌل البٌانات
4
34 المعامل )(sizeof
34 أولوٌات تنفٌذ المعامبلت
36 تمارٌن
37 الفصل السادس :بنى التحكم ()Control Structures
37 بنٌة الشرط condition structure
39 بنى التكرار loops or repetition structures
42 التعلٌمة break
42 التعلٌمة continue
43 التعلٌمة goto
43 التعلٌمة switch
46 الحلقات المتداخلة nested loops
48 تمارٌن محلولة
56 تمارٌن
58 الفصل السابع :التوابع ()Functions
60 التوابع التً ال تعٌد قٌمة ) استخدام الكلمة ( void
61 تمر ٌر الوسطاء بالقٌمة وبالمرجع )العنوان(
63 المدى Scope
63 المتغٌرات الشاملة Global variablesو المتغٌرات الموضعٌة Local variables
64 المتغٌرات الثابتة static
64 تعٌٌن القٌمة االفتراضٌة للوسطاء
65 إعادة تحمٌل التوابع functions overloading
65 التعرٌف المبدبً للتوابع functions prototype
67 الفصل الثامن :التعاودٌة ()Recursion
72 تمارٌن محلولة
86 تمارٌن
5
92 الفصل العاشر :سالسل الرموز ()Strings of Characters
92 التعامل مع السبلسل
95 الفصل الحادي عشر :المؤشرات ()pointers
95 معامل العنوان ) & (
95 معامل المرجع ) * (
:7 التصرٌح عن المإ ّ
شرات
:8 المإ ّ
شرات والمصفوفات
:9 تبدبة المإ ّ
شرات
:9 مصفوفة المإ ّ
شرات
99 العملٌات الحسابٌة على المإ ّ
شرات
100 شرات على المإ ّ
شرات المإ ّ
100 المإ ّ
شرات الخالٌة void pointers
101 المإ ّ
شرات على التوابع
103 الفصل الثانً عشر :الذاكرة الدٌنامٌكٌة ()Dynamic Memory
103 المعامل new
104 المعامل delete
105 الفصل الثالث عشر :التراكٌب ()Structures
105 تراكٌب المعطٌات
107 مصفوفة التراكٌب
108 التراكٌب و المإ ّ
شرات
109 التراكٌب المتداخلة
113 الفصل الرابع عشر :األنواع المعرفة من قبل المستخدم
113 تعرٌف أنواع خاصّة ) ( typedef
113 الوحدات ) ( Unions
114 المر ّقمات ) Enumerations ( enum
114 الفصل الخامس عشر :اإلدخال و اإلخراج فً الملفات
115 فتح ملف
116 إغبلق ملف
116 الملفات النصٌّة
117 التحقق من الحالة
117 مإ ّ
شرا التدفق ) putو ( get
119 الفصل السادس عشر :معالجة االستثناءات ( ) Exceptions handling
6
122 التوجه ()OOP
ّ الفصل السابع عشر :البرمجة كائن ٌّة القسم الثالث
122 مقدّمة
123 معرّ فات الوصول Access modifieres
125 معامل المدى ::
125 التوابع األعضاء inline
128 المشٌّدات Constructors
129 الهادمات Destructors
129 إعادة تحمٌل المشٌّدات Overloading Constructors
132 المإ ّ
شرات على الصفوف Pointers to classes
133 الكلمة المفتاحٌّة this
135 الصفوف المعرّ فة باستخدام الكلمة المحجوزة struct
135 إعادة تحمٌل المعامبلت Overloading operators
138 األعضاء الثابتة من النوع static
140 التوجه ()OOP principles
ّ الفصل الثامن عشر :مبادئ البرمجة كائن ٌّة
140 مبدأ التغلٌف Encapsulation
142 التوابع friendالكلمة المفتاحٌّة ) ( friend
143 الصفوف من النوع friend
144 الوراثة بٌن الصفوف Inheritance between classes
147 الوراثة المتعددة Multiple inheritance
148 تعدد األشكال Polymorphism
148 المإ ّ
شرات على الصفّ األساسً Pointers to base class
149 األعضاء من النوع virtual
152 الصفوف األساسٌّة المجردة Abstract base classes
155 الفصل التاسع عشر :القوالب ()Templates
155 تابع القوالب
157 صفّ القوالب
158 تخصٌص القالب Template specialization
061 الفصل العشرون :فضاءات األسماء ()Namespaces
272 التعلٌمة using namespace
273 الفضاء std
061 حلول التمارٌن غٌر المحلولة
7
املقدّمة:
الحمد هلل ربّ العالمٌن الرحمن الرحٌم مالك ٌوم الدٌن ,والصبلة والسبلم على س ٌّد األوّ لٌن واآلخرٌن مح ّمد النبًّ
األمٌن وعلى آله وصحبه ال ُغرِّ المٌامٌن ومن اهتدى بهدٌهم واستنَّ بسنتهم أجمعٌن.
قال هللا تعالى" :1وقل ربِّ ِزدنً علما" .قال ابنُ كثٌر فً تفسٌره" :أي :زدنً منك علما".
قال ابن ُع ٌَ ٌْ َن َة رحمه هللا" :ولم ٌزل رسول هللا صلى هللا علٌه وسلم فً زٌادة ] من العلم [ ح ّتى تو ّفاه هللا ع ّز
وج ّل".
وعن أبً هرٌرة ,رضً هللا عنه ,أنّ رسول هللا ,صلى هللا علٌه وسلم ,قال" :ومن سلك طرٌقا ٌلتمس فٌه علما,
س ّهل هللا له به طرٌقا إلى الجنة".
ملعونة ,ملعونٌ ما فٌها ,إال ذكر هللا تعالى ,وما ٌ وعنه قال :سمعت رسول هللا ,صلى هللا علٌه وسلمٌ ,قول" :الدنٌا
2
وااله ,وعالما ,أو متعلما".
وعن أنس ,رضً هللا عنه قال :قال رسول هللا ,صلى هللا علٌه وسلم" :من خرج فً طلب العلم ,فهو فً سبٌل
3
هللا ح ّتى ٌرجع".
خٌروعن أبً سعٌ ٍد الخدري4 ,رضً هللا عنه ,عن رسول هللا ,صلى هللا علٌه وسلم ,قال" :لن ٌشبع مإمنٌ من ٍ
ح ّتى ٌكون منتهاه الجنة".
وعن أبً أمامة ,رضً هللا عنه ,أنّ رسول هللا ,صلى هللا علٌه وسلم ,قال" :فضل العالم على العابد كفضلً
على أدناكم ث ّم قال رسول هللا ,صلى هللا علٌه وسلم :إن هللا ومبلبكته وأهل السموات واألرض حتى النملة فً
5
جحرها وحتى الحوت لٌصلون على معلمً الناس الخٌر".
علم فكتمه ,ألجم ٌوم رضً هللا عنه ,قال :قال رسول هللا صلى هللا علٌه وسلم" :من سبل عن ٍ وعن أبً هرٌرة,
6
ار". بلجام من ٍ
ن ٍ القٌامة
صل األجر طبلبه فً الدنٌا واآلخرة ولكً ُتح ّ إنّ ما تق ّدم من اآلٌات واألحادٌث إ ّنما ٌ ّدل على فضل العلم و ّ
العظٌم من هللا تعالى علٌك أن تعلم أنّ ن ٌّتك فً طلب العلم مه ّمة فقد روى إماما المح ِّدثٌن البخاريّ ومسلم رضً
حفص عمر بن الخطاب ٍ هللا عنهما فً صحٌحٌهما -اللذٌن هما أص ّح الكتب المص ّنفة -عن أمٌر المإمنٌن أبً
ئ ما رضً هللا عنه ,قال" :سمعت رسول هللا صلى هللا علٌه وسلم ٌقول :إ ّنما األعمال بالن ٌّات ,وإ ّنما لك ّل امر ٍ
نوى فمن كانت هجرته إلى هللا ورسوله فهجرته إلى هللا ورسوله ,ومن كانت هجرته لدنٌا ٌصٌبها ,أو امرأ ٍة
7
ٌن ِك ُحها فهجرته إلى ما هاجر إلٌه".
إ ّنما ُجعِل هذا الكتابُ لٌكون مساعدا للذٌن ٌو ّدون تعلّم شًء من علوم البرمجة )برمجة الحاسب( وفً محاول ٍة
ك أح ٌد بإهمٌته للبشرٌة جمعاء ولؤل ّمة اإلسبلم ٌّة على وجه لزٌادة الكتب العرب ٌّة التً تهت ّم بهذا العلم الذي ال ٌش ُّ
ُون ِب ْال َمعْ رُوفِ َو َت ْن َه ْو َن َع ِن ْ ُ ُ
الخصوص تلك األمّة التً خاطبها هللا تعالى فقالُ " :ك ْن ُت ْم َخٌ َْر أ َّم ٍة أ ْخ ِر َج ْ
ت لِل َّن ِ
اس َتؤ ُمر َ
8
ان َخٌْرا لَ ُه ْم". اهلل َولَ ْو آ َم َن أَهْ ُل ْال ِك َتا ِ
ب لَ َك َ ون ِب َّ ِْال ُم ْن َك ِر َو ُت ْإ ِم ُن َ
عز وج ّل أن تعود هذه األ ّمة إلى عهدها قابدة ورابدة فً كل المجاالت ومشكاة للنور ومنبعا للفكر سابلٌن المولى ّ
العذب الصافً.
8
إهداء
عّا .
إلى والدينا األ ّ
كل المسلمين.
إلى ّ
المؤلفان
يف يوم السبت 81ذي القعدة سنة 8341هجريّة
9
مق ّدمة إلى البرمجة
تحت ّل علوم الحاسب اإللكترونًّ فً أٌامنا هذه مكانة عالٌة بٌن العلوم وهً ترتبط بشكل وثٌق ج ّدا مع ك ّل العلوم
األخرى بدء بالعلوم الرٌاض ٌّة والفٌزٌاب ٌّة مرورا بعلوم اللغات والعلوم الطب ٌّة وغٌرها.
وم ّما هو معلوم عند الناس أنّ الحاسبات تإ ّدي العدٌد من الوظابف المه ّمة فً حٌاتنا الٌومٌة بسرعة وكفاءة
عالٌتٌن وبدقة كبٌرة فً النتابج األمر الذي ساعد العلماء على اختراع الكثٌر من اإلبداعات العلمٌة بسرعة كبٌرة
تفوق تصوّ رات الكثٌرٌن من البشر ابتداء باآلالت المٌكانٌكٌة كالسٌارات إلى عالم اإلنترنت الملًء بالمفاجآت
وصوال إلى القمر حٌث استطاع البشر الوصول إلٌه بإذن هللا تعالى ث ّم بما أبدعته عقول العلماء وبمساعدة هذه
الحاسبات.
ّإال أنّ الحاسب ال ٌستطٌع أن ٌفعل أي شًء مالم ٌقم اإلنسان بتعلٌمه وتدرٌبه على القٌام به هذا األمر من خبلل
صٌصا لٌرافقك عزٌزي القارئ فً رحلة- ص ِنع ِخ ّ
برمجة الحاسب على القٌام بما نرٌده أن ٌقوم به وهذا الكتاب ُ
نرجو من هللا أن تكون ممتعة بالنسبة لك– فً رحاب إحدى أه ّم وأقوى لغات البرمجة لتتم ّكن بعدها من قٌادة
حاسبك وجعلِه ٌفعل كل األشٌاء التً ترٌدها منه.
ٌشبه هذا األمر الطرٌقة التً ٌ ّتبعها الناس فً تربٌة وتعلٌم أبنابهم حٌث ٌُول ُو َنهم الحبّ والرحمة وٌحاولون
جاهدٌن أن ٌجعلوا من أوالدهم أفضل ما ٌمكن ,وما نرٌده منك فً هذه الرحلة أن تعزم على أن تقرأ هذا الكتاب
فالصبر
َ كامبل وأن تتحلى بالصبر قال هللا تعالى " :واستعٌنوا بالصبر والصبلة وإ ّنها لكبٌرة إال على الخاشعٌن",
الصبر.
قد ٌبدو األمر صعبا فً أوّ له ولك ّنه سٌسهل شٌبا فشٌبا مع تق ّدمك فً صفحات هذا الكتاب وتمرّ نك على ما فٌه
من التمارٌن واألسبلة وال تكتفِ بذلك بل اكتب كل ما ٌخطر ببالك من برامج وإن لم تتم ّكن من ذلك بسهولة ,و
حاول أن تح ّل ك ّل المشاكل التً تواجهها باستخدام البرمجة لٌتث ّنى لك ما ترٌد ,وتذ ّكر دابما ما قاله أجدادنا
الحكماء" :إهمال ساعة ٌفسد رٌاضة دهر" فإ ٌّاك واإلهمال وواصل العمل بج ّد فمن ج ّد وجد ومن سار على
الدرب وصل ,ولكً تكون على الدرب علٌك أوّ ال أن تعرف الدرب وهذا ال ٌكون ّإال بالتخطٌط وتحدٌد األهداف
ث ّم األسباب ث ّم تضع الخطة وتبدأ بتنفٌذها وتذ ّكر هدفك دوما –الغاٌة األسما لكل مسلم إرضاء هللا عز وجل–
واعمل له ك ّل ساعة.
أخٌرا أقول لكِ " :اعمل لدنٌاك كؤ ّنك تعٌش أبدا واعمل آلخرتك كؤ ّنك تموت غدا".
:
البداٌة مع البرمجة
نقصد بالبرمجة صناعة البرامج ولٌس شرطا أن تكون برامجا تعمل فقط على الحاسبات أو على اآلالت
اإللكترونٌة .البرامج هً مجموعة من التعابٌر المنطقٌّة والرٌاض ٌّة الخاصة المرتبطة مع بعضها لتكوّ ن حلوال
لمشاكل معٌنة.
ولكً نكتب برنامجا ما علٌنا أن نقوم بخطوات مح ّددة قبل ذلك وهذه الخطوات تبدأ أوّ ال بتحلٌل المشكلة المعطاة
إلى مشاكل أبسط ث ّم نقوم بوضع خطوات الحل وذلك وفق ترتٌب مع ٌّن ٌبلبم التحلٌل الذي حصلنا علٌه وهذا
الترتٌب لخطوات الحل ٌدعى بالخوارزمٌة ,ث ّم كتابة البرنامج بلغة البرمجة.
الخوارزمٌة :هً خطوات منطق ٌّة مر ّتبة ترتٌبا صحٌحا لح ّل مشكلة مع ٌّنة.
ال ب ّد فً كل برنامج من مرحلتً التحلٌل وكتابة الخوارزمٌة بعد ذلك ٌؤتً دور الحاسب .حٌث ٌتبقّى أن تقوم
بترجمة الخوارزمٌة التً صغتها إلى برنامج مكتوب بإحدى لغات البرمجة ث ّم ٌقوم الحاسب بعمله لٌعطٌك
البرنامج الذي قمت بكتابه.
مثبل ّ لنفترض أ ّننا نرٌد أن نقوم بحساب مساحة مستطٌل.
ّأوالا :لنحلّل هذه المشكلة
ما هو المستطٌل و كٌف نحسب مساحته ؟ المسطٌل هو شكل هندسً له أربعة أضبلع اثنان منها ٌمثبلن الطول
واالثنان اآلخران ٌمثبلن العرض أ ّما مساحته فهً تنتج من ضرب الطول بالعرض.
الخوارزمٌة:
-1اقرأ الطول ث ّم العرض
-2اضرب الطول بالعرض
-3أعطنً الناتج
تمثل خوارزم ٌّة لحل مشكلتنا السابقة .سنعتمد فً هذا الكتاب على كتابة الخوارزمٌات بنفس هذه الخطوات ّ
صصة فً هذا المجال أ ّما هذا الكتاب الطرٌقة السابقة .ولن نكثر من الشرح حول الخوارزم ٌّات فهناك كتب متخ ّ
فهو ٌناقش البرمجة وبعض البرامج وما ٌه ّمنا هو توضٌح الفكرة من الخوارزمٌات فقط ولن نحتاج إلٌها كثٌرا
خبلل هذه الرحلة وٌمكنك التو ّسع فً ذلك المجال بقراءة بعض الكتب المختصة .اآلن بعد أن قمنا بوضع
الخوارزم ٌّة بقٌت المرحلة األخٌرة لكتابة البرنامج أال وهً ترجمتها إلى لغة برمجة ٌعرفها الحاسب.
لغة البرمجة
ٌواجه المبرمجون المشكلة ذاتها التً ٌواجهها المسافرون إلى بلدان أجنب ٌّة وهً مشكلة اختبلف لغة التخاطب
بٌن المسافر والبلد الذي سافر إلٌه فكان من المناسب إٌجاد ح ّل لهذه المشكلة وهو الٌوم اتقان اللغة األكثر شهرة
مثل اللغة اإلنكلٌز ٌّة مثبل فمعظم الناس ٌستطٌعون التح ّدث بهذه اللغة ,وكذلك األمر عند المبرمجٌن ت ّم إٌجاد
صة للتخاطب بٌن البشر)المبرمجٌن( والحاسب والتً تعرف بلغات البرمجة programming لغات خا ّ
languagesوهذه اللغات صنعت لهذا الغرض ولن نطٌل الكبلم حول هذا الموضوع فالكبلم فٌه طوٌل ولٌس
له أهم ٌّة كبٌرة فً تعلّم البرمجة وتستطٌع عزٌزي القارئ الحصول على المعلومات الكاملة حول هذا الموضوع
من خبلل اإلنترنت ففٌه الكثٌر م ّما ٌجب علٌك أن تتعلّمه أ ّما ما ٌه ّمنا هنا هو أنّ ما ٌكتب باستخدام لغة البرمجة
ٌسمى شٌفرة.
لكً ٌستطٌع الحاسب معرفة هذه اللغة ت ّم تصنٌع برامج أخرى س ّمٌت مترجمات compilersتقوم هذه
المترجمات بترجمة الشٌفرة التً تكتب بلغة البرمجة إلى لغة أخرى هً لغة اآللة إذ أنّ الحاسب ٌمتلك لغة
ٌمثل كل البٌانات والمعلومات فٌه على شكل سبلسل من األرقام الثناب ٌّة ) 0و (1ما ٌجعل صة حٌث ّ خا ّ
التخاطب معه بلغته أمرا فً غاٌة الصعوبة والتعقٌد.
21
لمحة تارٌخ ٌّة عن C++
طوّ رت C++من لغة Cالتً طوّ رت بدورها من لغتٌن سابقتٌن هما BCPLو . B
قام مارتٌن رٌكارد Martin Richardsعام 2:78م بتطوٌر BCPLكلغة لكتابة أنظمة التشغٌل والتطبٌقات و
المترجمات.
وأضاف كِن ثومبثون Ken Thompsonالعدٌد من المٌزات الجدٌدة إلى لغته Bالتً تشبه BCPLإلى ح ّد كبٌر
واستخدمها فً إنتاج النسخ األولى من نظام التشغٌل Unixالشهٌر وذلك فً مختبرات Bellعام 2:81م
باستخدام الحاسب المعروف بـ DEC DPD-7كلتا اللغتٌن كانتا عدٌمتً األنواع فً البداٌة.
طوّ ر دٌنِس رٌتشً Dennis Retchieلغة Cمن لغة Bفً مختبرات Bellباستخدام الحاسب DEC DPD-
11عام 2:83م.
حٌث استخدمت Cالعدٌد من األفكار الموجودة فً اللغتٌن Bو BCPLو أضافت إلٌهما أنواع البٌانات وبعض
المٌزات األخرى.
ومن هذه اللغة التً تل ّقت العدٌد من التعدٌبلت والتطوٌرات ح ّتى نالت درجة القٌاسٌة العالمٌة
) ISO(International Standards Organaizatoionت ّم تطوٌر لغة C++فً مختبرات Bellمن خبلل
Bjarne Stroustrupفً مطلع الث ّمانٌنات.
زوّ دت C++بمجموعة من المزاٌا ّإال أنّ أه ّمها كان دعمها لمبادئ البرمجة كابن ٌّة التوجه OOP(Object-
)Oriented Programming
هذا الكتاب لك ّل من ٌرٌد أن ٌتعلّم البرمجة وال ٌفترض هذا الكتاب وجود أيّ معرفة لدى القارئ لذلك لٌس مه ّما إن كانت
هذه أوّ ل مرّ ة تقرأ فٌها كتابا فً هذا المجال أو إن كانت المرّ ة األولى التً تقرّ ر فٌها تعلّم البرمجة ,وكذلك لؤلشخاص
الذٌن ٌو ّدون االنتقال من لغات أخرى إلى هذه اللغة ٌمكن أن ٌق ّدم هذا الكتاب المبادئ األساس ٌّة للبرمجة باستخدام لغة
C++ولكنّ هذا الكتاب ال ٌعطً لؤلشخاص المتق ّدمٌن فً البرمجة سوى مراجعة لبعض معلوماتهم السابقة وقد ٌضٌف
بعض األفكار البسٌطة إن لم ٌكونوا قرإوها من قبل.
22
فصول الكتاب
نتح ّدث فً هذا الفصل عن البنٌة األساس ٌّة للبرنامج وفق قواعد اللغة ونتناول أه ّم العناصر المش ّكلة للبرنامج ونشرح ك ّل
واحدة منها من خبلل البرنامج األوّ ل لنا فً هذا الكتاب.
نطرح فً هذا الفصل فكرة المتغٌّرات التً تشبه خبلٌا الذاكرة فً دماغ اإلنسان فهً خبلٌا فً ذاكرة الحاسب
ٌستخدمها الحاسب لتخزٌن القٌم التً ٌحتاجها أثناء تنفٌذ البرنامج وسنناقش كٌفٌة التعامل معها أٌضا.
هذا الفصل هو بداٌتك لكً تكون قادرا على التواصل مع الحاسب بشكل مباشر حٌث ستتم ّكن من الطباعة على
الشاشة و القراءة من لوحة المفاتٌح وهذا هو التخاطب الذي نبحث عنه بٌن المبرمج والحاسب.
فً هذا الفصل سنشرح فكرة استخدام الثوابت و الفرق بٌنها و بٌن المتغٌّرات.
صة تقوم بوظابف من نقصد بها الرموز التً تعنً للحاسب عمل ٌّات معٌّنة إما رٌاض ٌّة أو منطق ٌّة أو عمل ٌّات خا ّ
أنواع أخرى والمعامبلت ضرور ٌّة ج ّدا وال ٌخلو برنامج منها أبدا لذلك ننصحك بالتم ّعن أثناء قراءتها و التمرّ ن
علٌها بشكل ج ٌّد.
صة تقوم بوظابف معٌنة منها ما ٌدعى ببنى الشرط و منها ما نق ّدم هنا أه ّم البنى البرمج ٌّة وهً تعلٌمات خا ّ
ٌدعى ببنى التكرار وهً أنواع نتع ّرف علٌها فً حٌنها ث ّم نشرح فٌه بعض الكلمات المستخدمة مع هذه البنى
لمساعدتنا فً إدارة برامجنا بشكل كامل.
بنى معطٌات تسهّل التعامل مع البٌانات التً لها نفس النوع كالبحث والترتٌب والتخزٌن
نناقش هنا كٌفٌة التعامل مع النصوص حٌث ٌت ّم تمثٌل الكلمات والنصوص بسبلسل من األحرف )الرموز(.
23
الفصل الحادي عشر :المؤ ّ
شرات
شرات من أقوى مٌزات لغة الـ C++حٌث تسمح لنا بالتعامل مع الذاكرة مباشرة وتم ّكننا من إنشاء تعتبر المإ ّ
شرات صعبة الفهم ولكنّ مفهومها بسٌط وٌصبح التعامل معها سهبل بنى معطٌات دٌنامٌكٌة .أحٌانا تكون المإ ّ
كلّما زاد التمرّ ن وكتابة األكواد المتعلقة بها.
هً بنى معطٌات خاصّة تسمح لنا بجمع ع ّدة أنواع من المعطٌات تحت نوع واحد وهً مهمّة فً قواعد البٌانات
نعرّ ف هنا أنواع بٌانات جدٌدة غٌر موجودة باالعتماد على أنواع موجودة ومعرّ فة مسبقا.
نتعلم هنا كٌفٌة التعامل مع المل ّفات سواء قراءة محتوٌاتها أو الكتابة علٌها أو البحث فٌها.
هذا الفصل هو عبارة عن إضافة جدٌدة إلى لغة C++نتع ّرف من خبلله على طرٌقة عمل ٌّة فً منع تدمٌر
البرنامج الناجم عن أخطاء مع ٌّنة فً العمل ٌّات داخل البرنامج كؤن ٌدخل المستخدم حرفا أو اسما بدال من أن
ٌدخل رقما .مثل هذه األخطاء قد تتسبب بتوقف البرنامج وتدمٌره لذلك سٌكون من األفضل التخلّص منها
بطرٌقة آمنة.
ٌعتبر هذا الفصل مدخبل إلى الصّفوف والكابنات وٌق ّدم بعض المفاهٌم التً تخصّ هذا النمط من البرمجة
صفوف )األنواع( الجدٌدة وأشٌاء أخرى تتعلّق بها.
وٌتح ّدث عن أسلوب بناء ال ّ
نتعرّ ض فً هذا الفصل إلى المبادئ الثبلث للبرمجة كابن ٌّة التوجّ ه ونشرحها بشكل سهل و مختصر ونق ّدم بعض
األمثلة علٌها فً محاولة لتقدٌم فكرة بسٌطة عن هذا النمط من البرمجة وال ٌعتبر هذا الكتاب كافٌا فً هذا
المجال.
أسلوب قويّ ج ّدا للتعامل مع الصفوف والتوابع واختصار الوقت والجهد األمر الذي ستتعرّ ف علٌه عندما تنهً
آخر صفحة من صفحات البرمجة الكابن ٌّة.
مكتبات قٌاس ٌّة موجودة فً لغة C++القٌاس ٌّة تحتوي على الكثٌر من المزاٌا و التوابع التً تو ّفر علٌك الوقت و
الجهد فهً تحوي المبات من التوابع الجاهزة والتً ستحتاجها فً ك ّل برامجك .سن ّتعلم بسرعة كٌف ٌمكننا أن
صة بنا.
نصنع فضاءات األسماء الخا ّ
24
التعامل مع المترجم visual c++ 6.0
نقوم بفتح البرنامج بعد تنصٌبه على الحاسب فتظهر النافذة التالٌة
نختار Newمن القائمة Fileث ّم نختار التبوٌب Filesث ّم نختار C++ Source Fileث ّم نحدد اسم الملف
ومكان الحفظ 9ث ّم نضغط الزر OK
9
أحٌانا ٌجب تغٌٌر مكان الحفظ عند العمل على Windows 7
25
) (compileأو ctrl+f7لترجمة الشٌفرة كما فً نكتب البرنامج فً المحرّ ر الذي ٌظهر ونضغط الزر
الشكل
26
القسم األول
27
الفصل األوّل :
لع ّل أفضل ما نبدأ به رحلتنا مع هذه اللغة هو البرنامج الشهٌر الذي ٌتم ّتع ببساطته إضافة الحتوابه على
المكوّ نات الربٌس ٌّة التً الب ّد منها فً كل برنامج ,ولٌس علٌك اآلن لكً تكون مبرمجا سوى أن تضع أناملك
الناعمة تلك على لوحة المفاتٌح .اآلن هل أنت مستع ّد لكتابة أوّ ل برنامج لك؟ إذن ه ٌّا بنا.
افتح المترجم واكتب فٌه النصّ الذي على ٌسار الشكل ث ّم اضغط على أزرار التشغٌل
تهانٌنا! كان هذا أوّ َل برنامج لنا فً ,C++واآلن دعنا نبدأ بشرح هذه العبارات
>#include <iostream
ّ
الجمل التً تبدأ بالرمز) (#هً عبارات تقوم بتوجٌه المترجم وال ٌت ّم تنفٌذها أثناء تنفٌذ الشٌفرة التً نكتبها لكنها
تعمل كدلٌل للمترجم ,ففً مثالنا الجملة > #include <iostreamتخبر المترجم بؤن ٌقوم بتضمٌن الملف
المصدري iostreamوهو ملف مع ّرف سابقا ٌحتوي على تصرٌحات للمكتبة القٌاسٌة الخاصة باإلدخال
واإلخراج فً لغة C++وقد استدعٌنا هذه المكتبة أل ّننا سنستخدمها الحقا فً برنامجنا ,وكؤننا نقول للمترجم:
"إننا سوف نستخدم التوابع المعرفة فً هذا الملف المصدري لذلك اذهب وأحضره" ,وسنؤتً على شرح ذلك
الحقا.
)(int main
ٌمثل هذا السطر بداٌة التصرٌح عن التابع الربٌسً .main
ب بلغة .C++وهذا الٌعتمد على كون هذا التابع مكتوبا إنّ التابع mainهو النقطة األولى لبداٌة أي برنامج مكتو ٍ
فً أوّ ل الشٌفرة أو فً وسطها أو فً آخرها فؤٌنما كان هذا التابع مكتوبا فإنّ التنفٌذ سٌبدأ منه أي أ ّنه ضروريّ
ج ّدا لٌعمل البرنامج ومن دونه ال ٌوجد برنامج.
فً التصرٌح عن التابع mainوضعنا القوسٌن ) ( بعد اسم التابع وذلك ألنّ الصٌغة العا ّمة للتصرٌح عن التوابع
تقضً بذلك كما سٌرد معنا فٌما بعد.
ك ّل التعلٌمات التً سٌقوم التابع mainبتنفٌذها محصورة بٌن القوسٌن} { كما هو مبٌن فً المثال السابق.
28
;"!cout << "Hello World
هذه التعٌلمة هً األكثر أهمٌة فً هذا البرنامج .تعتبر coutتعلٌمة قٌاسٌة فً C++وهً تقوم بطباعة الجملة
Hello Worldعلى الشاشة.
ومن الجٌد التنوٌه إلى أن التعلٌمة coutمعرّ فة فً الملف المصدري iostreamوقد قمنا بتضمٌنه فً بداٌة
برنامجنا كً نتمكن من استخدامها.
مالحظة :من المه ّم أن تعرف أنّ ك ّل تعلٌمة فً ٌ C++جب أن تنتهً بفاصلة منقوطة );(.
)من األخطاء الشابعة بٌن مبرمجً C++أ ّنهم ٌن َسون وضع الفاصلة المنقوطة فً نهاٌة بعض
التعلٌمات م ّما ٌُحدث خطؤ ٌمنع البرنامج من العمل ,فانتبه لذلك(.
;return 0
تقوم التعلٌمة returnبإنهاء التابع )( mainوتعٌد التعلٌمة التً تؤتً بعدها كقٌمة للتابع ,فً حالتنا هذه تعٌد .0
هذه هً الطرٌقة المعتادة إلنهاء البرنامج فعندما ٌعٌد التابع )( mainالقٌمة 0نعلم أنّ البرنامج انتهى دون أ ٌّة
أخطاء أثناء ال ّتنفٌذ.
ومن ث ّم البد أ ّنك قد الحظت أنّ كل سطر فً هذا البرنامج قام بعمله ,فالتعلٌق الذي بدأ بالرمز ) (//الذي وجّ ه
المترجم ألن ٌتجاهل هذا السطر ,وهناك السطر الذي بدأ بالرمز) (#الذي وجّ ه المترجم كً ٌجلب الملف
المصدري ,iostreamوكان هناك السطر الذي صرّ حنا به عن التابع )( ,mainوأخٌرا التعلٌمة coutالتً
صٌن بالتابع .main
وضعناها بٌن القوسٌن } { الخا ّ
تنسٌق الكتابة
ٌمكننا أن نكتب:
} ;int main () { cout << " Hello World "; return 0
ك ّل تعلٌمة فً C++تنتهً بالفاصلة المنقوطة كما ذكرنا .لذلك ال فرق فً أن تكتب ال ّتعلٌمات على سطر واحد
أو فً ع ّدة أسطر ,فطالما أ ّنك لم تضع فاصلة منقوطة فهذا ٌعنً أنّ ال ّتعلٌمة لم تنت ِه بعد.
لك ّننا كتبناه كما فً الجدول لكً تسهل قراءته.
وٌجب االنتباه إلى أنّ الموجِّ هات )األسطر التً تبدأ بـ ُّ (#
تشذ عن هذه القاعدة أل ّنها فً واقع األمر ال ّ
تمثل
تعلٌمات حقٌق ٌّة فهً أسطر ٌقرإها المترجم لك ّنها ال ّ
تمثل أيّ جزء من شٌفرة البرنامج ,فهذه األسطر ٌجب أن
تكتب فً مكانها الخاص فً أعلى البرنامج وهً ال تحتاج إلى فواصل منقوطة فً نهاٌاتها.
29
التعلٌقات
ال ّتعلٌق هو قطعة من الشٌفرة مهملة من قبل المترجم .إذن التعلٌقات ال تقوم بؤ ٌّة وظٌفة برمجٌة ,وإ ّنما هً
موجودة فقط لتذ ّكر المبرمج ببعض المبلحظات حول شٌفرته.
2:
الفصل الثاني:
إنّ الفابدة من برنامج hello worldالذي قمنا بإنشابه فً الدرس السابق هً أن نعرض نصّا ما على شاشة
الحاسب ,لكن هل البرمجة محدودة إلى هذه الدرجة؟
لنفترض أ ّننً طلبت منك أن تحتفظ بالرقم 4فً ذهنك ث ّم طلبت منك أن تحتفظ بالرقم ,1اآلن رجاء أضف 4
إلى الرقم األوّ ل ,ث ّم اجمع الرقم األوّ ل إلى الرقم الثانً وأعطنً الناتج.
ٌمكن أن نعبِّر برمجٌا عن ذلك كما ٌلً:
;a=4
;b=1
;a=a+3
; result = a + b
إنّ الحاسب ٌقوم بإجراء هذه العملٌات تماما كما تقوم أنت بها ,لكنه ٌتم ٌّز عنك بؤ ّنه قادر على االحتفاظ بآالف
قصٌر جدّا وهذا ٌت ّم من خبلل إدخال القٌم إلى الحاسب
ٍ القٌم وإجراء عشرات العملٌات الحسابٌة المع ّقدة فً وقت
وتخزٌنها فً أماكن مخصّصة فً الذاكرة ندعوها بالمتغٌّرات.
31
حساسٌة اللغة لحالة األحرف:
إنّ لغة C++ح ّساسة لحالة األحرف فعندما تكتب اسم المتغٌّر علٌك أن تراعً حالة ك ّل حرف من حروفه
واألمثلة التالٌة كفٌلة بشرح هذه الفكرة إن شاء هللا:
فً المثال السابق المتغٌّر ٌ aختلف تماما عن المتغٌّر ,Aوكذلك كل المتغٌّرات التالٌة مختلفة
أي أ ّنه لو قمنا بالتصرٌح عن متغٌّر ما باالسم aفلن ٌكون بمقدورنا أن نستدعٌه إال باالسم aولو استدعٌناه
باالسم Aفلن ٌعرفه المترجم أل ّنه سٌعتبره متغٌّرا َ
آخر وهو غٌر موجود.
نخزن ّ
كبل لكن هل لكل ّ المتغ ٌّرات نفس الحجم فً الذاكرة؟ لتوضٌح هذه المسؤلة لنفترض أ ّننا نرٌد أن ّ
من القٌم التالٌة 10و 45.123و .Hi Everybody
إنّ ذاكرة الحاسب مقسّمة إلى وحدات تدعى باٌتات .Bytesوالباٌت هو وحدة قٌاس الحجم الصغرى التً
سنتعامل معها .نستطٌع أن نخ ّزن فً الباٌت الواحد عددا صحٌحا بٌن 1و 366أو حرفا أو رمزا واحدا فقط.
واضح تماما أ ّننا لن نستخدم فقط األرقام من 1إلى ,366ولن ندخل حرفا واحدا فقط فنحن بحاجة ألكثر من
ذلك بكثٌر لذلك ٌو ّفر لنا الحاسب أنواعا أخرى أكثر تعقٌدا من النوعٌن السابقٌن وذلك بتجمٌع عدّة باٌتات إلى
بعضها لت ّتسع لحجم أكبر من البٌانات) .كما هو موضح فً الشكل(
32
نعرض فً الجدول التالً عدّ ة أنواع من البٌانات المستخدمة فً .C++
مالحظات المدى (ٌمثل القٌم التً ٌمكن للمتغ ٌّر أن ٌأخذها) الحجم بالباٌت نوع المتغ ٌّر
حرف واحد أو رقم طوله بإشارة ][-128,127 2 char
8بِت دون إشارة ][0,255
رقم صحٌح طوله 06 بإشارة ][-32768 , 32767 3 short
بِت دون إشارة ][0,65535
رقم صحٌح طوله 23 بإشارة ][-2147483648 , 2147483647 5 long
ِبت دون إشارة ][0,53:5:783:6
رقم صحٌح إما shortأو long 3أو 5 int
رقم عشري ) 8أرقام( إلى 5 float
رقم ذو دقة عشرٌة ) 26رقم( إلى 9 double
مضاعفة عن float
رقم ذو دقة عشرٌة ) 26رقم( إلى 21 long double
مضاعفة عن double
متغ ٌّر منطقً بإحدى trueأو false 2 bool
القٌمتٌن 1أو 0
واآلن لنعد إلى موضوعنا الذي ك ّنا بدأنا الحدٌث عنه سابقا.
; int a
; float mynumber
; long mysecondnumber = 5
كما تبلحظ بدأ التصرٌح عن المتغٌّر aبالنوع intأي أ ّننا نقول للمترجم" :إنّ المتغٌّر هو من نوع األعداد
الثانً .أمّا المثال ّ
الثالث فقد تابعنا الخطوات بؤن قمنا الصحٌحة intو اسمه ,"aوكذلك األمر فً المثال ّ
بتبدبته )أي إسناد قٌمة ابتدابٌة للمتغٌر أثناء التصرٌح عنه( على القٌمة .5
تم ّكننا C++من التصرٌح عن عدّة متغٌّرات من نفس النوع وتبدبتها إن أردنا فً سطر واحد.
مثال:
; int a, b = 3, c = 5
وهذا مكافا تماما لل ّشكل التالً:
; int a
; int b = 3
; int c = 5
33
لعلّك الحظت من الجدول أنّ األنواع ( )int , short , long, charتكون بإشارة أو بدون إشارة وهذا تابع
للمجال الذي نرغب بؤن ٌضمّه المتغٌّر ففً بعض الحاالت نكون واثقٌن بؤنّ القٌم التً سٌؤخذها متغٌّر عدديّ
هً من ال ّنوع الصّحٌح و الموجب فقط عندها قد ال نرغب بؤن ٌكون المتغٌّر معرّ فا لٌستقبل األعداد السالبة.
تستطٌع أن تح ّدد فٌما إذا كان المتغٌّر من األنواع األربعة السابقة ٌمتلك إشارة أو ال وذلك باستخدم إحدى
الكلمتٌن التالٌٌن:
فً الحالة األولى من المعروف أنّ عدد األبناء ال ٌمكن أن ٌكون أقل من الصفر فإمّا أن ٌكون هناك أبناء أو ال
ٌكون لذلك صرّ حنا عن NumberOfSonsعلى أ ّنه بدون إشارة سالبة.
أمّا فً الحالة الثانٌة فبل شًء ٌضمن عدم إدخال قٌمة سالبة على المتغٌّر MyAccountBalance
( داللة على الخسارة مث اال ) لذلك صرّ حنا عنه على أ ّنه من النوع signedالذي ٌستطٌع أن ٌحمل أرقاما سالبة.
وبشكل افتراضً إذا لم تحدد فٌما إذا كان المتغٌّر من النوع signedأو unsignedفإنّ المترجم سٌعتبره من
النوع signedلذلك ٌمكن التصرٌح عن المتغٌّر فً الحالة الثانٌة من المثال السابق بالشكل:
; Int MyAccountBalance
وهذا هو الشكل المعتاد لهذه الحالة.
مالحظة :إنّ الطرٌقة السابقة بتبدبة المتغٌّرات مؤخوذة من لغة ,Cوهذا ما ٌدعى ) ,(C-Likeلكنّ
C++تمتلك طرٌقة أخرى لفعل ذلك وهً :
; )data_type variable_Identifier (initial_value
; int a = 5 ; )int a (5 أي أنّ :
34
) strings ( مق ّدمة إلى السالسل
C++ توجد فً لغة. ٌعبّر عن سلسلة من الرموز المحفوظة فً حجرات متتالٌة من الذاكرةstring إنّ النوع
سنشرحها الحقا فً فصلC-style string وتدعىC األولى مؤخوذة من لغة,طرٌقتان للتعامل مع السبلسل
.STL ومكتبة القوالب القٌاسٌةstring ّسبلسل الرموز أمّا الطرٌقة الثانٌة فتعتمد على الصف
int main ()
{
string name;
cout<<"enter your name: ";
cin>>name;
cout << "Hello "<<name<<endl;
return 0;
}
ّ تقوم بنقل المإendl التعلٌمة
.شر إلى السطر التالً كما سنرى فٌما بعد
(<,>) ( والمقارنة+=) ( واإلضافة+) كالجمعstring ّهناك مجموعة من العمل ٌّات المعرّ فة فً الصف
:مثال
int main ()
{
string firstName,lastName,fullName;
cout<<"enter your first name: ";
cin>>firstName;
cout<<"enter your last name: ";
cin>>lastName;
fullName=firstName+" "+lastName;
cout<<"Hello "<<fullName<<endl;
if(firstName<lastName)
cout<<firstName<<endl;
return 0;
}
35
.2أجب عن األسبلة التالٌة :
هل المتغٌّر Numهو نفس المتغٌّر numفً C++؟
هل ٌجب أن ٌعطى المتغٌّر نوعا من البٌانات عند التصرٌح عنه ؟
هل ٌمكن أن تكون أسماء المتغٌّرات أي مجموعة من الرموز ؟
هل نستطٌع أن نعرّ ف متغٌّرا ونعطٌه قٌمة فً نفس اللحظة ؟
ما الفرق بٌن المتغٌّرات signedو . unsigned
.3امؤل الفراغات التالٌة :
المتغ ٌّرات هً ______ فً ذاكرة الحاسب ______فٌها البٌانات ,وٌت ّم الوصول إلٌها من خبلل
______المتغٌّر الذي ______عن باقً المتغٌّرات فً ______.
>#include <iostream
;using namespace std
)( int main
{
; float a = 1 , b = 0
;unsigned int result
;a = a - 6
;result = A + b
;cout << result
}
36
الفصل الثالث :
تو ّفر المكتبة iostreamالتعلٌمتٌن cinو coutحٌث ت ّم تصمٌ ُم ُه َما من أجل التخاطب بٌن المستخدم والحاسب,
وذلك أنّ العمل ٌّة coutتقوم بالطباعة على الشاشة بٌنما تقوم العملٌة cinبإدخال القٌم التً ٌحتاجها البرنامج من
لوحة المفاتٌح.
تعمل هذه التعلٌمة على إخراج قٌم المتغٌّرات والثوابت التً تؤتً مباشرة بعد معامل الحشر >> ,ولها الشكل
التالً:
-0التعلٌمة األولى :تطبع هذه التعلٌمة العبارة Islam is a way of lifeالمحصورة بٌن عبلمتً
التنصٌص " " على شاشة الخرج( .عندما نرغب بطباعة نص ما فعلٌنا أن نضعه بٌن قوسً التنصٌص وكذلك األمر عند
إسناد نص إلى متغٌّر نصً لذلك فالعبارتٌن اآلتٌتٌن مختلفتٌن تماماا).
; " cout<< "The peace upon you, " << "I am " << "a C++ sentence.
; cout<<"I am "<< age << " years old and my zipcode is "<< zipcode
37
عندها فإنّ ناتج التعلٌمة42296 ٌحمل القٌمةzipcode والمتغٌّر32 ً هage لو افترضنا أن قٌمة المتغٌّر
:السابقة سٌكون
I am 20 years old and my zipcode is 60094
\) فهً تطبع على سطرnew line( \n ال تقوم بإضافة رمز انتهاء السطرcout ٌجب أن تعلم أنّ التعلٌمة
لتوضٌح هذه. لذلك عندما ترغب فً الطباعة على سطر جدٌد فعلٌك أن تضٌف هذا الرّ مز بنفسك.واحد
:المسؤلة
Go forward young Muslims, wherever you are In the shadow of the sun or by the light of a star
والحل ٌكمن كما قلنا,وهذا ما ال نرٌده فالعبارتان على سطر واحد بٌنما نرٌد أن تكون كل واحدة على سطر
:\ فً نهاٌة التعلٌمة األولى لتصبح بالشكلn للتوّ بإضافة الرمز
#include<iostream>
using namespace std;
int main()
{
/* **** 1 **** */
cout<< "Welcome to you\n";
cout<<"C++ You are elegant"<< endl;
/* **** 2 **** */
cout<< "Welcome to you "<< endl;
cout<<"C++ You are elegant\n";
/* **** 3 **** */
cout<< "Welcome to you\nC++ You are elegant"<< endl;
/* **** 4 **** */
cout<< "Welcome to you"<< endl <<"C++ You are elegant\n";
/* … */
return 0;
}
Welcome to you
C++ You are elegant
38
تعلٌمة اإلدخال )input (cin
تستخدم هذه التعلٌمة إلدخال القٌم المطلوبة من لوحة المفاتٌح ,ونستخدم لذلك معامبل ٌدعى معامل اإلدخال <<
ث ّم نتبعه باسم المتغٌّر الذي نرغب بإعطابه القٌمة المقروءة من لوحة المفاتٌح ,وذلك كما ٌلً:
; int age
; cin>> age
مثال:
>#include <iostream
;using namespace std
)( int main
{
;int i
;" cout << "Please enter an integer value:
;cin >> i
;cout << "The value you entered is " << i
;"cout << " and its double is " << i*2 << ".\n
;return 0
}
Please enter an integer value: 702
The value you entered is 702 and its double is 1404.
مالحظة :2قد ٌكون المستخدم أحد أه ّم العوامل التً تسبب فشل برنامجك ففً المثال السابق طلبنا
من المستخدم أن ٌدخل رقما صحٌحا ,ولكن ماذا لو أدخل المستخدم اسمه؟
بالطبع لن تكون مسرورا لذلك.
طبعاً ٌىاك حل لمثل ٌذي المشامل َلنىّىا له وتحذث عىً ٌىا َإو ّما أردوا التىبيً لمثل
ٌذي المشامل حتّ تضعٍا في حسباول.
39
.2مالذي تطبعه التعلٌمة التالٌة:
; " *****cout<<"*\n**\n***\n****\n
.3اكتب برنامج ٌقرأ درجة الحرارة بالسٌلٌسوس ) ,(cث ّم ٌحولها إلى الفهرانهاٌت وفق العبلقة
.2اكتب برنامج ٌقرأ درجة الحرارة بالفهرانهاٌت ) ,(fث ّم ٌحولها إلى مبوٌة وفق العبلقة
–
.6اكتب برنامجا ٌقرأ تسارع جسم ما aو الزمن tالذي استغرقه فً الحركة ث ّم ٌحسب:
المسافة المقطوعة
و السرعة النهابٌة
.5اكتب برنامجا ٌحسب قٌمة التابع التالً
3:
الفصل الرابع :
فً كثٌر من األحٌان نحتاج إلى أرقام أو نصوص ثابتة الستخدامها فً برامجنا .قد ال ٌكون ذلك واضحا فً
البرامج العادٌة أو البسٌطة لك ّنه ٌ ّتضح فً البرامج الكبٌرة التً تتعامل مع الدوا ّل الرٌاضٌّة والرسوم وغٌرها.
ولنؤخذ كمثال الرقم المعروف 𝜋 الذي كثٌرا ما ٌُستخدم فً الحسابات الرٌاضٌة .نعلم أ ّنه كلّما زادت د ّقة األرقام
العشرٌّة زادت د ّقة الحسابات ,ولنفترض أ ّننا سنستخدم الرقم 𝜋 فً برنامجنا عدّة مرّ ات فهل سنكون مضطرّ ٌن
لكتابة هذا الرّ قم عدّة مرّ ات .إنّ هذه الطرٌقة تعنً زٌادة احتمال وقوع أخطاء فقد نخطا بكتابة الرّ قم ممّا ٌعنً
خطؤ حسابٌا قد ٌتسبب بكارثة كبٌرة فً البرامج الهندسٌّة أو اإلنشابٌّة لذلك وفرّ ت لغات البرمجة ما ٌسمّى
بالثوابت فؤنت تصرح عن الثابت وتعطٌه القٌمة التً سٌؤخذها والتً ال ٌمكن أن تتغٌر طوال فترة التنفٌذ ث ّم
تقوم باستدعاء الثابت فً كل مرّة تو ّد استخدامه فٌها.
األولى :const
الثانٌة :#define
#define pi 3.14159265
فً هذه الحالة نستخدم التعلٌمة #defineث ّم نذكر اسم الثابت ث ّم القٌمة التً سٌؤخذها .انتبه :فً هذه الطرٌقة ال
ٌوجد فاصلة منقوطة فً نهاٌة التعلٌمة.
لعلّك الحظت أ ّننا لم نقم بتحدٌد نوع الثابت فً الحالة الثانٌة كما فعلنا فً الحالة األولى.
41
الفصل اخلامس :
تعرّ فنا فً الدرس السابق على المتغٌّرات والثوابت وقلنا" :إنّ المتغٌّرات هً األماكن التً ّ
ٌخزن الحاسب فٌها
البٌانات وهً مستعدّة لتغٌٌر قٌمتها أثناء تنفٌذ البرنامج ,بٌنما الثوابت فهً أماكن فً الذاكرة تحتفظ بقٌمة وحٌدة
ال ٌمكن تغٌٌرها طوال فترة تشغٌل البرنامج" ,وتعرّ فنا أٌضا على كٌفٌة ال ّتصرٌح عن ك ّل منهما ,ولكن كٌف
ٌمكننا التحكم بالقٌم التً تحتفظ بها المتغ ٌّرات؟
مثل فً هذه اللغة بمجموعة من الكلمات المفتاحٌة المحجوزة من أجل هذا تزوّ دنا C++بالمعامبلت .والتً ُت َّ
والرموز الخاصة وهذه المعامبلت تعتبر من أساس ٌّات اللغة لذلك الب ّد لك عزٌزي القارئ من التعرف علٌها و
التعامل معها بشكل جٌد.
.1اإلسناد (=)
ٌقبله(كأن نضع رقم صحٌح فً متغٌّر من النوع العشري مثالا) نستخدم معامل اإلسناد = كً نعطً المتغٌّر قٌمة من نوع
; float a = 3
أسند العدد الصحٌح 4إلى المتغٌّرالعشري ٌ .aقوم معامل اإلسناد بإسناد القٌمة على ٌمٌنه إلى المتغٌّر الذي على
ٌساره حٌث أنّ القٌمة على الٌمٌن ٌمكن أن تكون متغٌّرا أو عددا ثابتا أو نتٌجة لعدد من العملٌات على قٌم
موافقة لنوع المتغٌّر على ٌسارمعامل اإلسناد .واإلسناد المعاكس لٌس ممكنا.
أمثلة:
أسند القٌمة 6إلى المتغٌّر bث ّم أسند المجموع ) (2 + bإلى المتغٌّر .a
; a = b = c = 5 ; //1( c =5 ; 2( b = c ; : c = 5 3) a = b ; : b = 5
أسند القٌمة 6إلى المتغٌّرات الثبلثة a , b , c
الوظٌفة العملٌة
ٌقوم بجمع القٌمتٌن على طرفٌه + Addition
ٌقوم بطرح القٌمتٌن على طرفٌه subtractionــ
ٌقوم بضرب القٌمتٌن على طرفٌه * multiplication
ٌقوم تقسٌم القٌمة التً علً ٌساره على القٌمة التً التً على ٌمٌنه / division
ٌعٌد باقً قسمة القٌمة على ٌمٌنه على القٌمة على ٌساره % module
42
.3معامالت اإلسناد المركبة (=| )+=, -=, *=, /=, %=, &=, ^=,
مالحظة:
ٌمكن استخدام هذٌن المعاملٌن بطرٌقتٌن مختلفتٌن و المثال التالً ٌبٌن ذلك:
طبعا نستطٌع استخدام متغٌّرات أو تعابٌر للمقارنة بٌنها عوضا عن استخدام أرقام ثابتة فقط.
لنفترض أنّ لدٌنا
a = 2, b = 3, c = 6
تعٌد false ) ( a == 5
تعٌد true ) ( a * b >= c
تعٌد false )(b+4>a*c
تعٌد true ) ( ( b = 2 ) == a
43
كن حذراا :استخدام المعامل = مرّ ة واحدة فقط ٌعنً اإلسناد أمّا استخدامه مرّ تٌن == فٌعنً المقارنة والسطر
الرابع من المثال السابق ٌوضح ذلك.
فً العدٌد من المترجمات كما فً لغة Cمثبل تعٌد المعامبلت المنطقٌّة قٌما عددٌّة صحٌحة حٌث تعٌد القٌمة 1
بدال من falseوتعٌد قٌما مختلفة عن 1بدال من ( trueفً الحالة العامة تعٌد القٌمة .)0
&& ّ
ٌمثل معامل الربط المنطقً ) َو ( and
|| ّ
ٌمثل معامل الربط المنطقً ) أو ( or
مثال ))((a ) && ( b)) , (( a) || ( b a || b a && b b a
)) (( 5 == 5 ) && ( 3 < 6 )), (( 5 == 5 ) || ( 3 < 6 true true true true
)) (( 5 == 5 ) && ( 3 > 6 )), (( 5 == 5 ) || ( 3 > 6 true false false true
)) (( 5 != 5 ) && ( 3 < 6 )), (( 5 != 5 ) || ( 3 < 6 true false true false
)) (( 5 != 5 ) && ( 3 > 6 )), (( 5 != 5 ) || ( 3 > 6 false false false false
أي :إذا كان الشرط محققا ا فإنّ المعامل سٌعٌد النتٌجة األولى و ّإال سٌعٌد النتٌجة الثانٌة.
مثال:
;a = 7, b = 3
; (a == b) ? return 1 : 2
سٌعٌد العدد 3ألن الشرط غٌر محقق ) 7ال تساوي .(2
44
.8معامل تحوٌل البٌانات
ٌسمح لك هذا المعامل بتحوٌل متغٌّر من نوع إلى آخر وهناك عدّة طرق لفعل ذلك واألكثر شهرة منها هو
المعامل التالً )type( :أو )type (value
مثال:
; Int i
; float pi = 3.14
i = (int)pi ; // pi = 3.14 , i = 3
السطر الثالث من المثال السابق ٌقوم بتحوٌل قٌمة المتغٌّر العشري إلى عدد صحٌح ,و ٌمكن أن ٌكتب بالشكل:
; )i = int(pi
.9المعامل )(sizeof
ٌقبل هذا المعامل وسٌطا واحدا إ ّما أن ٌكون نوعا من أنواع البٌانات المؤلوفة أو متغٌّرا بح ّد ذاته ,وهو ٌعٌد حجم
الوسٌط بالباٌت.وله الشكل:
; )int a = sizeof(char
سٌعٌد هذا المعامل القٌمة 2ألن النوع ٌ charؤخذ 2باٌت فً الذاكرة كما فً الجدول فً الدرس السابق.
;a=5+8%2
ما هً نتٌجة هذا التعبٌر برأٌك؟ طبعا جوابك هو 7ولكن لماذا؟
45
مثال:
46
: ما هً قٌمة العبارات التالٌة.2
int a = 0 ;
long b = 1, c = 2, d = 3 ;
bool e = true , r = true , t = false ;
a) a += (b = c = d - 5) ;
b) d %= 2 * c / ++b ;
c) a = d – ( b += ( c * ( 1 – a ) ) ) ;
d) e = !e ;
e) r = e || t ;
f) t = e && r ;
g) e = !( (e && r ) || (e && t ) ) ;
: فً كل مرةx حدد أولوٌات العملٌات فً التعابٌر التالٌة ث ّم أوجد قٌمة.3
a) x = 7 + 3 * 6 / 2 – 1 ;
b) x = 2 % 2 + 2 * 2 – 2 / 2 ;
c) x = ( 3 * 9 * ( 3 + ( 9 * 3 / ( 3 ) ) ) ) ;
d) c = 2*b – 3/d + a++;
47
الفصل السادس :
إنّ البرنامج لٌس عبارة عن مجموعة من تعلٌمات اإلسناد أو المقارنات أو اإلدخال واإلخراج التً تعلّمناها ح ّتى
اآلن ,فنحن وكما تعلم نتحدّث عن البرمجة التً إ ّنما نستخدمها كً تساعدنا فً حل مشاكلنا الٌومٌة ومن األشٌاء
المهمّة التً نحتاج إلٌها هً اتخاذ القرارت المناسبة إلجراء عملٌات مع ٌّنة دون أخرى .توفّر C++مجموعة
بُنى برمجٌة نسمٌها بنى التحكم ,و البنٌة البرمجٌة هً عبارة عن مجموعة من التعلٌمات ٌفصل بٌن كل
تعلٌمتٌن متتالٌتٌن فٌها فاصلة منقوطة ,وتكون هذه المجموعة محصورة بٌن قوسً البنٌة } { .معظم البنى التً
سنتعرّ ف علٌها اآلن تحتاج إلى عبارة عا ّمة كوسٌط ٌت ّم تمرٌره إلٌها .فً حال كانت البنٌة تحوي تعلٌمة واحدة
فقط فإ ّنها ال تحتاج إلى القوسٌن } { أ ّما إذا كانت البنٌة تحوي أكثر من تعلٌمة فإ ّنها تحتاج إلٌهما.
) if ( condition
تعلٌمة واحدة فقط statement ; //
أٚ
) if ( condition
{
أكثر من تعلٌمة statements… //
}
حٌث أنّ التعلٌمات التً داخل هذه البنٌة ال ٌت ّم تنفٌذها ّإال إذا كان الشرط الذي بٌن القوسٌن )(condition
مح ّققا.
مثال :نرٌد من المستخدم أن ٌدخل رقما ما
فإذا كان (الرقم ٌساوي )011عندها سنطبع العبارة" x is 100 " :
) if ( x == 100
; " cout << " x is 100
فً هذا المثال لدٌنا تعلٌمة واحدة فقط لذلك لم نستخدم القوسٌن }{ ,و لو أردنا أن نضٌف تعلٌمات أخرى إلى
هذه البنٌة عندها ٌجب أن نستخدم القوسٌن }{ أي:
) if ( x == 100
{
; " cout << " x is
; cout << x
… statements
}
48
هناك نوع آخر من الشرط نستخدمه فً حٌاتنا فكثٌرا ما نقول ":إذا حصل هذا الشًء عندها سؤفعل هذه األشٌاء
و إال سؤفعل أشٌاء أخرى ".
) if ( x == 100
; statement1
else
; statement2
)if (x == 100
;"cout << "x is 100
else
;"cout << "x is not 100
الٌزال هناك حالة أخٌرة للشرط وسنحتاجها بكثرة أٌضا وهً من الشكل:
)if (condition 1 ( شرط ) 0عندها ِافعل األشٌاء1 إذا كان
{ و إال إذا كان ( شرط ) 2عندها ِافعل األشٌاء2
; statements 1 .
} .
)else if (condition 2 .
; statement 2 وإال ِافعل األشٌاءn
.
.
else
;statement n
مثال:
)if (x > 0
;"cout << "x is positive
)else if (x < 0
;"cout << "x is negative
else
;"cout << "x is 0
49
)2بنى التكرار loops or repetition structures
ٌ
شرط ما( أثناء كتابة برامجنا قد نحتاج إلى تكرار مجموعة من التعلٌمات )عددا من المرات أو ح ّتى ٌتح ّقق
فعندما ترٌد أن تطبع األرقام من 12إلى 1تنازل ٌّا فما الذي ستصنعه هل ستكتب 12مرّ ات التعلٌمة cout
لتخرج كل مرّة رقما أق ّل من سابقه ماذا لو أردت طباعة 1222رقم أو أكثر .إنّ استخدام البنى التكرارٌة
سٌسهّل هذا األمر كثٌرا .هناك ثبلثة أشكال من البنى التكرارٌة سنتعرف علٌها تباعا وهً:
while ( condition ) statements البنٌة األولى :مادام ) الشرط محققا ا ( نفذ التعلٌمات التالٌة
البرنامج التالً ٌستخدم هذه الحلقة لطباعة األرقام من 12إلى 1تنازل ٌّا كما هو موضح:
// custom countdown using while !10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE
>#include <iostream
;using namespace std
)( int main
{
; int n = 10
)while (n>0
{
;" cout<< n << ",
;n--
}
;"!cout<< "FIRE
;return 0
}
بدأ البرنامج من التابع )( ,mainث ّم صرّ حنا عن المتغٌّر nالذي حمل القٌمة ,12ث ّم استخدمنا البنٌة while
التً تفحص الشرط n > 0أوالا
فإذا كان الشرط محققا فإ ّنها تقوم بما ٌلً:
-1تطبع العدد .n
-3تنقص العدد nبمقدار .1
-2نهاٌة البنٌة ث ّم العودة للتح ّقق من الشرط مرّ ة أخرى فإذا كان مح ّققا عادت إلى الخطوة .1
و إال سٌنتقل المترجم إلى التعلٌمات التً تقع بعد هذه البنٌة وهً طباعة العبارة !.FIRE
ث ّم نهاٌة البرنامج.
4:
بدأ البرنامج من التابع )( ,mainث ّم صرّ حنا عن المتغٌّر nالذي حمل القٌمة ,12ث ّم استخدمنا البنٌة doالتً
تنفذ التعلٌمات أوالا وهً تقوم باآلتً:
.1تطبع العدد .n
.3تنقص العدد nبمقدار .1
.2نهاٌة البنٌة ث ّم التحقق من الشرط
ّ ّ
محققا فإنها تعود إلى الخطوة .1 فإذا كان الشرط
سٌنتقل المترجم إلى خارج هذه البنٌة وٌطبع عبارة !.FIRE و إال
ث ّم نهاٌة البرنامج.
تنبٌهات حول البنٌتٌن السابقتٌن
ٌ -1جب أن تضع شرطا قاببل للتحقق كً تضمن انتهاء الحلقة )البنٌة( التكرارٌة ألنّ عدم تحقق الشرط ٌعنً
الدخول فً حلقة ال نهابٌة وبالتالً لن ٌتوقف البرنامج عن العمل.
فمثبل لو وضعنا ; n++بدال من ; n--فً أحد المثالٌن السابقٌن فإنّ الحلقة لن تنتهً أبدا.
-3هاتان البنٌتان ال تمتلكان عدّادات زٌادة أو نقصان فً داخلهما لذلك فهما تقببلن الشروط المنطقٌة و
العددٌة وٌجب علٌك أن تجد طرٌقة تستطٌع من خبللها أن تعرف فٌما إذا تحقّق الشرط )المنطقً أو العددي(
أوّ ال ,فً المثال السابق استخدمنا المتغٌّر nلهذه المهمة الذي أخذ ٌتناقص مع كل تكرار ح ّتى تحقق شرط
. التوقف
ّ ّ ا
-2البنٌة whileتقوم باختبار الشرط ّأوال ث ّم تنفذ التعلٌمات التً بداخلها لو كان الشرط محققا .أي أنه قد
محقق .بٌنما تعمل البنٌة doبعكس ٍ غٌر
َ ال ٌت ّم تنفٌذ تعلٌمات هذه البنٌة وال مرّ ة فً حال كان الشرط
مر اة أولى ث ّم تتح ّقق من الشرط فإذا تح ّقق أعادت تكرار العملٌات التً أختها فهً تن ّفذ تعلٌمات بنٌتها ّ
بداخلها و إال خرجت من البنٌة و تابعت البرنامج.
البنٌة الثالثة:
)for (initialization ; condition ; increase
;statement
تتمتع هذه البنٌة بشهرة كبٌرة ألنها من أسهل و أكثر الحلقات التكرارٌة استخداما ,فهً تعمل على تكرار
التعلٌمات التً بداخلها ابتداء من قٌمة مع ٌّنة وح ّتى قٌمة االنتهاء التً ٌجب أن تكون محدّدة ,وهً تحتوي على
عدّاد بداخلها ٌستطٌع المبرمج أن ٌتح ّكم بمقدار زٌادته أو نقصانه.
البرنامج التالً ٌستخدم هذه الحلقة لطباعة األرقام من 12إلى 1تنازل ٌّا كما هو موضح:
// custom countdown using for !10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE
>#include <iostream
;using namespace std
)( int main
{
) for ( int n=10 ; n>0 ; n--
{
;" cout << n << ",
}
;"!cout << "Fire
;return 0
}
51
ٌمكن أن تض ّم هذه الحلقة عدّادٌن بنفس الوقت فتؤخ َذ الشكل التالً:
Initialization
Condition
( for n=0 , i=100 ; n!=i ; n++ , i-- )
Increase
{
// whatever here...
}
ْ
الحلقة ستتوقف تبدأ هذه الحلقة بالقٌم االبتدابٌة التالٌة n = 0و i = 100وتستمرّ مادام n != iأي أنّ
بعد 52تكرارا ألنّ i = n = 50
); ;(for حلقة ال نهابٌة ٌمكن الخروج منها باستخدام التعلٌمة ; // break
ٌمكن أن نستخدم الحالة األخٌرة عندما ال نستطٌع أن نعرف قٌمة التوقف أو عندما نرغب باستخدام شرط
منطقً بدال من العدّاد كما فً المثال التالً:
مثال:
البرنامج التالً ٌقوم بقراءة رقم من لوحة المفاتٌح وطباعته على الشاشة وٌكرّ ر هذه العملٌة حتى ٌدخل
المستخدم الرقم 2
52
// number echoer Enter number (0 to end): 5
#include <iostream> You entered: 5
using namespace std; Enter number (0 to end): 0
int main () You entered: 0
{
unsigned long n;
do
{
cout << "Enter number (0 to end): ";
cin >> n;
cout << "You entered: " << n<< "\n";
} while (n != 0);
return 0;
}
تستخدم هذه التعلٌمة للخروج من البنٌة التً ُكتِبت فٌها كما فً الحالة الثالثة من:break ) التعلٌمة3
(n == 0) فنحن نرٌد أن نخرج من الحلقة)البنٌة(التكرارٌة بمجرّ د أن ٌتح ّقق الشرط,المثال السابق
ً تستخدم هذه التعلٌمة عندما نرغب بؤن ٌتجاهل البرنامج التعلٌمات التً تل:continue ) التعلٌمة4
. والعودة إلى بداٌة البنٌة البرمجٌة التً كتبت فٌها هذه التعلٌمةcontinue التعلٌمة
:ً باستخدام هذه التعلٌمة فسنكتب اآلت5 ماعدا الرقم12 و1 فلو أردنا أن نكتب برنامجا ٌطبع األعداد بٌن
#include <iostream> 10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE!
using namespace std;
int main()
{
for (int n=10; n>0;n--)
{
if (n==5)
continue;
cout << n << ", ";
}
cout << "FIRE!\n";
return 0;
}
53
البداٌة من التابع )(ٌ .mainدخل المترجم الحلقة التكرارٌة وعندها تكون قٌمة العدّاد n = 12ث ّم ٌختبر
الشرط ) (n == 5وبالطبع لن ٌكون الشرط مح ّققا ألنّ 10 != 5وعندها ٌتجاهل التعلٌمة الموجودة داخل
بنٌة الشرط ifث ّم ٌنتقل إلى التعلٌمة التالٌة وهً تعلٌمة طباعة العدد nوبعدها تنتهً الحلقة للمرّ ة األولى
فٌعود المترجم إلى معامل النقصان فً الحلقة وٌغٌر قٌمة العداد nبحسب قٌمة النقصان المطلوبة )فً حالتنا (1ث ّم
ٌختبر الشرط n>0فإن كان محققا فسٌعود إلى داخل الحلقة مرّ ة أخرى وٌستمر فً هذه العملٌات حتى تصبح
قٌمة n = 5عندها سٌختبرالشرط n == 5والذي أصبح محققا لذلك سٌن ّفذ التعلٌمة الموجودة داخل تعلٌمة
الشرط وهً التعلٌمة continueوالتً ستجبر المترجم على تجاهل التعلٌمات التً تلٌها مما ٌعنً تجاهل
التعلٌمة ;" cout << n << ",والعودة إلى بداٌة الحلقة إلنقاص الع ّداد واختبار الشرط ث ّم الدخول فً
الحلقة من جدٌد وهكذا حتى نهاٌة الحلقة.
)5التعلٌمة :gotoبهذه التعلٌمة تستطٌع إجبار المترجم على القفز من السطر الذي هو فٌه إلى السطر
الذي ترٌده لٌكمل التنفٌذ من المكان الذي أرسلته إلٌه .الستخدام هذه التعلٌمة نحتاج إلى الفتة label
الستعمالها كدلٌل على السطر الذي سنرسل المترجم إلٌه ,وهذه البلفتة ٌجب أن تتبع بالنقطتٌن ) .( :
مثال:
// goto loop example !10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE
>#include <iostream
;using namespace std
)( int main
{
;int n=10
loop:// goto label
;" cout << n << ",
;n--
)if (n>0
;goto loop
;"cout << "FIRE!\n
;return 0
}
فً المثال السابق استطعنا أن نطبع األعداد من 12إلى 1دون استخدام حلقات تكرارٌة وذلك باستخدام .goto
كالمعتاد بدأ البرنامج من التابع )( ,mainث ّم صرّ حنا عن المتغٌّر nالذي أخذ القٌمة 12ث ّم بعد ذلك صرّ حنا
عن البلفتة loop:وبعدها طبعنا قٌمة nث ّم أنقصناها بمقدار 1بعد ذلك وضعنا شرطا لنعرف إذا ما كانت
n>0أو ال فإذا كانت n > 0عندها سنعٌد المترجم إلى السطر الذي ٌحوي البلفتة loop:لٌعٌد العملٌات
السابقة كلّها حتى تصبح n = 0عندها لن ٌرجع المترجم إلى البلفتة وسٌكمل البرنامج لٌطبع العبارة
! FIREث ّم ٌنتهً البرنامج.
)6التعلٌمة :switchتشبه هذه التعلٌمة فً وظٌفتها التعلٌمة ifفهً تختبر قٌمة المتغٌّر الذي ٌت ّم
تمرٌره لها كوسٌط ث ّم تحدد العمل الذي ستقوم به من خبلل قٌمة المتغٌّر.
ولها الشكل التالً:
)switch(variable
{
case value1:
;statements
;break
…//other cases here
default: //optional
;statements
;break
}
54
. نرٌد برنامجا ٌخبر المستخدم عن الٌوم الذي ٌقابل الرقم الذي أدخله المستخدم:مثال
ّ
(7 - 1 ونخزنه فً متغٌّر عددي صحٌح و موجب)ألن األرقام هً بٌن أوال ٌجب أن نقرأ الرقم
... وهكذاFriday ٌقابل ٌوم الجمعة1 ثانٌا سنختبر قٌمة المتغٌّر ث ّم نقابله بالنصّ المناسب فالرقم
.ثالثا سنطبع اسم الٌوم المناسب على شاشة الخرج
// switch // if
#include<iostream> #include<iostream>
using namespace std; using namespace std;
int main() int main()
{ unsigned short dnum ; {
cout<< "Enter number of day(1-7): "; unsigned short dnum ;
cin>> dnum; cout<< "Enter number of day(1-7): ";
cout<< "\n"; cin>> dnum;
switch(dnum){ cout<< "\n";
case 1: // if dnum = 1 if(dnum == 1)
cout << "the day is Friday"; cout << "the day is Friday";
break; else if(dnum == 2)
case 2: // if dnum = 2 cout << "the day is Saturday";
cout << "the day is Saturday"; else if(dnum == 3)
break; cout << "the day is Sunday";
case 3: // if dnum = 3 else if(dnum == 4)
cout << "the day is Sunday"; cout << "the day is Monday";
break; else if(dnum == 5)
case 4: // if dnum = 4 cout << "the day is Tuesday";
cout << "the day is Monday"; else if(dnum == 6)
break; cout << "the day is Tuesday";
case 5: // if dnum = 5 else if(dnum == 7)
cout << "the day is Tuesday"; cout << "the day is Thursday";
break; else
case 6: // if dnum = 6 cout << "Sorry we're closed ";
cout << "the day is Wednesday"; cout<<'\n';
break; return 0;
case 7: // if dnum = 7 }
cout << "the day is Thursday";
break;
default: // if dnum < 1 or dnum> 7
cout << "Sorry we're closed ";
break;
}
cout<< "\n";
return 0;
}
55
لنشرح ما حصل فً التعلٌمة switch
وخز ّناه فً
ّ كما عوّ دتنا c++بدأ البرنامج من التابع )( mainث ّم صرّحنا عن المتغٌّر ,dnumث ّم قرأنا الرقم
المتغٌّر ,dnumواآلن جاء دور التعلٌمة switchالتً أخذت المتغٌّر dnumوسٌطا .بعد ذلك قمنا بذكر
الحاالت التً ٌمكن للمتغٌّر أن ٌحملها وهً األرقام } {1,2,..,7وذكرنا كل عنصر منها لوحده بعد الكلمة
caseث ّم وضعنا التعلٌمة التً تناسب كل حالة على حدة وفً نهاٌة كل حالة كتبنا التعلٌمة breakالتً
شرحناها سابقا والتً لها أهمٌّة كبٌرة فً التعلٌمة switchفعندما ٌقارن المترجم قٌمة المتغٌّر الوسٌط مع
الحالة األولى و تكون القٌمتٌن متساوٌتٌن عندها سٌنفذ التعلٌمات الخاصة بهذه الحالة وعندما سٌنتهً منها نرٌد
وأال ٌختبر باقً الحاالت لذلك وضعنا التعلٌمة breakولو لم نضعها منه أن ٌخرج من التعلٌمة ّ switch
الخبتر المترجم كل الحاالت الباقٌة وهذا ٌعنً مضٌعة للوقت وبطؤ للبرنامج ال نرٌده أن ٌحصل طبعا .أمّا
التعلٌمة defaultفهً تخصّ باقً االحتماالت الممكنة إذ قد ٌدخل المستخدم رقما غٌر األرقام المذكورة
لذلك نرٌد من البرنامج أن ٌخبر المستخدم أ ّنه أدخل رقما خاطبا .جرّ ب البرنامجٌن ,وستجد أن لهما نفس الناتج
تماما كما فً الشكل:
Enter number of day: 5
the day is Tuesday
باستخدام إحدى البنى التكرارٌة أو باستخدام التعلٌمة gotoعدّل البرنامج السابق لٌكرّ ر اإلدخال ح ّتى ٌدخل
المستخدم رقما من خارج المجال 1إلى 7حٌث ٌخرج من البرنامج.
56
الحلقات المتداخلة :nested loopsقلنا عند الحدٌث عن البنى التكرارٌة" :إ ّنها تم ّكننا من )7
تكرار مجموعة من التعلٌمات عددا من المرّ ات" .أي أ ّنه ٌمكننا أن نطبع الشكل التالً باستخدام حلقة
تكرارٌة كما بٌّنا من قبل:
1 2 3 4 5
لكن ماذا لو أردنا أن نطبع الشكل التالً و الذي ٌمثل عناصر مصفوفة ثنابٌة األبعاد.
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
ٌمكن فهم هذا الشكل على أ ّنه طباعة األعداد من 1إلى 5ثبلث مرّ ات متتالٌة على ثبلثة أسطر متتالٌة أٌضا أي
أ ّننا سنقوم بتكرار عمل الحلقة السابقة ثبلث مرّات كما فً الشكل التالً:
// nested loop 1 2 3 4 5
>#include <iostream 1 2 3 4 5
;using namespace std 1 2 3 4 5
)( int main
{
{)for( int i = 1 ; i<=3 ; i++
)for(int j = 1 ; j<=5 ; j++
;" " << cout << j
;"cout<<"\n
}
;return 0
}
تبدأ الحلقة األولى عندما i = 1وبما أنّ 1<3سٌ ّتجه المترجم إلى داخل الحلقة األولى لٌن ّفذ ما فٌها من
تعلٌمات فٌجد أنّ أول تعلٌمة أما َمه هً الحلقة الثانٌة التً تبدأ من j = 1وتطبع األرقام من 1إلى 5على
نفس السطر حٌث ٌعلق المترجم فً هذه الحلقة ح ّتى ٌنتهً منها عندما ,j = 6ث ّم ٌ ّتجه المترجم إلى التعلٌمة
الثانٌة فً الحلقة األولى وهً ;" cout<<"\nوالتً تعنً ِابدأ سطرا جدٌدا ,ث ّم ٌنتهً التكرار األول لهذه
الحلقة ,وتت ّم زٌادة العدّاد iبمقدار 1لٌصبح i = 2وٌت ّم اختبار الشرط مرّ ة أخرى وبما أنّ 2<3فإنّ
المترجم سٌعود وٌدخل الحلقة األولى لٌقوم بنفس الخطوات السابقة ,فٌعٌد قٌمة jإلى 1لٌعلق مرّ ة أخرى فً
الحلقة الثانٌة فٌقوم بطباعة األرقام من جدٌد على السطر الجدٌد الذي جاء من التعلٌمة ;" ,cout<<"\nوعندما
ٌنتهً من الحلقة الثانٌة ٌكمل الحلقة األولى فٌطبع سطرا جدٌدا ,ث ّم ٌكرّ ر ذلك مرّ ة أخٌرة حٌث تكون i = 3
وبعدها تصبح i = 4م ّما ٌعنً أنّ المترجم سٌغادر الحلقة دون أن ٌنفذها مرّ ة رابعة وعندها نحصل على
الشكل السابق.
57
.ًاكتب برنامجا ٌطبع الشكل التال:مثال
*
* *
* * *
* * * *
* * * * *
// nested loop *
#include <iostream> * *
using namespace std;
int main ()
* * *
{ * * * *
for( int i = 1 ; i<=5 ; i++) * * * * *
{
for(int j = 1 ; j<=i ; j++)
cout << "* ";
/* for(int j = 1 ; j<=5 ; j++)
if(j<=i) cout << "* "; */
cout<<"\n";
}
return 0;
}
// nested loop *
#include <iostream> * *
using namespace std;
int main ()
* * *
{ * * * *
int j = 1; * * * * *
for( int i = 1 ; i<=5 ; i++)
{
j = 1 ;
while( j<=i )
{
cout <<"* " ;
j++;
}
cout<<"\n" ;
}
return 0;
}
58
.1اكتب برنامجا ٌطلب من المستخدم أن ٌدخل رقما ث ّم عملٌّة حسابٌّة من العملٌّات األربع المعروفة ث ّم ٌطلب
آخر ث ّم ٌظهر النتٌجة وفقا للعملٌّة التً أدخلها المستخدم )باستخدام .(switch
رقما َ
الخوارزمٌة .0
(aاقرأ الرقم األول .n1
(bاقرأ العملٌة .op
(cاقرأ الرقم الثانً .n2
(dافحص العملٌة op
' op = '+اطبع المجموع إذا كانت
وإال إذا كانت '–' = opاطبع الفرق
وإال إذا كانت '*' = opاطبع الجداء
وإال إذا كانت 'op = '/
إذا كان الرقم الثانً ال ٌساوي الصفر
اطبع القسمة
و ّإال اطبع عبارة . Infinite
الشٌفرة .2
>#include<iostream
;using namespace std
)(int main
{
;float n1 , n2
;'char op = '+
;cout<<"Enter n1:"; cin>> n1
;" cout<<"\nEnter Operator of {+,-,/,*}:
;cin>>op
;cout<<"\nEnter n2: "; cin>> n2
)switch(op
{case '+':
;cout<< n1<<op<<n2<<" = "<<n1+n2
;break
case '-':
;cout<< n1<<op<<n2<<" = "<<n1-n2
;break
case '*':
;cout<< n1<<op<<n2<<" = "<<n1*n2
;break
case '/':
)if(n2 != 0
;cout<< n1<<op<<n2<<" = "<<n1/n2
;"else cout<<"Infinite
;break
}
;return 0
}
59
.3اكتب برنامجا ٌحسب أصغر األعداد التً ٌدخلها المستخدم وعددها ٌ nحدّده المستخدم.
.0الخوارزمٌة
(aاقرأ .n
(bاقرأ الرقم األول .
(cاعتبر أنّ أصغر عدد هو الرقم األول
( أصغر منه اعتبرناه هو األصغر (. )وذلك لكً نقارن كل األعداد التً سنقرأها به ) ( minفإن وجدنا )
(dمن أجل i = 2حتى ) i = nقرأنا الرقم األول سابقا لذلك بدأنا من (3
اقرأ
فاعتبر أن إذا كان
(eاطبع أصغر عدد min
.2الشٌفرة
>#include<iostream
;using namespace std
)(int main
{
;int n, a, min
;" cout<<"Enter n:
;cin>>n
;" cout<<"\nEnter number 1:
;cin>>a
;min = a
)for(int i =2 ; i <=n;i++
{
;" cout<<"\nEnter number "<<i<<":
;cin>>a
)if(a<min
;min = a
}
;cout<<"\nmin = "<< min << endl
;return 0
}
.2اكتب برنامجا ٌقرأ اسم طالب وعدد العبلمات التً ٌرغب بحساب المتوسط الحسابً لها ث ّم ٌقرأ ك ّل عبلمة
منها وفً النهاٌة ٌطبع اسم الطالب ومتوسطه الحسابً فً ك ّل المواد.
.0الخوارزمٌة
(aاقرأ اسم الطالب ثم عدد العبلمات.
(bمن أجل i = 1حتى i = nبزٌادة قدرها 1
اِقرأ العبلمة رقم i
أضف العبلمة رقم iإلى المجموع
(cاطبع اسم الطالب ثم المتوسط الحسابً )المجموع ÷ .(n
5:
.2الشٌفرة
>#include<iostream
>#include<string
;using namespace std
)(void main
;{ string name
;int n,mark,i = 0,sum = 0
//important to initial sum and i to 0 here (it's local var).
;" cout<< "Enter student name: ;cin>>name
;cout<< "Enter number of marks: "; cin>>n
)while(i++ < n
{ ;" cout<< "Enter mark ("<<i<<") [between 0 and 100]:
;cin>> mark
;sum += mark
}; // you can do that
;'cout<< name << " Average = " << (float)sum/n <<'\n
}
.6اكتب برنامجا لحساب السلسلة التالٌة حٌث تدخل nمن لوحة المفاتٌح
.0الخوارزمٌة
(aاقرأ .n
فإن (bمن أجل القٌم بٌن الـ i=1حتى i=n
المجموع = aالمجموع + a
(cاطبع المجموع.
.2الشٌفرة
>#include<iostream
;using namespace std
)(int main
{
; int n
float a = 0.0f ;//Initial a to 0 where f means float value
;" cout<<"Enter n:
;cin>>n
)for(int i=1;i<=n;i++
;a+=1.0f/i;//like a = a + (float)1/i
;cout<< a << endl
;return 0
}
ّ
المخزنة فً المتغٌّر aهً من النوع مالحظة :التعلٌمة ; float a = 0.0fتعنً أنّ القٌمة
العشري و لٌس الصحٌح .وكذلك األمر فً التعلٌمة ; a+=1.0f/iوكان بإمكاننا أن نكتبها كالتالً:
; a += (float)1 / i
ألنّ ناتج عمل ٌّة القسمة الموجودة على ٌمٌن المساوة السابقة لٌس بالضرورة عددا صحٌحا فمثبل العدد
1/2 = 0.5وهو عشريّ لذلك قمنا بتعرٌف المجموع على أ ّنه عشريّ ث ّم قمنا بتحوٌل الطرف
األٌمن من المساواة إلى النوع العشريّ لنضمن عدم ضٌاع البٌانات ألنّ قسمة عددٌن صحٌحٌن هً
عدد صحٌح فً .c++ولو لم نفعل ذلك فإن ناتج التعلٌمة سٌكون كاآلتً:
61
a += 1 / i ;
الخوارزمٌة.0
.n ( اقرأa
ّ فإنi=n حتىi=0 ( من أجل القٌم بٌن الـb
: =i! احسب
= * j فإنj=i حتىj=1 من أجل-
+ e = المجموعe المجموع
.( اطبع المجموعc
الشٌفرة.2
#include<iostream>
using namespace std;
int main()
{
int n;
double e = 0.0f; //Initial a to 0 where f means float value
double fact = 1;
cout<<"Enter n: ";
cin>>n;
for(int i=0;i<n;i++)
{
fact = 1; //initial fact to 1 for each calculation of i!
for(int j = 1; j<=i;j++)
fact *= j;
e += 1.0f/fact; //like e = e + (float)1/i;
}
cout<< e << endl;
return 0;
}
62
مالحظةٌ :جب علٌك أن تقوم بتبدبة متغٌّرات المجامٌع والجداءات إلى القٌمة الحٌادٌّة فً العملٌّة فمثبل المتغٌّر
ٌمثل مجموع السلسلة ونعلم أنّ الجمع ٌؤخذ 2كقٌمة حٌادٌّة أي أنّ إضافة 2إلى المجموع لن ٌغٌّر من النتٌجة ّ e
شٌبا.
ٌمثل جداءات أي أنّ القٌمة الحٌادٌّة هً 1ألنّ ضربها بؤيّ عدد لن ٌغٌّر من النتٌجة أمّا المتغٌّر factفهو ّ
شٌبا .و لو جعلناها 2فإنّ القٌمة التً سنحصل علٌها من أجل المتغٌّر factهً 2ألنّ :
fact = 0وهذا ٌعنً أنّ ناتج التعلٌمة التالٌة هو كاآلتً:
.0الخوارزمٌة
(aاقرأ .x,n
(bمن أجل القٌم بٌن الـ i=0حتى i=nفإن
إلى (1 )كل مرة نعٌد قٌمة
: احسب !=i
من أجل j=1حتى j=iفإن
= * j
+ = المجموع المجموع
(cاطبع المجموع.
.2الشٌفرة
>#include<iostream
عند استخدام التوابع الرٌاضٌة مثل #include<cmath> // pow
;using namespace std
)(int main
{
; int n,x
double e = 0.0f ;//Initial a to 0 where f means float value
;double fact = 1
;" cout<<"Enter n,x:
;cin>>n>>x
)for(int i=0;i<n;i++
{
!fact = 1;//initial fact to 1 for each calculation of i
)for(int j = 1; j<=i;j++
;fact *= j
;e += pow(x,i)/fact
}
;cout<< e << endl
;return 0
}
63
.7اكتب برنامجا لحساب العبلقتٌن التالٌتبن:
̅ ∑ ∑
.0الخوارزمٌة
(aاقرأ .n
(bمن أجل القٌم بٌن الـ i=1حتى i=n
اقرأ
+ = المجموع المجموع
المتو ّسط الحسابً لؤلعداد = المجموع ÷ .nأي
(cاطبع المتوسّط الحسابً.
.2الشٌفرة
>#include<iostream
;using namespace std
)(int main
{
;float sum =0 , average=0 , a=0
;int n
;" cout<<"Enter n:
;cin>>n
)for(int i =1 ; i<=n;i++
{
;" cout<<"Enter a"<<i<<" :
;cin>>a
;sum += a
}
;average = sum / n
;cout<<"\nAverage = "<<average
;return 0
}
.0الخوارزمٌة
(aاقرأ .n
(bمن أجل القٌم بٌن i = 1حتى i = n
+ = المجموع المجموع
(cاطبع المجموع.
64
.2الشٌفرة
>#include<iostream
;using namespace std
)(int main
{
;float sum =0
;int n
;" cout<<"Enter n:
;cin>>n
)for(int i =1 ; i<=n;i++
;sum += i*i*i
;cout<<"\nSum = "<<sum
;return 0
}
.8اكتب برنامجا إلٌجاد جذور معادلة من الدرجة الثانٌة معتمدا على المعلومات التالٌة:
√
√ √
{
.0الخوارزمٌة
(1اقرأ a,b,c
a (3أ( إذا كان 0
b -إذا كان 0
c إذا كان 0
√
إذا كان <2فإن:
√ √
65
الشٌفرة.2
#include<iostream>
#include<cmath> // or <math.h>
using namespace std;
int main()
{
float a , b , c;
float delta=0.0 , x1=0.0 , x2=.0;
float dsqrt=.0;
cout<<"Enter a , b , c:";
cin>>a>>b>>c;
cout<<"\n";
if(a!=0) //1
{
if(b!=0) //2
{
if(c!=0) //3
{
delta =((b*b) - (4*a*c));
cout<<"delta = "<<delta<<"\n";
if(delta > 0) //4
{
x1 = (float)(-1*b + sqrt(delta)) / 2*a;
x2 = (float)(-1*b - sqrt(delta)) / 2*a;
cout<<"x1 = "<< x1<<"\nx2 = "<< x2 << endl;
}
else if(delta == 0)
{
x1 = x2 = (float)-1*b / 2*a ;
cout<<"x1 = x2 = "<<x1<<" Doublicated root!\n";
}
else
cout<<"Impossible in R\n";
}
else
{
x1 = 0;
x2 = (float)-1*b/a;
cout<<"Either x = "<<x1<<"\nOr x = "<<x2<<endl;
}
}
else
{
float t = (float)-1*c/a;
if(t>=0)
cout<<"x = "<<sqrt(t)<<endl;
else
cout<<" Impossible in R\n";
}
}
else{
if(b!= 0) cout<<"x = "<< (float) -c/b<<endl;
else cout<<"it\'s not equation.\n";
}
return 0;
}
66
.1اكتب الشٌفرة الموافقة للخوارزمٌّة التالٌة) :باستخدام التعلٌمة (if
.iأدخل المعدّل
.iiإذا كان المعدّل أكبر من 89و أصغر أو ٌساوي 122اطبع Excellent
.iiiإذا كان المعدّل أكبر من 79و أصغرأو ٌساوي 89اطبع Very Good
.ivإذا كان المع ّدل أكبر من 49و أصغرأو ٌساوي 79اطبع Good
.vإذا كان المعدّل أكبر من 59و أصغرأو ٌساوي 49اطبع Passed
وإال اطبع failed .vi
.3صحّ ح البرامج التالٌة:
) a) while ( c <= 5
{
;product *= c
;++c
) b) if ( gender == 1
; "cout<< "Woman
;else
;"cout<<"man
) c) while ( z >= 0
;sum += z
)d
// nested loop *
>#include <iostream * *
;using namespace std
)( int main
* * *
{ * * * *
;int j = 1 * * * * *
)for( int i = 1 ; i<=3 ; i++
{
) while( j<i
{
; " *"<< cout
;j++
}
}
;return 0
}
3 4 5 6 3 3 4 5 6 6 3 4 5 6 3 4 5 6
4 5 6 7 4 5 5 6 7 6 7 4 5 6 4 7
5 6 7 8 5 6 7 7 8 6 7 8 5 6 5 8
6 7 8 9 6 7 8 9 9 6 7 8 9 6 6 7 8 9
.5اكتب برنامجا ٌقرأ عددا ث ّم ٌحدد فٌما إذا كان ٌقبل القسمة على 12أو ال.
.4اكتب برنامجا لحساب العبلقة التالٌة:
67
.7اكتب برنامجا لحساب وطباعة مجموع األعداد الزوجٌة القابلة للقسمة على 3ما بٌن 1و .99
.8اكتب برنامجا لحساب المضاعف المشترك األصغر LCMلعددٌن مدخلٌن من لوحة المفاتٌح.
بطرٌقتٌن مختلفتٌن. .9اكتب برنامجا لحساب العبلقة التالٌة
.12اكتب برنامجا ٌطلب من المستخدم أن ٌدخل حرفا ث ّم عددا ,ث ّم ٌقوم البرنامج بطباعة مثلث قابم
ومتساوي الساقٌن من هذا الحرف وطول ساقه هو الرقم المدخل سابقا.
.11اكتب برنامجا ٌطلب من المستخدم إدخال عددٌن ث ّم ٌقوم بتقسٌم األوّ ل على الثانً )إذا كان العدد الثانً
صفرا فإن البرنامج ٌطلب من المستخدم أن ٌعٌد إدخال الرقم الثانً من جدٌد( ,ث ّم ٌخٌر المستخدم بٌن إجراء عملٌة
والخروج من البرنامج )و ذلك بإدخال الحرف .(e
ِ جدٌدة )وذلك بإدخال الحرف (n
.13اكتب برنامجا ٌطبع جمٌع قواسم عدد مدخل من لوحة المفاتٌح.
68
الفصل السابع :
لعلّك تذكر برنامجك األوّ ل فً هذا الكتاب Hello Worldقلنا حٌنها" :إنّ النقطة األولى لبداٌة البرنامج هً
التابع )( ."mainلكن ما هو التابع ولماذا نستخدمه؟
التابع :هو بنٌة برمجٌة ٌت ّم تنفٌذها عند استدعابه من أي نقطة فً البرنامج.
ونستخدم التوابع أل ّنها تو ّفر الكثٌر من المزاٌا ومنها:
-2تختصر من طول البرنامج و تو ّفر الوقت ,فبدال من إعادة كتابة ماسٌقوم به تابع ما ع ّدة مرّ ات فإ ّننا
نكتبه مرّ ة واحدة فً تابع ث ّم نستدعً هذا التابع كلّما دعت إلٌه الحاجة.
-3تسهل قراءة البرنامج وتت ّبع األخطاء ,أل ّنه من غٌر الج ٌّد أن تكتب برنامجك كلّه داخل التابع )(main
فٌصبح متشابكا وتصعب قراء ُته.
-4تصوّ ر أ ّنك كتبت برنامجا استخدمت فٌه مجموعة من التعلٌمات ع ّدة مرّ ات ث ّم قرّ رت أن تح ِّسن من
أداء هذه التعلٌمات أو أن تصحِّ ح خطؤ ما فٌها ,فهل ستقوم بهذا التصحٌح من أجل كل مرّ ة كتبت فٌها
تلك التعلٌمات .ماذا لو استخدمت تابعا ٌقوم بهذه العملٌات ث ّم استدعٌته تلك المرّ ات العدٌدة؟ عندها
سٌكون كافٌا أن تعدّل التابع مرّ ة واحدة فقط لٌسري هذا التعدٌل فً برنامجك كلّه دون عناء ٌذكر.
وتشبه التوابع البرمجٌة الدوال الرٌاض ٌّة فً عملها إلى ح ٍّد ما ,فهً تقوم بمجموعة من العملٌات ث ّم تعٌد قٌمة
وحٌدة تدعى قٌمة التابع.
كٌف نصرح عن التوابع؟ ٌتم التصرٌح عن التوابع وفقا للقاعدة التالٌة:
69
تابع لنا فً هذا الكتاب:
و اآلن لنكتب أوّ َل ٍ
// function example The result is 8
>#include <iostream
;using namespace std
)int addition (int a, int b
{
;int r = a + b
;)return (r
}
)( int main
{
;int z
;)z = addition (5,3
;cout << "The result is " << z
;return 0
}
أذ ُك ُر أ ّننا قلنا فً درسنا األول" :إنّ البرنامج ٌبدأ من التابع )( mainدابما" .لذلك سنبدأ من هناك.
تستطٌع أن ترى كٌف أن التابع )( mainبدأ بالتصرٌح عن المتغٌّر zمن النوع الصحٌح ,وبعد ذلك نجد التعلٌمة
; )z = addition(5,3
حٌث ٌت ّم استبدال الوسٌطٌن الشكلٌٌن a, bبالقٌمتٌن 5, 3على الترتٌب ث ّم ٌتوجّه المترجم إلى التابع addition
تاركا التعلٌمات التً لم ّ
ٌنفذها بع ُد من التابع )(ٌ .mainعرِّ ف التابع additionمتغٌّرا موضعٌّا)انظر فقرة المدى
فً نهاٌة الدرس( جدٌدا rث ّم ٌسند إلٌه مجموع الوسٌطٌن .a, b
= r ; a + b
لكنّ a = 5, b = 3وبالنتٌجة فإنّ r = 8ث ّم ٌعٌد التابع القٌمة rباستخدام التعلٌمة ; return rأي أنّ قٌمة التابع
هً العدد 9بعدها ٌخرج المترجم من التابع additionث ّم ٌعود إلى التعلٌمة
;)z = addition(5,3
وبما أنّ قٌمة التابع additionأصبحت 8فهذا ٌعنً أنّ z = 8أٌضا .كما فً الشكل:
6:
مثال:
// function example The 1st result is 5
>#include <iostream The 2nd result is 5
;using namespace std The 3rd result is 2
)int sub(int a, int b The 4th result is 6
{
;)return (a-b
}
)( int main
{
;int x=5, y=3, z
;)z = sub(7,2
;'cout<<"The 1st result is "<<z<<'\n
;'cout<<"The 2nd result is "<<sub(7,2)<<'\n
;'cout<<"The 3rd result is "<<sub(x,y)<<'\n
;)z = 4 + sub(x,y
;'cout << "The 4th result is " << z << '\n
;return 0
}
مالحظة :فً C++عندما نصرّ ح عن تابع أو طرٌقة دون وسطاء فلٌس من الضروري استخدام
الكلمة voidبٌن القوسٌن )( لك ّننا نضعها لنشٌر إلى أنّ التابع ال ٌمتلك وسطاء.
وممّا ٌجب علٌك أن تنتبه إلٌه عندما تستدعً أيّ تابع هو استخدام القوسٌن )( بعد اسم التابع
ح ّتى ولو لم ٌمتلك وسطاء.
71
تمرٌر الوسطاء بالقٌمة و بالمرجع(العنوان)
فً األمثلة السابقة قمنا بتمرٌر الوسطاء بالقٌمة وهذا ٌعنً أ ّننا عندما نستدعً تابعا ذا وسطاء بالقٌمة فإ ّننا نمرّ ر
قٌم المتغ ٌّرات إلى التوابع وال نمرّ ر المتغٌّرات نفسها .كمثال افترض أ ّننا استدعٌنا التابع additionفً المثال
األول كاآلتً:
; int x = 5 , y = 3 , z
; )z = addition(x,y
ما فعلناه هنا هو أ ّننا استدعٌنا التابع additionومرّ رنا إلٌه قٌمتً المتغٌّرٌن xو yأي أ ّننا م ّررنا إلٌه الرقمٌن
5و 3ولم نم ّرر إلٌه المتغٌّرٌن xو .yكما فً الشكل.
إنّ استدعاء الوسطاء بالقٌمة ٌمنع حدوث أي تغٌٌر على المتغٌّر الذي ت ّم تمرٌره إلى التابع خارج هذا التابع
ولتوضٌح هذه المسؤلة نقدّم هذا المثال:
// passing by values
>#include<iostream
;using namespace std
)int add(int a,int b
{
;int result = a + b
a--; b++; //changeing values of a and b
;return result
}
)(int main
{
;int a=5,b=3,z
;cout<<"a and b before calling add function is: "<<a<<", "<<b<<endl
;)z = add(a,b
;cout<<"value of add function is: "<<z<<endl
;cout<<"a and b after calling add function is: "<<a<<", "<<b<<endl
;return 0
}
a and b before calling add function is: 5, 3
value of add function is: 8
a and b after calling add function is: 5, 3
لعلّك الحظت أنّ قٌمتً المتغٌّرٌن aو bلم تتغٌّرا فً التابع)( mainح ّتى بعد استدعاء التابع
additionالذي قام بالتعدٌل على الوسٌطٌن aو bالمعرّ فٌن فٌه والذٌن تغٌّرت قٌمتاهما كما هو واضح فً
نتٌجة البرنامج السابق .لكن ماذا لو أردنا أن تتغٌر قٌم المتغ ٌّرات عند تمرٌرها إلى تابع ما؟ عندها لن ٌكون
تمرٌرها بالقٌمة مجدٌا وٌتح ّتم علٌنا عندب ٍذ أن نم ّررها بالمرجع )العنوان(.
عندما نم ّرر متغٌّرا ما بالمرجع إلى أحد التوابع فإ ّننا ال نمرّر قٌمته وحسب بل نمرّر المتغٌّر نفسه أي أنّ أيّ
تغٌٌر على المتغٌّر الوسٌط فً التابع س ٌَحْ ُد ُ
ث على المتغٌّر ح ّتى خارج هذا التابع.
وٌت ّم االستدعاء بالمرجع من خبلل استخدام المعامل & بعد نوع الوسٌط الذي نرغب بتمرٌره بالمرجع فً جسم
التابع كما فً الشكل:
)void duplicate (int& a, int& b, int& c
x y z
( duplicate x , y , ) z
72
:المثال التالً ٌوضح ذلك
// passing parameters by reference x,y,z before calling duplicate
#include <iostream> x=1, y=3, z=7
using namespace std; x,y,z after calling duplicate
void duplicate (int& a, int& b, int& c) x=2, y=6, z=14
{
a*=2;
b*=2;
c*=2;
}
int main ()
{
int x=1, y=3, z=7;
cout<<"x,y,z before calling duplicate";
cout <<"\nx="<<x<<", y=" << y
<<", z=" <<z<<endl;
duplicate (x, y, z);
cout<<"x,y,z after calling duplicate\n";
cout <<"x="<<x<<", y=" << y
<<", z=" <<z<<endl;
return 0;
}
أ ُ ْت ِب َع نوعُه بالرمز & الذي ٌعنً أنّ هذا الوسٌطduplicate ٌجب أن تنتبه إلى أنّ ك ّل وسٌط فً التابع
.سٌمرّ ر بالمرجع و لٌس بالقٌمة كما فً الحالة األولى
ولكنّ تمرٌر الوسطاء,كما قلنا فً بداٌة هذا الدرس إنّ التوابع تعٌد قٌمة وحٌدة بٌنما ال تعٌد الطرق أ ٌّة قٌمة
.بالمرجع ٌع ّد أداة قوٌة تستطٌع من خبللها أن تجعل التابع )الطرٌقة( ٌعٌد أكثر من قٌمة
:والمثال التالً ٌوضّح هذا
الذي ٌقبل ثبلثة وسطاء حٌث ٌؤخذ الوسٌط األوّ ل وٌعٌد الرقم الذي ٌسبقه كقٌمة له منprevnext لدٌنا التابع
.خبلل الوسٌط الثانً كما ٌعٌد الرقم الذي ٌلً الوسٌط األول كقٌمة له من خبلل الوسٌط الثالث
73
المدى Scope
ك ّل المتغٌّرات التً سنستخدمها فً برامجنا ٌجب أن ٌت ّم التصرٌح عنها أوالٌ .مكن التصرٌح عن المتغٌّرات فً
أيّ مكان من صفحة الشٌفرة .لكنْ هناك شٌا ٌجب أن تعلمه عزٌزي القارئ ,وهو ما ٌ َ
ُعرفُ بمجال الرإٌا
للمتغٌّر )المدى( .تابع الشكل التالً أوال:
>#include<iostream
;using namespace std
; int Integer
; char aCharacter Global Variables
; ]char string[20
)(int main
{
; unsigned short Age
; float ANumber , AnotherOne Local Variables
متغيراث موضعيت
;" cout << "Enter Your age:
;cin >> Age Instructions
…
; return 0
}
المتغ ٌّرات الشاملة Global variablesو المتغ ٌّرات الموضع ٌّة :Local variables
المتغ ٌّرت الشاملة هً المتغٌّرات التً ٌُصرّ ح عنها أعلى البرنامج خارج كل التوابع كما هو واضح فً الشكل
السابق فالمتغٌّرات ] Integer , aCharacter , string [20كلّها متغٌّرات شاملة.
معرّ فة فً طرٌقة(إجراء) ٌمكن الوصول إلى هذه المتغٌّرات من أي مكان داخل الشٌفرة ,و من أي تابع أو
البرنامج.
فً الشكل السابق المتغٌّرات Age , ANumber , AnotherOneصُرِّ ح عنها فً جسم التابع )( mainأي
أ ّننا قادرون على الوصول إلٌها من داخل التابع )( mainفقط .وهذا ٌعنً أ ّنه لن ٌكون بمقدورنا أن نصل إلى
أحد هذه المتغٌّرات من أي تابع آخر مع ّرف فً البرنامج.
فً C++المدى للمتغٌّر الموضعًّ محدّد فقط فً البنٌة البرمجٌة التً صُرِّ َح عنه فٌها
(البنٌة البرمجٌة المقصودة هً
مالحظة :المتغٌرات الشاملة تتم تبدأتها مع بداٌة البرنامج قبل التابع mainبشكل تلقابً
إلى القٌم الصفرٌة لكل نوع فمثبل المتغٌر ٌ Integerؤخذ القٌمة 1تلقابٌا
)جرّ ب أن تطبع قٌم المتغٌرات الشاملة من المثال السابق ستجد أن المتغٌرات الحرفٌة
تطبع فراغات )أو ال تطبع شٌبا(( أمّا المتغٌرات الموضعٌة فٌت ّم تبدأتها عندما ٌصل المترجم
إلى مكان التصرٌح عنها وهً تأخذ قٌما ا عشوائٌة بشكل تلقائً ما لم تقم بتبدئتها بنفسك.
74
المتغٌرات الثابتة static
هذا النوع من المتغٌرات تت ّم تبدأته مرة واحدة فقط وٌمكن أن تتغٌر قٌمته )ٌوجد منه نسخة واحدة فقط(
مثال:
// Example static variables n == 0 , x == 0
>#include <iostream.h n == 1 , x == 0
)void f(int a n == 2 , x == 0
{ n == 3 , x == 0
)while(a-- != 0
{
static int n = 0 ;// initialized once
; int x = 0 // initialized n times
;"cout<<"n == "<<n++<<", x == "<<x++<<"\n
}
}
)( int main
{
;)f(4
;return 0
}
كما ترى فإنّ ناتج التعلٌمة ) divide(12هو العدد 4أل ّننا لم نضع قٌمة للوسٌط الثانً bالذي ٌؤخذ القٌمة
3كقٌمة افتراضٌة له لذلك فإنّ divide(12) = 12 / 2 = 6
أمّا فً الحالة الثانٌة فقد استدعٌنا التابع بالشكل ) divide(20,4أي أ ّننا طلبنا منه أن ٌغٌّر القٌمة
االفتراضٌة للوسٌط bلتصبح العدد 6وعندها ٌكون الناتج .divide(20,4) = 20 / 4 = 5
75
إعادة تحمٌل التوابع functions overloading
لو كان لدٌنا تابعان ٌقومان بنفس التعلٌمات تماما وٌمتلكان نفس االسم أٌضا لك ّنهما ٌختلفان عن بعضٌهما
ُعرفُ بإعادة التحمٌل
بالوسطاء وهذا االختبلف قد ٌكون فً األنواع أو فً عدد الوسطاء المطلوبة ,فهذا ما ٌ َ
التوابع.
وإلٌك المثال التالً:
//overloaded function 2
>#include<iostream 2.5
;using namespace std
)int divide (int a, int b
} ;){ return (a/b
)float divide (float a, float b
} ;){ return (a/b
)( int main
{
;int x=5,y=2
;float n=5.0,m=2.0
;)cout << divide (x,y
;"cout << "\n
;)cout << divide (n,m
;"cout << "\n
;return 0
}
ٌستطٌع المترجم أن ٌحدّد أيّ التابعٌن سٌستخدم من خبلل نوع االوسطاء التً س ُتمرِّ رُها فإذا كانت أعدادا
صحٌحة سٌستدعً التابع المعرّ ف أوّ ال والذي ٌقبل وسطاء من النوع intوإذا كانت الوسطاء من النوع
floatعندها سٌستخدم التابع الثانً.
ٌفٌدنا هذا األسلوب فً التقلٌل من أسماء التوابع التً سنستخدمها فً برنامجنا ,فطالما أنّ هذه التوابع تقوم بنفس
العمل ,فلِم ال تؤخذ نفس االسم.
76
:مثال
// prototyping Type a number (0 to exit): 9
#include <iostream> Number is odd.
using namespace std; Type a number (0 to exit): 6
void odd (int a); Number is even.
void even (int a); Type a number (0 to exit): 1030
Number is even.
int main () Type a number (0 to exit): 0
{ Number is even.
int i;
do {
cout << "Type a number(0 to exit): ";
cin >> i;
odd (i);
} while (i!=0);
return 0;
}
void odd (int a)
{
if ((a%2)!=0)
cout<<"Number is odd.\n";
else even (a);
}
void even (int a)
{
if((a%2)==0)
cout <<"Number is even.\n";
else odd (a);
}
77
الفصل الثامن:
وتستخدم هذه الطرٌقة لحل المشاكل التً ٌمكن ردّها إلى مشكلة واحدة مكرّ رة عدّة مرّ ات ,و ٌعتبر هذا األسلوب
مفٌدا من أجل بعض طرق الترتٌب أو لحساب عاملً عدد ما ! nوالذي ٌعطى بالعبلقة التالٌة:
لو تؤملنا العبلقة ج ٌّدا سنجد أ ّنها تكتب أٌضا بالشكل التالً:
لعلّك الحظت أنّ التابع factقام باستدعاء نفسه من خبلل التعلٌمة ))return (n * fact(n-1
وهذا ما ٌُعرف بالتعاودٌّة .والمقصود بهذا أنّ التابع لن ٌكمل تنفٌذ التعلٌمات الموجودة بعد هذه التعلٌمة وإ ّنما
لٌستدعً نفسه من جدٌد ,وذلك ألنّ قٌمة االستدعاء األوّ ل مرتبطة باستدعاء جدٌد للتابع نفسه وقٌمة هذا
َ سٌعود
االستدعاء الجدٌد مرتبطة باستدعاء آخر سٌتحقق بمجرّ د وصول المترجم إلى نفس السطر من االستدعاء الذي
الحلقة من االستدعاءات المترابطة مع بعضها وٌستمر المترجم بحجز أماكن جدٌدة من ٌنفذه حالٌا وتستمر هذه ْ
الذاكرة لكل المتغٌّرات الموجودة فً التابع المُس َت ْدعى ولكن إلى متى؟
78
ٌعتبر شرط التوقف الذي ٌجب أن تضعه فً التابع أه ّم ما ٌجب علٌك فعله أل ّنك لو لم تفعل فإنّ البرنامج سٌدخل
فً حلقة تعاودٌّة النهابٌّة نتٌجتها تو ّقف البرنامج بخطؤ من النوع .stack overflow
شرط التوقف هو شرط ٌإدّي تح ّققه إلى تنفٌذ تعلٌمة ال تحتوي على استدعاء جدٌد للتابع ومن المه ّم أن ٌكون
هذا الشرط قاببل للتح ّقق لكً ٌتوقف التابع عن استدعاء نفسه ّ
وإال فلٌس لهذا الشرط أٌّة قٌمة .فً مثالنا السابق
الجزء الثانً من تعلٌمة الشرط هو شرط التوقف .اآلن لنعد إلى برنامجنا السابق ولندخل عالم التعاودٌّة الملًء
بالمغامرات.
التابع factمن أجل القٌمة 3 التابع factمن أجل القٌمة 5
fact(3) :
3 > 1 ? yes
)fact(3) = 3 * fact(2
fact(2) :
2 > 1 ? yes
)fact(2) = 2 * fact(1
fact(1) :
1 > 1 ? no
return 1
fact(2) = 2 * 1 = 2
return 2
fact(3) = 3 * 2 = 6
return 6
كما تبلحظ ُتحسب قٌم ُة االستدعاء األخٌر أوّ ال ث ّم الذي قبله ث ّم الذي قبله ح ّتى ٌصل إلى االستدعاء األوّ ل مجسدا
بذلك فكرة المكدّس stackوهً تقول" :آخ ُر الداخلٌن هو أوّ ل الخارجٌن )."(Last in first out
هل ٌجب علٌنا أن نستخدم هذا األسلوب دائماا؟ فً الحقٌقة إنّ استخدام هذا األسلوب مرب ٌ
ك كثٌرا وٌكمن البدٌل
فً استخدام البنى التكرارٌّة ,فالقاعدة تقول" :البرنامج الذي ٌمكن كتابته بشكل تعاوديّ ٌمكن كتابته بشكل
تكراري وهذا أفضل وأسرع" .لنكتب المثال السابق بشكل تكراري:
79
:اكتب التابع factباستخدام الحلقتٌن التكرارٌتٌن الباقٌتٌن.
مثال :اٌجشٔبِظ اٌزبٌ٠ ٟم َٛثؾغبة ِغّٛع اٌغٍغٍخ اٌّىٔٛخ ِٓ األػذاد اٌطج١ؼ١خ ثبٌشىً:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34,.. . عٕىزت ربثؼب ً رؼبٚدّ٠ب ً إل٠غبد األسلبَ اٌزبٌ١خ:
ؽ١ش ّ
أْ اٌشلُ األوجش ِٓ ٕ٠ 1زظ ِٓ ِغّٛع اٌشلّ ٓ١اٌز٠ ٓ٠غجمبٔٗ ٚفك اٌؼاللبد اٌزبٌ١خ:
٘ٚزٖ اٌغٍغٍخ رؼط ٟإٌغجخ اٌز٘ج١خ اٌز ٟرٛعذ ثىضشح ف ٟاٌطج١ؼخ ٟ٘ٚرٕزظ ِٓ اٌمغّخ
ٟ٘ٚاٌّغزخذِخ ف ٟئٔشبء إٌٛافز ٚاٌغشف ٚاٌّجبٔ ٟؽ١ش رّضً ٔغجخ اٌطٛي ئٌ ٝاٌؼشع.
7:
#include<iostream> Enter n: 4
using namespace std; fib(4) = 3
int fib(int n)
{
if ( n == 0 || n == 1 )
return n;
else
return (fib(n-1)+fib(n-2));
}
int main()
{
int n ;
cout<< "Enter n: ";
cin>> n;
cout<< "\nfib(" << n << ") = " << fib(n) << endl;
}
1- fib(4):
4 ?= 0 no, or 4 ?= 1 no
fib(4) = fib(3) + fib(2)
2- fib(3):
3 ?= 0 no, or 3 ?= 1 no
fib(3) = fib(2) + fib(1)
3- fib(2):
2 ?= 0 no, or 2 ?= 1 no
fib(2) = fib(1) + fib(0)
4- fib(1):
1 ?= 0 no, or 1 ?= 1 yes
fib(1) = 1
return fib(1)
5- fib(0):
0 ?= 0 yes, or 0 ?= 1 no
fib(0) = 0
return fib(0)
fib(2) = 1 + 0
return fib(2)
fib(3) = 1 + fib(1)
6- fib(1):
1 ?= 0 no, or 1 ?= 1 yes
fib(1) = 1
return fib(1)
fib(3) = 1 + 1 = 2
return fib(3)
fib(4) = 2 + fib(2)
81
7- fib(2):
2 ?= 0 no, or 2 ?= 1 no
fib(2) = fib(1) + fib(0)
8- fib(1):
1 ?= 0 no, or 1 ?= 1 yes
fib(1) = 1
return fib(1)
9- fib(0):
0 ?= 0 yes, or 0 ?= 1 no
fib(0) = 0
return fib(0)
fib(2) = 1 + 0
return fib(2)
fib(4) = 2 + 1 = 3
82
.1ماهو ناتج تنفٌذ التوابع التالٌة:
A B C
>#include<iostream >#include<iostream >#include<iostream
;using namespace std ;using namespace std ;using namespace std
)int sum(int a )int sum(int a )int sum(int a
{ { {
)if(a>1 )if(a>1 )if(a>1
;)return a+sum(--a ;)return a+sum(a-- ;)return a+sum(a-1
)else if(a==1 )else if(a==1 )else if(a==1
;return a ;return a ;return a
;else return 0 ;else return 0 ;else return 0
} } }
)(int main )(int main )(int main
{ { {
;cout<<sum(5)<<endl ;cout<<sum(5)<<endl ;cout<<sum(5)<<endl
;return 0 ;return 0 ;return 0
} } }
الحالة Aنجد التعلٌمة ;) return a+sum(--aفً هذه التعلٌمة المعامل ٌ --aؤخذ أولوٌة التنفٌذ ح ّتى
ولو كان فً ٌمٌن التعلٌمة لذلك فإنّ قٌمة aستتغ ٌّر أوّ ال ث ّم سٌت ّم االستدعاء التالً ,وسٌكون ناتج التابع كما هو
ضح فً الجدول .A مو ّ
الحالة Bنجد التعلٌمة ;) return a+sum(a--فً هذه التعلٌمة المعامل ٌ a--ؤخذ أولوٌة التنفٌذ ح ّتى
ولو كان فً ٌمٌن التعلٌمة لكنّ قٌمة aلن تتغ ٌّر ح ّتى ٌنتقل المترجم إلى التعلٌمة التالٌة ّإال أنّ االستدعاء التالً
سٌت ّم وستكون قٌمة aعندها نفسها فً االستدعاء السابق أي أنّ شرط تو ّقف التعاودٌّة لن ٌتحقّق أبدا ممّا ٌسبب
الخطؤ المذكور فً الجدول .B
الحالة Cنجد التعلٌمة ;) return a+sum(a-1فً هذه التعلٌمة a-1تنقص قٌمة aبمقدار 1فً
االستدعاء التالً ,وسٌكون ناتج التابع كما هو موضح فً الجدول .C
83
ٌُ .3قا ُل عن عد ٍد ما إ ّنه تا ٌّم إذا كان ٌساوي مجموع قواسِ مه كلِّها باإلضافة إلى العدد 1ما عدا العدد نفسه.
مثال:
6 = 1 + 2 + 3
اكتب برنامجا فٌه إجرا ٌء ٌطبع العبارة Is perfectإذا كان العدد المدخل تامّا
وٌطبع sn't perfectإذا لم ٌكن تامّا.
>#include<iostream
;using namespace std
;)void isperfect(int a
)(int main
{
;int n
;" cout<<"Enter number:
;cin>>n
;)isperfect(n
;return 0
}
)void isperfect(int a
{
;int sum = 0
)for(int i = 1; i< a;i++
)if(a%i == 0
;sum+= i
;"(sum == a)? cout<<a <<" perfect\n":cout<< a<<" not perfect\n
}
.2أبراج هانوي ()Towers of Hanoi
رؼزشع ٘زٖ اٌّشىٍخ ِؼظُ ِزؼٍّ ٟاٌجشِغخ ٟ٘ٚرؼٛد ئٌِٕ ٝبؽك ف ٟششق آع١ب ؽ١ش وبْ ف ٟاٌّؼجذ صالصخ
أػّذح األٚي ف 46 ٗ١لشطب ً ِشرجخ رظبػذ٠ب ً ِٓ األػٍ ٝئٌ ٝاألعفً ثؾ١ش ٠ى ْٛأوجش٘ب ف ٟأعفً اٌؼّٛد ٚرمٛي
األعطٛسح" :ئّٔٗ ػٕذِب ٕ٠ز ٟٙاٌش٘جبْ ِٓ ٔمً وً ٘زٖ األلشاص ئٌ ٝاٌؼّٛد اٌضبٌش عٕ١ز ٟٙاٌؼبٌُ"ٌٚ ,ىٕ٠ ٟمً
اٌش٘جبْ ٘زٖ األلشاص ٠غت أْ ٠شاػٛا اٌمبػذح اٌزبٌ١خ:
ٌ -2جب نقل قرص واحد فقط فً ك ّل مرّ ة.
ٌ -3جب استخدام أحد األعمدة كوسٌط مإقت.
-4ال ٌجوز أن تضع قرصا كبٌرا فوق قرص أصغر منه أبدا.
مهم ّتنا اآلن أن نساعد هإالء الرهبان على إٌجاد الطرٌقة األفضل لح ّل هذه المشكلة.
حٌث سنكتب تابعا تعاود ٌّا ٌقبل الوسطاء التالٌة:
n 1 عدد األقراص
from العمود الموجودة علٌه األقراص
to العمود الذي سننقل األقراص إلٌه
temp العمود الوسٌط المإقت
84
لدٌنا ثبلثة أقراص نرٌد نقلها من العمود األول إلى العمود الثالث باالعتماد على العمود الثانً كوسٌط:مثال
.مإقت
الخوارزمٌة.0
n = 1 إذا كان-1
.انقل القرص من العمود األول إلى العمود الثالث من دون اللجوء إلى العمود الوسٌط المإقت
: و إال افعل الخطوات التالٌة-3
. من العمود األول إلى العمود الثانً باستخدام العمود الثالث كوسٌط مإقتn-1 انقل القرص رقم-a
. انقل القرص األخٌر من العمود األول إلى العمود الثالث-b
. من العمود الثانً إلى العمود الثالث باستخدام العمود األول كوسٌط مإقتn-1 انقل القرص رقم-c
الشٌفرة.2
#include<iostream>
using namespace std;
int han(int n,int a,int b,int t);
int main()
{
int n,from=1,to=3,temp=2;
cout<<"Enter n, from, to, temp\ne.g: 3\n1\n3\n2\n\n\n";
cin>>n>>from>>to>>temp;
han(n,from,to,temp);
return 0;
}
85
.1أوجد األخطاء فً التوابع التالٌة:
)1. int Sum(int a , int b
{
;int sum = a + b
}
)2. int divide(int a , int b
{
;return (float)a/b
}
)3. void subtract(int a , int b
{
;return a-b
}
.2ما هو ناتج البرنامج التالً:
>#include<iostream
;using namespace std
;int x = 0
;float b
)float d(float a , float& b
{
;a--
;b++
;x = a/b
;return (x+1)/2.0
}
)(int main
{
;float a
;"cout<<"x\tb\ta\n
;cout<<x<<"\t"<<b<<"\t"<<a<<endl
;a = b = ++x
;cout<<d(a , b)<<endl
;cout<<x<<"\t"<<b<<"\t"<<a<<endl
;return 0
}
.3ماذا سٌكون ناتج البرنامج السابق لو استبدلنا التعلٌمة ; return (x+1)/2.0بالتعلٌمة
; return ++x/2.0؟.
.4اكتب برنامجا ٌقوم بالعملٌّات الرٌاضٌّة األربع وذلك باستخدام التوابع.
ث ّم اكتبه باستخدام تابع تكراري. .5باستخدام تابع تعاوديّ اكتب برنامجا ٌحسب العدد
( و و َو )مع مالحظة أنّ :
.6اكتب برنامجا فٌه تابع ٌقوم بإٌجاد مجموع السلسلة التالٌة:
𝜋 ∑
اعتمد على التمرٌن السابق لحساب.
.7اكتب برنامجا إلٌجاد القاسم المشترك األكبر لعددٌن باستخدام تابع تكراري و آخر تعاودي
علما أنّ .GCD(x , y) = GCD(x , x % y) :
86
) ( .8اكتب برنامجا فٌه تابع لحساب ! nو آخر لحساب
) ( و آخر لحساب
.9اكتب تابعا )إجراء( اسمه multipleبحٌث ٌؤخذ عددٌن صحٌحٌن كوسٌطٌن ث ّم ٌعٌد )ٌطبع( trueإذا
كان العدد الثانً من مضاعفات العدد األول وإال فٌعٌد )ٌطبع( .false
.10اكتب برنامجا ّ فٌه تابع ٌقوم بفحص رقم صحٌح ممرّ ر إلٌه وٌعٌد قٌمة منطقٌّة trueإذا كان أولٌّا و
falseإذا لم ٌكن ,ث ّم استخدم إجراء ٌقوم بطباعة كل األرقام األولٌّة بٌن 1والرقم المدخلٌ).مكنك استخدام
التابع السابق داخل هذا اإلجراء(.
مبلحظة :الرقم األوّ لً هو الرقم الذي ٌقبل القسمة على نفسه وعلى 1فقط .والرقم 1لٌس أولٌّا.
.11اكتب برنامجا فٌه تابع لحساب القٌمة المطلقة لعدد ما .علما أ ّنها تح ّقق الشكل التالً:
| | {
.12اكتب برنامجا فٌه ثبلثة توابع كما ٌلً:
𝜋 ٌ حسب مساحة دابرة بعد إدخال نصف قطرها r
ٌ حسب مساحة مستطٌل بعد إدخال طولً ضلعٌه a, b
ٌحسب مساحة مثلث بعد إدخال طول قاعدته bو ارتفاعه h
حٌث ٌعرض البرنامج قابمة فٌها الخٌارات الممكنة وٌختار المستخدم أحدها كما فً الشكل التالً:
87
القسم الثاني
ِ
ببيان عن تفصيمُا سأَُّبِ َ
يك مِ ّإل بست ٍةِ
أخي لن تنال الع َ
ِ
زمان وطول ٍ
أستاذ وصحبةُ اجتُاد وبمغةٌ
ُ وحرص و ٌ ٌ ذكاءٌ
لألمام الشافعي
88
الفصل التاسع:
المصفوفة هً سلسلة من العناصر ذات النوع نفسه محفوظة فً الذاكرة بشكل متتالً بحٌث ٌمكن الوصول إلى
أي عنصر بذكر اسم المصفوفة متبوعا بالدلٌل .الشكل العام للتصرٌح عن المصفوفات هو
فمثبل ٌمكن أن نخزن 5قٌم من النوع intدون الحاجة إلى التصرٌح عن خمسة متغٌّرات بؤسماء مختلفة وذلك
باستخدام المصفوفات كما ٌلً:
; ]int array[5
مالحظة :عند التصرٌح عن المصفوفة فً لغة ٌ C++جب أن ٌكون عدد العناصر قٌمة ثابتة
حٌث إن المصفوفات هً حجرات ذاكرة ستاتٌكٌة ٌجب أن ٌُعطى حجم هذه الحجرات
;}int array[5]={1,3,4,2,7
;}int array[]={1,3,4,2,7
عندما نصرح عن المصفوفات داخل التوابع وال نضع قٌم لعناصرها فإن قٌم العناصر ستبقى عشوابٌة حتى
نضع قٌم لهذه العناصر ,وعندما نصرح عن المصفوفات خارج أي تابع فإن قٌم العناصر تكون صفرٌة.
89
التعامل مع المصفوفات
فً أي جزء من البرنامج تكون فٌه المصفوفة مربٌّة )راجع فقرة المدى( ٌمكن أن نصل إلى عناصرها للقراءة أو
للتعدٌل على أيّ عنصر منها كما ٌلً:
لؤلقواس المربعة استخدامان مختلفان األول لتحدٌد حجم المصفوفة عند التصرٌح عنها ,والثانً لتحدٌد دلٌل
العنصر المراد الوصول إلٌه من المصفوفة
8:
المصفوفات المتعددة األبعاد
ٌمكن أن توصف المصفوفات المتعددة األبعاد بؤ ّنها مصفوفات لمصفوفات فالمصفوفة ثنابٌة البعد ٌمكن تصورها
على أ ّنها جدول ثنابً البعد لبٌانات من نوع واحد.
تمثل aمصفوفة ثنابٌة البعد مإلفة من 3أسطر و 5أعمدة من النوع intتع ّرف كما ٌلً :
;]int a[3][5
]a[1][3
المصفوفات المتعددة األبعاد ال تقتصر على دلٌلٌن) بعدٌن( فقط بل ٌمكن أن تحوي أدلة بحسب الحاجة ,لك ّننا
نادرا ما نحتاج أكثر من 3أبعاد حٌث تكون كمٌة الذاكرة المطلوبة لتخزٌن هذه المصفوفات كبٌرة جدّا فمثبل
هذه المصفوفة تحجز فً الذاكرة متغٌّر من نوع charلكل ثانٌة فً القرن أي تحجز حوالً 3ملٌارات باٌت
إذا صرحنا عن هذه المصفوفة فإ ّنها ستستهلك حوالً 3جٌغا من الذاكرة .RAM
المصفوفات المتعددة األبعاد هً مجرد تبسٌط لمصفوفة من بعد واحد حٌث المصفوفتان التالٌتان متكافبتان
91
// multidimensional array // pseudo-multidimensional array
>#include <iostream >#include <iostream
;using namespace std ;using namespace std
استخدمنا #defineلٌصبح التعدٌل البلحق على البرنامج أسهل فلو أردنا أن تكون قٌمة البعد HEIGHT
4بدال من 2نكتب #define HEIGHT 4بدال من #define HEIGHT 3
وذلك أبسط من تعرٌف المصفوفة بثوابت عددٌة ) ;] ( int a[3][5ث ّم تعدٌل 3إلى 4فً كل مرّ ة تذكر فٌها المصفوفة
فً البرنامج.
كما ٌمكن أن نسند قٌم لعناصر المصفوفة أثناء التصرٌح كما ٌلً :
;}}int a[3][5]={{1,2,3,4,5},{2,4,6,8,10},{3,6,9,12,15
حٌث إنّ العناصر المحصورة بٌن األقواس الداخلٌة هً عناصر السطر األول والثانً والثالث بالترتٌب
;}}int a[3][5]={{1,3,4,5},{10},{12,15
فإنّ باقً عناصر المصفوفة تكون أصفارا كما فً الجدول المبٌن :
92
المصفوفات كمعامالت(وسطاء) للتوابع
نحتاج أحٌانا أن نم ّرر مصفوفة كمعامل لتابع ما .فً لغة C++ال ٌمكن تمرٌر مجموعة حجرات ذاكرة بالقٌمة
كمعامل لتابع ما ,وبالتالً ال ٌمكن تمرٌر كامل المصفوفة ,ولكن ٌمكن تمرٌر عنوانها الذاكري.
ولكً تصبح المصفوفات معامبلت ٌجب علٌنا عند التصرٌح عن التابع المراد التعامل معه أن نضع نوع
البٌانات للمصفوفة المراد استقبالها واسم للمصفوفة داخل التابع ث ّم أقواس مربعة فارغة فمثبل التابع
ٌقبل مصفوفة من النوع intوسٌسمٌها argولنمرر مصفوفة لهذا التابع نصرح عنها
مثال
كما ترى فإنّ المعامل األول للتابع printarrayهو )][ٌ (int argقبل أي مصفوفة من النوع intأٌا كان
طولها ,أمّا المعامل الثانً فهو طول المصفوفة المراد تمرٌرها وهذا ٌعطً الحلقة forشرط التوقف.
عند التصرٌح عن التابع ٌمكن أٌضا أن نم ّكنه من أن ٌستقبل المصفوفات المتعددة األبعاد وٌكون التصرٌح عن
التابع الذي ٌقبل المصفوفة
;)]void procedure (int myarray[ ][3 ثنابٌة األبعاد
;)]void procedure (int myarray[ ][3][4 وثبلثٌة األبعاد
93
الحظ أنّ القوس األول فارغ أمّا باقً األقواس فٌجب أن نحدّد عمقها ألنّ المترجم ٌجب أن ٌحدد خبلل التابع ما
هً قٌمة كل بعد إضافً.
عندما تمرّ ر المصفوفات األحادٌة أو المتعددة األبعاد كمعامبلت للتوابع تشكل مصدرا شابعا لؤلخطاء عند
شرات لفهم أفضل آللٌة عمل المصفوفات. المبرمجٌن قلٌلً الخبرة ,ننصح هنا بقراءة فصل المإ ّ
األعداد العشوائٌة
هناك العدٌد من التطبٌقات البرمجٌة الشابعة التً تحتاج إلى المحاكاة كاأللعاب والدراسات االحتمالٌة
واالحصابٌة.
ٌمكن أن نولد األعداد العشوابٌة فً لغة C++باستخدام التابع )( randالموجود فً المكتبة القٌاسٌة
> <cstdlibلذلك ٌجب أن نضمّنها فً البرنامج.
ٌولد التابع )( randأرقاما صحٌحة موجبة ( )unsigned integerبٌن 0و RAND_MAXالذي
هو ثابت رمزي معرف فً المكتبة القٌاسٌة تكون قٌمته 32767على األقل.
لكً نحدد مجال لؤلعداد التً سٌتم تولٌدها نستخدم العبلقة
;number = shiftingValue + rand() % scalingFactor
كل مرّ ة ٌت ّم فٌها تنفٌذ البرنامج ٌت ّم تولٌد نفس األعداد لذلك ٌوجد تابع فً المكتبة القٌاسٌة اسمه
)(ٌ srandقوم بتغٌٌر سلسلة األرقام عند كل تنفٌذ للبرنامج وٌستقبل هذا التابع قٌمة من النوع
unsigned integerولكً نضمن تغٌّر القٌمة المرسلة إلى srandنستخدم التابع )( timeكالتالً:
;) ) srand( time( 0
) ٌ time( 0قرأ الوقت عند التنفٌذ بالثوانً وٌحوّ له إلى .unsigned integer
التابع )( timeموجود فً المكتبة > <ctimeالتً ٌجب أن نضمّها إلى البرنامج.
مثال:
>#include <iostream
>#include <cstdlib
>#include <ctime
;using namespace std
)( int main
{
;int num,guess,guessNum
;"cout<<"\tguessing game\n\n
;))srand(time(0
;num=1+rand()%100
;" cout<<"enter your guess between 1 and 100:
)for(guessNum=0;guess!=num;guessNum++
{
;cin>>guess
)if(guess<num
;" cout<<"your guess is too low!. try again:
)if(guess>num
;" cout<<"your guess is too high!. try again:
}
94
cout<<"congratulations. you guessed it!!!. "
<<"\nyou tried "<<guessNum<<" times to guess it\n";
return 0;
}
guessing game
95
: ذات النوع الصحٌح قم بطباعتها ث ّم اطبع مجموع عناصرهاA لتكن لدٌنا المصفوفة-1
A= [ 5, 6, 1, 9, 12, 4, 7 ]
#include <iostream>
using namespace std;
int main()
{
int A[]={5,6,1,9,12,4,7};
int sum=0;
for(int i=0;i<7;i++)
{
cout<<A[i]<<" ";
sum+=A[i]; //sum =sum+A[i];
}
cout<<"\nsum= "<<sum<<endl;
return 0;
}
#include<iostream>
using namespace std;
int f[1000];
int fib(int n)
{
f[0] = 0; f[1] = 1;
for(int i=2; i<=n;i++)
f[i] = f[i-1]+f[i-2];
return f[n];
}
int main()
{
int n ;
cout<< "Enter n: ";
cin>> n;
cout<< "\nfib(" << n << ") = " << fib(n) << endl;
}
ث ّم ٌقوم بالبحث عنV أرقام صحٌحة إلى مصفوفة وعدد10 اكتب برنامجا ٌطلب من المستخدم أن ٌدخل-3
ّ موجودا فٌهاV " إذا كانV is in the array" ضمن عناصر المصفوفة المدخلة وٌطبعV
وإال فإ ّنه ٌطبع
."V is not in the array"
96
#include <iostream>
using namespace std;
int main()
{
int arr[10],V,i;
bool found=false;
cout<<"enter 10 numbers please!\n";
for(i=0;i<10;i++)
{
cout<<"number"<<i+1<<"= ";
cin>>arr[i];
}
cout<<"enter V: ";
cin>>V;
for(i=0;i<10;i++)
if(arr[i]==V)
{
found=true;
break;
}
#include <iostream>
using namespace std;
}
int main()
{
97
int X[4][4],i,j;
int positives=0,negatives=0,zeros=0;
int even=0,odd=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
cout<<"X["<<i+1<<"]["<<j+1<<"]= ";
cin>>X[i][j];
if(X[i][j]>0)
positives++;
if(X[i][j]<0)
negatives++;
if(X[i][j]==0)
zeros++;
if(X[i][j]%2==0)
even++;
if(X[i][j]%2!=0)
odd++;
}
cout<<"\n";
print(X);//printing X
cout<<"\nnumber of positive elements="<<positives;
cout<<"\nnumber of negative elements="<<negatives;
cout<<"\nnumber of zeroth elements="<<zeros;
cout<<"\nnumber of even elements="<<even;
cout<<"\nnumber of odd elements="<<odd;
cout<<"\nleading diagonal: ";
for(i=0;i<4;i++)
cout<<X[i][i]<<"\t";
cout<<"\ncross diagonal: ";
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
if(i+j==4-1)
cout<<X[i][j]<<"\t";
}
cout<<endl;
return 0;
}
اكتب برنامجا ٌقوم بجمع مصفوفتٌن ثنابٌتً األبعادعلما أن شرط الجمع هو أن ٌكون للمصفوفتٌن نفس-5
.األبعاد
98
{
cout<<"a["<<i+1<<"]["<<j+1<<"]=";cin>>a[i][j];
cout<<"b["<<i+1<<"]["<<j+1<<"]=";cin>>b[i][j];
c[i][j]=a[i][j]+b[i][j];
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cout<<a[i][j]<<" ";
cout<<"\n";
}
cout<<"\n +\n\n";
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cout<<b[i][j]<<" ";
cout<<"\n";
}
cout<<"\n =\n\n";
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cout<<c[i][j]<<" ";
cout<<"\n";
}
return 0;
}
اكتب برنامجا ٌقوم بضرب مصفوفتٌن ثنابٌتً األبعادعلما أن شرط الضرب هو أن ٌكون عدد أعمدة-6
.المصفوفة األولى ٌساوي عدد أسطر المصفوفة الثانٌة
//matrix multiplication
#include<iostream>
using namespace std;
#define M 20
int a[M][M],b[M][M],c[M][M];//all arrays' elements equal zero
void main()
{
int ma,na,mb,nb,i,j,k;
99
cout<<"enter B elements\n";//reading B elements
for(i=0;i<mb;i++)
for(j=0;j<nb;j++)
{ cout<<"b["<<i+1<<"]["<<j+1<<"]= ";cin>>b[i][j];}
for(i=0;i<ma;i++)//multiplication
for(j=0;j<nb;j++)
for(k=0;k<na;k++)
c[i][j]+=(a[i][k]*b[k][j]);
( لٌقومprint) ( تحوي أسماء األشهر ث ّم مرر هذه المصفوفة إلى تابعstring) عرّ ف مصفوفة من النوع-8
.بطباعتها
#include<iostream>
#include<string>
using namespace std;
void print(string m[],int n)
{
for(int i=0;i<n;i++)
cout<<m[i]<<"\n";
}
int main()
{
string months[12]={"January","February","March"
,"April","May", "June"
,"July","August","September"
,"October","November","December"};
print(months,12);
return 0;
}
9:
-1أوجد األخطاء فً كل من العبارات التالٌة:
)a بفرض ; } int b[ 10 ] = { 0
) for ( int i = 0; i<= 10; i++
;b[ i ] = 1
-5اكتب برنامجا ٌطلب من المستخدم إدخال مصفوفتٌن Aو ) Bمن النوع (integerكل منهما مكونة
من 10عناصر ٌ ,جب على البرنامج أن ٌضم المصفوفة Bإلى نهاٌة المصفوفة Aوٌضع الناتج فً
المصفوفة Cالمإلفة من 20عنصر ث ّم ٌطبع المصفوفة .C
-6اكتب برنامجا ٌطلب من المستخدم إدخال مصفوفة ) (integerمن 10عناصر ث ّم ٌطبع البرنامج
المصفوفة تصاعدٌة " " the array is growingأو تنازلٌة ""the array is decreasing
أو ثابتة " "the array is constantأو تصاعدٌة وتنازلٌة "the array is growing and
"decreasing.
:1
-7اكتب برنامجا ٌم ّكن المستخدم من إدخال عدد الطبلب nوأسمابهم namesودرجاتهم marksفً
مقرر ما ث ّم ٌطبع أسماء الطبلب حسب درجاتهم فً المقرر وبترتٌب تنازلً.
-8اكتب برنامجا ٌقوم بجمع مصفوفتٌن ثنابٌتً األبعاد علما أن شرط الجمع هو أن ٌكون للمصفوفتٌن
نفس األبعاد باستخدام التوابع) .التمرٌن محلول فً التمارٌن المحلولة بدون استخدام التوابع(.
:2
الفصل العاشر:
تم ّكننا السبلسل من التعامل مع النصوص سواء منها الكلمات أو الجمل أو األسماء. ..
السلسلة مإلفة من تتابع من العناصر ذات النوع charحٌث إنّ كل عنصر ٌمثل حرف فً السلسلة .فمثبل
المصفوفة )سلسلة الرموز( التالٌة :
;]char str [20
ٌمكن أن تخزن سلسلة مإلفة من 15حرف كما فً الشكل
لٌس ضرورٌا أن نمؤل كل عناصر السلسلة فٌمكن أن تحوي السلسلة فً نقطة ما من البرنامج الكلمة ""Hello
التً تمؤل 5خانات أو العبارة " "Hello Worldالتً تمؤل 12خانة.
عند نهاٌة السلسلة المخزنة فً كبل الحالتٌن نصل إلى الرمز nullالذي ٌمكن أن ٌكتب 0أو ' ' \0
التعامل مع السالسل
بما أنّ السبلسل هً مصفوفات طبٌعٌة فإ ّنها تخضع لنفس قواعد المصفوفات فإذا أردنا مثبل أن نضع القٌم فً
السلسلة أثناء التصرٌح نكتب :
;} 'char mystring[6] = { 'H', 'e', 'l', 'l', 'o', '\0
أو
;} 'char mystring[ ] = { 'H', 'e', 'l', 'l', 'o', '\0
ولكن هناك طرٌقة أخرى لعمل ذلك وهً:
;"char mystring [ ] = "Hello
حٌث إنّ السبلسل المحصورة بعبلمات اقتباس مزدوجة ٌضاف إلى نهاٌتها الثابت nullبشكل آلً.
إنّ إسناد الثوابت النصٌة مثل " "Helloللسبلسل صحٌح فقط أثناء التصرٌح عن السلسلة )المصفوفة(
لذلك فالعبارات التالٌة غٌر صحٌحة:
;"mystring = "Hello
;"mystring[] = "Hello
;} 'mystring = { 'H', 'e', 'l', 'l', 'o', '\0
:3
شر ثابت ٌشٌر إلى كتلة ذاكرة محجوزة وبسبب هذا السبب فً ذلك ٌعود إلى أنّ المصفوفة هً عبارة عن مإ ّ
شر( فبل ٌمكن أن نسند أٌّة قٌمة للمصفوفة بح ِّد ذاتها ولكن ٌمكن إسناد قٌمة أليّ عنصر من الثبات )فً قٌمة المإ ّ
عناصر هذه المصفوفة.
لذلك فإنّ الطرف األٌسر لئلسناد ٌمكن أن ٌكون فقط عنصر من مصفوفة ولٌس مصفوفة كاملة.
إذا ٌمكن أن نكتب :
;'mystring[0] = 'H
;'mystring[1] = 'e
;'mystring[2] = 'l
;'mystring[3] = 'l
;'mystring[4] = 'o
;'mystring[5] = '\0
ال تبدو هذه طرٌقة عملٌة لذلك سنستخدم توابع جاهزة مثل التابع strcpyالمعرّ ف فً المكتبة cstring
) (stringوٌُستد َعى بالطرٌقة التالٌة:
;)strcpy (string1, string2
هذا التابع ٌقوم بنسخ محتوى string2وٌضعه فً string1
مثال
:4
هناك طرٌقة أخرى تعتمد على تعلٌمة اإلدخال cinفً هذه الحالة ٌت ّم إدخال السلسلة من قبل المستخدم أثناء
تنفٌذ البرنامج حٌث نستخدم هنا التابع getlineحسب الشكل العام
:5
شصر: الفصل احلاد
إنّ ذاكرة الحاسوب ماهً ّإال تتابع من خبلٌا حجم كل منها واحد باٌت ,ولكل واحدة من هذه الخبلٌا عنوان ممٌز
حٌث ٌتولى نظام التشغٌل عنونة الذاكرة بؤرقام متتابعة.
شر هو متغٌّر كسابر المتغٌّرات ولكنه ٌختلف عنها فٌما ٌختزنه فهو ال ٌختزن البٌانات العادٌة كاألرقام المإ ّ
والرموز وإ ّنما ٌختزن عنوان المتغٌّر الذي ٌشٌر إلٌه.
معامل المرجع ( * )
إذا سبقنا المإ ّشر aبمعامل المرجع * أي إذا كتبنا *aفإنّ العبارة ; c = *aتعنً ضع القٌمة التً ٌُشٌ ُر
إلٌها المإ ّ
شر aفً المتغٌّر .c
;a = &b
;c = *a
:6
التصرٌح عن المؤ ّ
شرات
الشكل العام للتصرٌح هو
;type * pointer_name
أمثلة
;int * number
;char * character
;float * greatnumber
شرات ٌحجز شرات كل منها ٌشٌر إلى نوع مختلف من البٌانات مع ذلك فإنّ ك ّل واحد من هذه المإ ّ لدٌنا ثبلثة مإ ّ
شرات لها حجوم مختلفة فً نفس الحجم فً الذاكرة بحسب نظام التشغٌل أ ّما البٌانات التً ُتشٌر إلٌها هذه المإ ّ
الذاكرة كما أنها من أنواع مختلفة.
مثال 0
// my first pointer a=10 , b=20
>#include <iostream
;using namespace std
)( int main
{
;int a = 5, b = 15
;int *ptr
;ptr= &a
;*ptr = 10
;ptr = &b
;*ptr = 20
;cout<<"a="<<a<<" , b="<<b
;return 0
}
شر ٌ ptrشٌر إلى aعن الحظ أنه تم تعدٌل قٌم aو bبشكل غٌر مباشر حٌث جعلنا المإ ّ
شر ptrوكذلك األمر بالنسبة لـ .b طرٌق الرمز & ث ّم أسندنا القٌمة 10إلى ماٌشٌر إلٌه المإ ّ
ّ
شر خبلل البرنامج عناوٌن مختلفة حٌث استخدمنا المإشر ptrلٌشٌر إلى a كما ٌمكن أن ٌؤخذ المإ ّ
ث ّم إلى .b
مثال 2
// more pointers a=10 , b=20
>#include <iostream
;using namespace std
)( int main
{
;int a = 5, b = 15
;int *p1, *p2
;p1 = &a = p1عنوان // a
;p2 = &b = p2عنوان // b
;*p1 = 10 اٌمّ١خ اٌز٠ ٟش١ش ئٌٙ١ب // 12=p1
;*p2 = *p1 القٌمة التً ٌشٌر إلٌها = p2القٌمة التً ٌشٌر إلٌها // p1
;p1 = p2 // p1 = p2
;*p1 = 20 القٌمة التً ٌشٌر إلٌها // 32 = p1
;cout << "a=" << a << " , b=" << b
;return 0
}
:7
المؤ ّ
شرات والمصفوفات
شر إلى ح ّد كبٌر فعندما نصرح عن مصفوفة فإ ّننا نضع فً الذاكرة عنوان أول عنصر إنّ المصفوفة تشبه المإ ّ
من عناصرها كما أ ّننا عندما نصرح عن مإشر فإنه ٌشٌر إلى أول عنصر لذلك فهما متشابهان.
ّ ّ
لنفرض التصرٌحٌن التالٌٌن:
;]int numbers [20
;int * p
إنّ اإلسناد ; p = numbersصحٌح ألنّ pو numbersمتكافبان ولهما نفس الخصابص ,االختبلف الوحٌد
شر pفً حٌن أنّ numbersسٌشٌر دوما إلى أول عنصر من هو أ ّننا نستطٌع أن نعطً قٌمة مختلفة للمإ ّ
شر ثابت ) اسم المصفوفةشر عادي إلى المتغٌّرات أ ّما numbersفهو مإ ّ العشرٌن عنصر .لذلك فإنّ pهو مإ ّ
هو مإ ّ
شر ثابت (.
مثال 3
فً فصل المصفوفات استخدمنا األقواس المربعة للتعامل مع عناصر المصفوفة ,هناك طرٌقة مكافبة باستخدام
شر ٌ pشٌر إلى المصفوفة :(aشرات كما ٌلً )إذا كان المإ ّ
المإ ّ
*p ]a[0
)*(p+1 ]a[1
)*(p+2 ]a[2
... ...
)*(p+i ]a[i
. .
. .
فإذا أردنا وضع القٌمة 1فً العنصر الخامس للمصفوفة aفهناك طرٌقتان متكافبتان
;a[5] = 0
;*(p+5) = 0
:8
تبدئة المؤ ّ
شرات
أمّا فً حالة المصفوفات فإنّ المترجم ٌسمح لنا بؤن نسند الثابت الذي سٌشٌر إلٌه المإ ّ
شر أثناء التصرٌح عن
المإ ّ
شر )هنا الثابت هو سلسلة رموز(:
;"char * p = "hello
شر ٌ pشٌر إلى أول فً هذه الحالة ت ّم حجز حجم ثابت من الذاكرة لتخزٌن السلسة " "helloوت ّم جعل المإ ّ
رمز ) (charلمجموعة الحجرات الذاكرٌّة التً ت ّم حجزها أي أنّ ٌ pشٌر إلى الحجرة التً تحوي الحرف ''h
فإذا فرضنا أنّ "ُ "helloخ ّزنت فً العنوان 2813وما بعده فإنّ الذي ت ّم ٌُلخصه الشكل التالً:
مصفوفة المؤ ّ
شرات
مثال :
;]char* cars[3 مصفوفة 4مإ ّ
شرات على سبلسل //
;"char[0]="Mercedes
;"char[1]="Nissan
;"char[2]="Ferrari
:9
العمل ٌّات الحسابٌة على المؤ ّ
شرات
العملٌّات الحسابٌة على المإ ّ
شرات تختلف قلٌبلعن تلك التً ننفذها على األعداد الصحٌحة إذ ٌمكن أن ننفذ فقط
شرات .لكن الجمع والطرح لهما عملٌتً الجمع والطرح أمّا الضرب والقسمة فلٌس لهما أي معنى فى عالم المإ ّ
شرات وذلك بحسب حجم نوع المعطٌات التً تشٌر إلٌها المإ ّ
شرات. سلوك مختلف مع المإ ّ
كما نعلم فإنّ مقدار ما ٌت ّم حجزه من الذاكرة ٌعتمد على نوع المعطٌات فمثبل النوع )ٌ (charحجز 2باٌت
والنوع )ٌ (shortحجز 3باٌت أما النوع ) (longفٌحجز 5باٌت ولنفرض أ ّنه لدٌنا ثبلثة مإ ّ
شرات
;char *mychar
;short *myshort
;long *mylong
وبفرض أ ّنها تشٌر إلى حجرات الذاكرة 4111 , 3111 , 2111بالترتٌب فإذا كتبنا
;mychar++
;myshort++
;mylong++
شر mycharسٌحوي القٌمة 2112و myshortسٌحوي القٌمة 2113و mylongسٌحوي عندب ٍذ المإ ّ
ّ
القٌمة 2115وسبب ذلك أننا عندما نضٌف 2إلى المإشر معنى ذلك أننا نجعله ٌشٌر إلى العنصر التالً لنفس
شر حسب النوع.النوع الذي عرفناه أي ٌضاف الحجم بالباٌت إلى المإ ّ
::
من المهم التنبٌه إلى أنّ معامبل الزٌادة ) (++والنقصان ) (--لهما أولوٌّة على معامل المرجع )*( لذلك فإنّ
التعابٌر التالٌة ربما تسبب التباس فً فهمها
;*p++
;*p++ = *q++
شر pولٌس القٌمة التً ٌشٌر التعبٌر األول مكافا لـ ) *(p++وهو ٌقوم بزٌادة 2إلى العنوان الذي ٌحوٌه المإ ّ
إلٌها وبالتالً فإنّ القٌمة الجدٌدة التً ٌشٌر إلٌها pهً قٌمة عشوابٌة.
فً التعبٌر الثانً بما أنّ المعاملٌن ) (++و ) (--بعد المساواة التً ٌجب أن تتح ّقق فإنّ القٌمة ُ *qتسند إلى *p
ث ّم ٌُزاد ك ّل من pو qبمقدار 2أي التعبٌر الثانً مكافا لـ
;*p = *q
;p++
;q++
لذلك ٌنبغً استخدام األقواس لتجنب األخطاء.
;char a
;char * b
;char ** c
;'a = 'z
;b = &a
;c = &b
بفرض حجرات الذاكرة التً حُجزت عشوابٌا مبٌّنة بالشكل:
الجدٌد فً هذا المثال هو المتغٌّر cالذي ٌمكن أن ٌد ّل على ثبلث قٌم مختلفة
هو متغٌّر من النوع )** (charوقٌمته 8092 c
*cهو متغٌّر من النوع )* (charوقٌمته 7230
**cهو متغٌّر من النوع ) (charوقٌمته ''z
مالحظة
*c == b == 7230
'**c == *b == a == 'z
المؤ ّ
شرات الخالٌة ()void pointers
شر ذو النوع ٌ voidمكنه أن ٌشٌر إلى أي نوع من المعطٌات سواء كان صحٌحا ) (integerأو حقٌقٌا المإ ّ
شرات ال نستطٌع أن نستخدم معامل ) (floatأو سلسلة رموز) .(string of charactersفً هذا النوع من المإ ّ
شر غٌر معلوم ,ولهذا السبب ٌجب علٌنا أن نلجؤ دابما إلى تحوٌل النوع المرجع * بشكل مباشر ألنّ طول المإ ّ
voidإلى نوع آخر مح َّدد من المعطٌات.
211
ّ من فوابد هذا المإ
: ًشر هو إمكانٌة تمرٌر قٌم عامّة إلى تابع ما كما فً المثال التال
// integer increaser 6, 10, 13
#include <iostream>
using namespace std;
int main ()
{
char a = 5;
short b = 9;
long c = 12;
increase (&a,sizeof(a));
increase (&b,sizeof(b));
increase (&c,sizeof(c));
cout << (int) a << ", " << b << ", " << c;
return 0;
}
هوsizeof(char) فمثبل, هو تابع مدمج فً اللغة ٌرجع قٌمة ثابتة تمثل الحجم بالباٌت لما بٌن القوسٌنsizeof
. باٌت2 هوchar ألنّ طول النوع2
ّ المؤ
شرات على التوابع
ّ نصرّ ح عن المإ.شرات على التوابع ٌمكن أن نم ّرر التابع كمعامل لتابع آخر
شر على تابع بنفس ّ من خبلل المإ
.* األسلوب الذي نصرّ ح به عن تابع باستثناء أ ّننا نضع االسم بٌن قوسٌن ونسبقه بـ
:مثال
// pointer to functions 8
#include <iostream>
using namespace std;
212
int main ()
{
int m,n;
m = operation(7, 5, addition);
n = operation(20, m, minus);
cout <<n;
return 0;
}
subtraction أسندنا التابع.int ٌقبل معاملٌن من النوعint شر عام على تابع من النوع
ّ هو مإminus
فً سطر التعرٌف نفسهminus شر ّ إلى المإ
int (* minus)(int,int) = subtraction;
213
الفصل الثاني شصر:
ح ّتى اآلن كان حجز الذاكرة فً برامجنا ٌت ّم أثناء كتابة الكود أي أثناء التصرٌح عن المتغٌّرات المختلفة قبل
تنفٌذ البرنامج .ولكن ماذا لو احتجنا مقداراا متغ ٌّراا من الذاكرة ٌت ّم تحدٌده أثناء تنفٌذ البرنامج؟
مثبل فً حال احتجنا إلى دخل من المستخدم لنحدّد الحجم البلزم حجزه.
اإلجابة على ذلك هً الذاكرة الدٌنامٌكٌة التً من أجلها تحوي C++معاملً newو delete
المعامل new
لكً نطلب ذاكرة دٌنامٌكٌة نستخدم المعامل newمتبوعا بنوع المعطٌات أو متبوعا بنوع المعطٌات و
قوسٌن مربعٌن ] [ ٌحوٌان عدد العناصر المطلوبة.
شرا ٌشٌر إلى أول حجرة من حجرات الذاكرة التً ت ّم حجزها.ٌ عٌد المعامل newمإ ّ
نستخدمه كما ٌلً
;pointer = new type لحجز ذاكرة تحوي عنصر واحد من نوع المعطٌات.
أو
لحجز ذاكرة تحوي مجموعة عناصر)مصفوفة( من نوع المعطٌات ;]pointer = new type[elements
مثال:
;int * p
;]p = new int [5
فً هذه الحالة ٌقوم النظام بحجز مقدار من الذاكرة مإلّف من 6حجرات من النوع intوٌعٌد مإ ّ
شرا ٌشٌر
إلى أول حجرة من الحجرات الخمس وت ّم إسناد قٌمة هذا المإ ّشر إلى المإ ّ
شر . p
سابقا عند التصرٌح عن المصفوفة كان ٌجب أن ٌكون عدد العناصر قٌمة ثابتة أمّا فً الذاكرة الدٌنامٌكٌة فٌمكن
أن ٌكون عدد العناصر متغٌّرا ٌقوم المستخدم بإدخاله
العدٌد من البرامج تستخدم الذاكرة الدٌنامٌكٌة و ٌت ّم أحٌانا استهبلك الذاكرة بشكل كامل لذلك ٌجب التؤكد من أنّ
الحجز قد ت ّم بشكل صحٌح عند استخدام newكما ٌلً
;int * p
;]p = new int [5
)if (p == NULL
exit(1); // error assigning memory.
214
المعامل delete
بعد أن تنتهً حاجتنا إلى الذاكرة التً حجزناها باستخدام ٌ newنبغً علٌنا أن نحرّ رها باستخدام المعامل
deleteلكً تصبح متاحة للحجز الحقا ,ونستخدمه كما ٌلً:
مثال:
//calculate average using dynamic memory enter the number of courses: 7
>#include <iostream mark 1= 91
>#include<stdlib.h mark 2= 78
;using namespace std mark 3= 77
mark 4= 68
mark 5= 83
)( int main mark 6= 73
{ mark 7= 81
;int n,i,sum=0 average= 78.7143
;" cout<<"enter the number of courses:
;cin>>n
;]int *p=new int[n
;)if(p==NULL)exit(1
)for(i=0;i<n;i++
{
;" ="<<cout<<"mark "<<i+1
)cin>>p[i];//or cin>>*(p+i
;]sum+=p[i
}
;cout<<"average= "<<(float)sum/n<<endl
;delete [] p
;return 0
}
شرات الفارغة )التً ال تشٌر إلى شًء(. NULLهً قٌمة ثابتة مع ّرفة فً مكتبات C++لتد ّل على المإ ّ
#define NULL 0 فً حال لم تكن معرّ فة فٌمكن أن تع ّرفها بنفسك كما ٌلً:
شرات ,ولكن NULLمستخدمة بشكل أكبر وهً أكثر ال ٌوجد فارق أن تضع 1أو NULLعندما تفحص المإ ّ
شرات مع قٌم ثابتة أو نسندها إلى أرقام.وضوحا أل ّننا نادرا ما نقارن المإ ّ
215
الفصل الثالث شصر:
تراكٌب المعطٌات
تركٌب المعطٌات هو نوع ٌقوم المستخدم بتعرٌفه وٌتؤلف من أنواع مختلفة من البٌانات ذات الحجوم المختلفة
مجموعة فً تصرٌح واحد بالشكل :
{ struct name
;data_type element1
;data_type element2
.
.
;data_type elementN
; } object1_name, object2_name, … , objectN_name
:nameاسم التركٌب.
أنواع البٌانات المختلفة التً ٌحوٌها التركٌب موجودة بٌن القوسٌن { }.
مثال:
{ struct products
;]char name [30
;float price
;} apple, orange, melon
عرّ فنا أوال التركٌب productsالذي ٌتؤلف من حقلٌن هما nameو priceك ّل منهما له نوع
مختلف عن نوع اآلخر.
بعد أن عرّ فنا التركٌب قمنا بتعرٌف ثبلثة كابنات من نفس النوع productsوهً apple :و
orangeو .melon
ٌمكن أن نشتق الكابنات من التركٌب بطرٌقة أخرى وذلك بؤن نعرف الكابن المشتق باستخدام اسم
التركٌب .مثبل:
{ struct products
;]char name [30
;float price
;}
;products apple
;products orange, melon
216
كل منهما له نوع مختلف عن نوعprice وname الذي ٌتؤلف من حقلٌن هماproducts عرّ فنا أوال التركٌب
.اآلخر
:ً( للتصرٌح عن ثبلثة كابنات من النوع نفسه هproducts) بعد أن عرّ فنا التركٌب استخدمنا اسم التركٌب
.melon وorange وapple
ٌصبح اسم نوع جدٌد مثل األنواع األساسٌةproducts ّ( فإنproducts) بعد أن صرّ حنا عن التركٌب
( وٌصبح بإمكاننا أن نصرح عن كابنات )متغٌّراتshort أوchar أوint المعرفة مسبقا كالنوع
.من هذا النوع
وname ٌصبح لكل منها حقبلن هماmelon وorange وapple بعد أن صرحنا عن الكابنات
.( ث ّم اسم الحقل.) ٌمكن أن نتعامل مع الحقول بذكر اسم الكابن تلٌه نقطةprice
أمثلة
apple.name
orange.name char [30]
melon.name
apple.price
orange.price float
melon.pric
مثال
struct students{
char name[50];
char city[50];
int tel;
}st1,st2;
int main()
{
//filling information
cout<<"enter student1 name, city and tel_no: ";
cin>>st1.name;
cin>>st1.city;
cin>>st1.tel;
cout<<"enter student2 name, city and tel_no: ";
cin>>st2.name;
cin>>st2.city;
cin>>st2.tel;
//printing information
cout<<"\nname"<<"\tcity\t"<<"tel_no";
cout<<"\n------------------------\n";
cout<<st1.name<<"\t"<<st1.city<<"\t"<<st1.tel<<endl;
cout<<st2.name<<"\t"<<st2.city<<"\t"<<st2.tel<<endl;
return 0;
}
217
enter student1 name, city and tel_no: Ali
Hama
3245675
enter student2 name, city and tel_no: Ahmad
Homs
2452658
مصفوفة التراكٌب
التراكٌب مٌزة كثٌرا ما تستخدم لبناء قواعد المعطٌات خاصة إذا استخدمناها مع المصفوفات حٌث ٌمكن بناء
: ًمصفوفة تراكٌب باإلعبلن عن التركٌب أوال ث ّم نعلن عن مصفوفة من نوع التركٌب كما ٌل
struct name {
type element1;
type element2;
.
.
type elementN;
} object_name [ELEMENTS];
:مثال
// array of structures Enter title: java how to program
#include <iostream> Enter year: 1997
using namespace std; Enter title: eat, pray, love
#include <stdlib.h> Enter year: 2006
Enter title: advanced memory
#define N_BOOKS 5 Enter year: 2005
Enter title: being logical
struct book { Enter year: 2004
char title [50]; Enter title: c++ how to program
int year; Enter year: 2005
} books [N_BOOKS];
You have entered these movies:
void printBook (book mybook); java how to program (1997)
eat, pray, love (2006)
int main () advanced memory (2005)
{ being logical (2004)
char buffer [50]; c++ how to program (2005)
int n;
cout<<"please enter the titles and
years for 5 books!.\n";
for (n=0; n< N_BOOKS; n++)
{
cout << "title: ";
cin.getline (books[n].title,50);
cout << "year: ";
cin.getline (buffer,50);
books[n].year = atoi(buffer);
}
218
cout << "\nYou have entered these
books:\n";
for (n=0; n< N_BOOKS; n++)
printBook (books[n]);
return 0;
}
ّ التراكٌب و المؤ
شرات
ّ ٌمكن استخدام للمإ
: ًشرات لتشٌر إلى التراكٌب كما ٌل
struct book {
char title [50];
int year;
};
book abook;
book * pbook;
book هو كابن من النوع:abook
ّ هو مإ:pbook
book شر ٌشٌر إلى كابن من النوع
نكتبabook ٌشٌر إلى الكابنpbook شر ّ ولجعل المإ
pbook = &abook;
مثال
// pointers to structures Enter title: c++ how to program
#include <iostream> Enter year: 2005
using namespace std;
#include <stdlib.h> You have entered:
struct book { c++ how to program (2005)
char title [50];
int year;
} ;
int main ()
{
char buffer[50];
book abook;
book * pbook;
pbook = &abook;
cout<<"please enter a book title and
its publish year!.\n";
cout << "title: ";
cin.getline (pbook->title,50);
cout << "Enter year: ";
cin.getline (buffer,50);
pbook->year = atoi (buffer);
return 0;
}
219
شرات على شرات على التراكٌب أو المإ ّ
المعامل )> (-هو معامل مرجعً ٌستخدم خصٌصا مع المإ ّ
األصناف للوصول إلى الحقول الموجودة فٌها وهو ٌلغً الحاجة الستخدام األقواس فً كل مرة نرٌد
أن نصل إلى حقل ما فً تركٌب ما.
pbook->title (*pbook).title
كبل العبارتٌن صحٌحتان وتعنٌان أ ّننا نتعامل مع الحقل titleالمشار إلٌه بالمإ ّ
شر pbook
وٌجب أن نمٌزهما عن العبارتٌن :
*pbook.title )*(pbook.title
اللتٌن تعنٌان أ ّننا نتعامل مع القٌمة المشار إلٌها بالعنصر ) titleالذي ال ٌعتبر مإ ّ
شرا باألساس(
أي أنّ العبارتٌن األخٌرتان خاطبتان وال تعنٌان شٌبا.
التراكٌب المتداخلة
تراكٌب أخرى كما فً المثال التالً:
َ ٌمكن أن تكون التراكٌب حقوال موجودة داخل
{struct books
;]char title [50
;int year
}
{struct friends
;]char name [50
;]char email [50
;books favourite_book
;} ahmad,ali
;friends *p = &ahmad
ahmad.name
ali.favourite_book.title
ahmad.favourite_book.year
p->favourite_book.year
21:
: اكتب برنامج ٌقوم باستعراض البحة تتضمن
. إدخال اسم جدٌد لطالب.2
. استعراض كل أسماء الطبلب المدخلة.3
. البحث عن طرٌق إدخال اسم الطالب.4
. البحث عن طرٌق إدخال السنة الدراسٌة للطالب.5
. ترتٌب أسماء الطبلب أبجدٌا.6
. الخروج من البرنامج.7
#include<iostream>
#include<string>
using namespace std;
#define M 100
int count=0;
struct studentsType
{
string name;
int age,year;
}student[M];
void add();
void browse();
void searchByName();
void searchByYear();
void order();
int main()
{
int choice;
do
{
cout<<"please enter your choice!.\n";
cout<<"1-add new student\n2-browse\n3-search by name\n4-search
by year"
<<"\n5-alphabetical order\n6-exit\n";
cin>>choice;
switch(choice)
{
case 1: add();break;
case 2: browse();break;
case 3: searchByName();break;
case 4: searchByYear();break;
case 5:order();break;
case 6: return 0;
}
}while(count<M);
return 0;
}
221
void add()
{
void searchByName()
{
string name;
bool found=false;
int i;
cout<<"enter name:";cin>>name;
for(i=0;i<count;i++)
{
if(name==student[i].name)
{
cout<<student[i].name<<"\t"<<student[i].age<<"\t"<<student[i].year<<"\n";
found=true;
}
}
if(!found)
cout<<name<<" was not found\n";
cout<<"\n";
}
void searchByYear()
{
int y;
bool found=false;
int i;
cout<<"enter year:";cin>>y;
for(i=0;i<count;i++)
{
if(student[i].year==y)
{
222
cout<<student[i].name<<"\t"<<student[i].age<<"\t"<<student[i].year<<"\n";
found=true;
}
}
cout<<"\n";
if(!found)
cout<<"no result\n";
}
void order()
{
int i,j;
studentsType temp;
if(count<2)goto out;
for(i=0;i<count;i++)
{
for(j=0;j<count-1;j++)
{
if(student[j].name>student[j+1].name)
{
temp=student[j];
student[j]=student[j+1];
student[j+1]=temp;
}
}
}
cout<<"\n";
out:browse();
}
223
الفصل الرابع شصر:
نوع بٌانا ٍ
ت ٌع ّرفه المستخدم )المبرمج ( ,باإلضافة إلى التراكٌب توجد تعرّ فنا سابقا على التراكٌب التً تعتبر َ
أنوع أخرى مثل:
صة ()typedef
تعرٌف أنواع خا ّ
ٌمكن أن نعرف أنواع خاصّة بنا باالعتماد على أنواع معرّ فة وموجودة مسبقا باستخدام الكلمة المفتاحٌة
typedefالتً ُتستخدم كما ٌلً :
هنا عرّ فنا أربعة أنواع جدٌدة هً Cو WORDو string_tو fieldعلى أنها charو unsigned
intو * charو ] char[50بالترتٌب ,وبالتالً ٌمكن استخدام هذه األنواع لتعرٌف متغٌّرات كما ٌلً :
typedefمفٌدة لتعرٌف نوع س ٌُستخدم بكثرة فً البرنامج ومن الممكن أن تحتاج لتغٌٌرهذا النوع فٌما بعد,
كما تستخدم أحٌانا عندما ٌكون اسم النوع طوٌبل وترٌده أن ٌكون مختصرا.
الوحدات )(Unions
الـ unionهو تركٌب جمٌع عناصره ٌت ّم حجزها فً نفس العنوان الذاكري.
طرٌقة اإلعبلن عنها واستخدامها مشابهة للطرٌقة المتبعة فً التراكٌب لكنّ عملها مختلف تماما:
{ union model_name
;type1 element1
;type2 element2
;type3 element3
.
.
;} object_name
224
مثبل:
{ union mytypes_t
;char c
;int i
;float f
;} mytypes
تنتج العناصر :
mytypes.c
mytypes.i
mytypes.f
كل واحد من هذه العناصر له نوع مختلف ولكنها فً نفس الموقع من الذاكرة وأي تعدٌل على قٌمة أحد
العناصر سٌإثر على قٌم كل العناصر.
ٌسمح هذا النوع بتعرٌف أنواع بٌانات ٌمكن أن تؤخذ قٌم مختلفة محدّدة من قبل المستخدم والشكل العام لها هو :
{ enum model_name
value1,
value2,
value3,
.
.
;} object_name
مثال:
;}enum colors {black, blue, green, cyan, red, purple, yellow, white
الحظ أ ّننا لم نضمّن أي نوع بٌانات أساسً أي أ ّننا أنشؤنا نوع بٌانات جدٌد دون اإلعتماد على نوع موجود
مسبقا وهو النوع colorsالذي ٌؤخذ أحد القٌم الموجودة بٌن القوسٌن }{ وعندما نعرّ ف الكابن mycolor
من هذا النوع فإنّ العبارات التالٌة صحٌحة:
;colors mycolor
;mycolor = blue
;if (mycolor == green) mycolor = red
فً الواقع إنّ البٌانات الموجودة داخل القوسٌن }{ تستبدل بقٌم عددٌة صحٌحة أثناء الترجمة والقٌم االفتراضٌة
هً 2ألول عنصر و 1للثانً و 3للثالث وهكذا...
أمّا إذا خصّصنا قٌمة ألول عنصر فإنّ قٌمة العنصر الثانً تزٌد عن قٌمة األول بواحد وهكذا..
مثبل إذا كتبنا black=1بدال من blackوتركنا العناصر الباقٌة كما هً فإنّ whiteسٌؤخذ القٌمة .8
225
الفصل اخلامس شصر:
الملفات تش ّكل أساس التعامل مع الحاسب فعندما تعمل على أي حاسب الب ّد لك من أن تفتح مل ّفا ما أو تكتب على
ملف سواء كان هذا الملف نصّا أو صورة أو صوتا. ..إلخ.
ّ
تخزن فً الذاكرة العشوابٌة وٌت ّم فقدانها عند إنهاء فً معظم البرامج التً كتبناها سابقا كانت المعلومات
البرنامج فإذا ك ّنا بحاجة لهذه المعلومات فٌمكننا تخزٌنها فً ملفات على القرص الصلب الستعادتها الحقا.
فتح ملف
عموما العملٌة األولى التً تن ّفذ على كابن من الصفوف المذكورة هً ربط هذا الكابن بملف حقٌقً أي عملٌة
مثل فً البرنامج من خبلل الكابن ) (streamوأي دخل أو خرج ٌنفذ على هذا الكابنفتح ملف ,هذه العملٌة ُت ّ
سٌطبق على الملف الحقٌقً.
لكً نفتح ملفا عن طرٌق الكابن streamنستخدم تابعه العضوي )( openالمعرّ ف بالشكل :
ٌمكن الجمع بٌن هذه األوضاع بالمعامل "أو" الثنابً | .مثبل إذا أردنا فتح الملف " "example.binفً
الوضع الثنابً إلضافة بٌانات ٌمكن أن نفعل ذلك باستدعاء التابع العضوي openكالتالً:
;ofstream file
;)file.open ("example.bin", ios::out | ios::app | ios::binary
لكل تابع openمن التوابع الخاصة بالصفوف ofstreamو ifstreamو fstreamوضع افتراضً
خاص ٌختلف من صف إلى آخر كما فً الجدول :
226
تطبق القٌمة االفتراضٌة فقط فً حال ت ّم استدعاء التابع بدون تخصٌص البارامتر .mode
بما أنّ العملٌة األولى التً تنفذ على الكابن من الصفوف السابقة هً عملٌة فتح ملف فإنّ كبل من هذه
الصفوف الثبلثة ٌحتوي على مشٌد )بانً( ٌقوم باستدعاء التابع openبنفس البارامترات ,لذلك ٌمكننا
أن نعرّ ف الكابن ونستدعً التابع بسطر واحد كما ٌلً:
ٌمكنك التحقق من أنّ الملف قد فُتح بشكل صحٌح باستدعاء التابع العضوي )(is_open
;)(bool is_open
هذا التابع ٌُعٌد trueإذا ت ّم ربط الكابن بالملف بشكل صحٌح ّ
وإال فإ ّنه ٌُعٌد .false
إغالق ملف
عندما تنتهً عملٌات القراءة أو الكتابة أو فً حال اكتمال الملف فٌجب إغبلقه لٌصبح متاحا لبلستخدام ثانٌة.
لفعل ذلك نستدعً التابع العضوي )( closeالمعرّ ف كما ٌلً:
;)( void close
بعد استدعاء هذا التابع ٌصبح الكابن streamجاهزا لفتح ملف آخر
فً حالة هدم الكابن وهو ماٌزال مرتبط بالملف فإنّ الهادم ٌستدعً التابع closeتلقابٌا.
صٌة
الملفات الن ّ
227
كما أنّ إدخال البٌانات من ملف ٌنفذ بنفس الطرٌقة التً نستخدم بها :cin
{ )( int main
;]char buffer[256
;)"ifstream examplefile ("example.txt
))(if (! examplefile.is_open
} ;){ cout << "Error opening file"; exit (1
) )(while (! examplefile.eof
{
;)examplefile.getline (buffer,100
;cout << buffer << endl
}
;return 0
}
هذا البرنامج ٌقوم بقراءة ملف نصًّ وٌطبع محتواه على الشاشة.
التابع العضوي )(ٌ eofعٌد trueعند الوصول إلى نهاٌة الملف.
التحقق من الحالة
باإلضافة إلى التابع )( eofتوجد توابع عضوٌة أخرى للتحقق من حالة الكابن )الملف( تعٌد كلها قٌم منطقٌة
)(bool
)(:bad
ٌعٌد trueإذا حدث خطؤ فً عملٌة القراءة أو الكتابة .مثبل إذا حاولنا الكتابة على ملف غٌر مفتوح ألجل
الكتابة.
)(:fail
ٌعٌد trueكما فً حالة التابع )( badكما ٌعٌد trueفً حال حدوث خطؤ فً صٌغة الملف كما فً حالة
قراءة عدد صحٌح وت ّم إدخال حرف.
)(:good
ٌعٌد falseفً نفس الحاالت التً تعٌد فٌها التوابع السابقة .true
لتصفٌر عبلمات الحالة التً ت ّم فحصها بالتوابع السابقة نستخدم التابع )( clearبدون وسطاء.
مؤ ّ
شرا التدفق ( getو )put
شر getالذي ٌشٌر إلى العنصر التالً المراد قراءته. ifstreamمثل ٌ istreamحوي المإ ّ
ّ
ofstreamمثل ٌ ostreamحوي المإشر putالذي ٌشٌر إلى المكان الذي سٌكتب فٌه العنصر التالً.
وأخٌرا fstreamمثل ٌ iostreamرث ّ
كبل من getو .put
228
ٌمكن التعامل مع هذه المإ ّ
شرات من خبلل التوابع التالٌة:
شر إلى مكان ٌبعد بعدا ثابتا عن نقطة معٌنة بحٌث:باستخدام هذا الشكل ٌت ّم تحوٌل المإ ّ
:off_typeنوع مكافا للنوع .long
:directionالوجهة التً سٌتم نقل المإ ّ
شر إلٌها وٌجب أن تؤخذ إحدى الحاالت التالٌة:
{ )( int main
;long l,m
ifstream file (filename,
;)ios::in|ios::binary
;)(l = file.tellg
;)file.seekg (0, ios::end
;)(m = file.tellg
;)(file.close
;cout << "size of " << filename
;"cout << " is " << (m-l) << " bytes.\n
;return 0
}
229
الفصل السادس شصر:
أثناء تطوٌر البرنامج قد نتعرض لمواقف ال نستطٌع فٌها أن نح ّدد فٌما إذا كانت هذه الشٌفرة ستعمل بالشكل
الصحٌح أو ال وذلك أل ّنه قد تكون هناك بعض الحاالت التً ال نتو ّقع حدوثها والتً قد تتسبب بخطؤ فً
البرنامج .مثل هذه المواقف هو ما ندعوه باالستثناءات.
وأخٌرا قدمت C++ثبلث معامبلت جدٌدة ) (try, throw, catchلتساعدنا فً معالجة هذه الحاالت وهً
تؤخذ الشكل التالً:
{ try
اٌش١فشح اٌز ٟعزؼًّ أ ّٚلً //
٠شعً ِزغّ١شاً ٠غزخذَ ٌّؼشفخ العزضٕبء اٌؾبطًthrow exception; //
}
)catch (type exception
{
اٌش١فشح اٌز ٟع١زُ رٕف١ز٘ب ؽ٠ ٓ١ؾذس العزضٕبء //
}
الشٌفرة داخل التعلٌمة ُ tryتن َّفذ بشكل طبٌعً ,وبمجرّ د حصول استثناء ما ٌت ّم استدعاء التعلٌمة throw -
التً تعٌد وسٌطا قٌمته وصفٌ لبلستثناء الحاصل و ٌؤخذ )الوسٌط( أي نوع مناسب لبلستثناء.
إذا حصل االستثناء فإنّ التعلٌمة catchستعمل على استقبال الوسٌط الممرّ ر من التعلٌمة throwو ّإال -
فإنّ التعلٌمة catchلن تن ّفذ.
مثال :
// exceptions Exception: Out of range
>#include <iostream
;using namespace std
{ )( int main
;]char myarray[10
try
{
)for (int n=0; n<=10; n++
;"{ if (n>9) throw "Out of range
;'myarray[9]='z
}
}
)catch (char * str
} ;{ cout << "Exception: " << str << endl
;return 0
}
22:
عندها فإنّ التعلٌمة التً ستن ّفذ هً تلك. لٌقبل أكثر من نوع من الوسطاءcatch ٌمكننا أن نعٌد تحمٌل المعامل
.throw التً تقابل الحالة الحاصلة وٌتعرّ ف المترجم علٌها من خبلل الوسٌط المرسل من التعٌمة
: مثال
عندها سٌت ّمmystring األول هو أ ّال ٌت ّم إسناد أيّ حرف من الحروف العشر المشكلة للمصفوفة ّ -
.catch( char * str ){…} استدعاء التعلٌمة
.catch ( int i ) {…} عندها ُتستدعى التعلٌمة9 القٌمة أكبر منi الثانً عندما ٌؤخذ العدّاد -
231
القسم الثالث
الن ِ
جوم فَال تَقنَ ْع مبا دو َن ف َم ُر ِوم إذا غامرت يف َشر ٍ
ّ َ َْ َ
َعظي ِ كطَ ْع ِ امل ْو ِت يف ْأم ٍر فطَ ْع ُِ امل ْو ِت يف ْأم ٍر َح ِق ٍي
َ َ
المّئي ِ ديعةُ الطّب ِع مك َ َ
خ وتهِ ه ه ه ه ه ه َ جز َع ْق ٌلَيرى اجلُبَ ُ ّ َ َ
الع نأ ناء
احلَكي ِ جاع ِة يف الش َثل ّ ِ
ول م َ جاع ٍة يف امل ْرِء تُغين كل َش َ و ّ
َ
السقي ِ
ّ وآفَهتُهُ ِم َن ال َف ُْ ِِ صحيحاً ب ْقولً َ وكِ من عائِ ٍ
ْ
والعُُز ِوم عمى قَ َد ِر ال َقَرائِ ِح ِ
تأخ ُذ اآلذا ُن مْنهُ ُ
وِ
لك ْن
للمتنبّي
232
الفصل السابع شصر:
مق ّدمة:
ح ّتى هذه اللحظة ك ّل البرامج التً كتبناها كانت من نمط البرمجة الهٌكل ٌّة أي أنّ البرنامج له مسار مح ّدد ال
ٌمكن أن ٌتغ ٌّر ,وٌواجه المبرمجون مشاكل عدٌدة فً هذا النمط من البرمجة حٌث تصبح عمل ٌّة تت ُّبع األخطاء و
التعدٌل على البرنامج صعبة ج ّدا ح ّتى مع استخدام التوابع ففً البرامج الكبٌرة والتً ٌعمل على إنجازها
عشرات المبرمجٌن سٌكون من الصعب تقسٌم العمل بحٌث نضمن فصبل تامّا لما سٌقوم به ك ّل مبرمج لذلك ت ّم
تصمٌم هذا المبدأ الجدٌد لٌح ّل مح ّل سابقه وقد اع َت َم َد هذا المبدأ على التفكٌر بالبرامج على أ ّنها مجموعة من
الكابنات تربط بٌنها عبلقات منطقٌّة معٌّنة تماما كما ٌحدث فً حٌاتنا الٌومٌّة.
ما هً الكائنات؟ الكابنات هً األشٌاء! .أجل انظر من حولك فك ّل األشٌاء التً تراها هً كابنات ,وك ّل الكابنات
التً تصادفها تمتلك صفات خاصة بها تمٌزها عن غٌرها وقد تمتلك بعض الصفات المشتركة مع كابنات
أخرى .لنؤخذ المثال التالً:
إنّ ك ّل مربع من هذه المربعات هو عبارة عن صفّ مستق ٍّل بح ّد ذاته عن اآلخرٌن فً الصفات الخاصّة به
)كاالسم والطول ولون البشرة (...وهو ٌشبه البقٌّة فً صفاته العامّة األخرى )كل األحٌاء تتنفّس وتؤكل وتنتقل
وتتكاثر .(...وقٌاسا على ذلك ٌمكننا أن نحوّ ل كل األشٌاء التً من حولنا إلى صفوف ونقو َم ببرمجتها لتإدّي
الوظابف المطلوبة منها ولتسهٌل هذه العملٌّة سنقوم بكتابة الشٌفرة )التً تحتوي على بٌانات وصفات هذا
الصفّ ( ث ّم نستطٌع أن ننشؤ كابنات عدٌدة من هذا الصفّ الذي ّ
ٌمثل مرجعا لك ّل الكابنات من نوعه ومثال ذلك
ك ٌّل من الج ّد واألب واالبن فً مثالنا السابق هً صفوف مستقلّة لكنّ عصام وخالد هما كابنٌن من صفّ االبن
وكل كابن منهما ٌختلف عن الكابن اآلخر فً بعض الصفات.
صةّ الخا بٌاناته متلك ٌ صفّال هذا من نسخة فهو الخبلصة إنّ الصفّ ّ
ٌمثل المرجع العام للنوع .أ ّما الكابن
والمختلفة عن باقً الكابنات المنشؤة من هذا النوع.
233
صف :هو طرٌقة منطق ٌّة لترتٌب البٌانات والتوابع فً بنٌة واحدة.
ال ّ
ٌصرّ ح عن الصفّ باستخدام الكلمة المحجوزة classوالتً تقابل من الناحٌة الوظٌف ٌّة الكلمة المحجوزة struct
فً لغة Cمع قدرتها على احتواء التوابع كؤعضاء ,بدال من احتوابها على بٌانات فقط كما فً structوٌكمننا
القول" :إنّ structهو نوع خاص من الصفوف".
{ class class_name
;member0
permission_label_1:
;member1
permission_label_2:
;member2
...
;} object_name
:classهً كلمة محجوزة ُتستخدم للتصرٌح عن صفّ جدٌد.
ٍّ
مشتق :object_nameاسم الكابن ال ُمشتق من الصفّ وهو اختٌاري ,و ٌمكن أن ٌكون هناك أكثر من كابن
عندها نفصل بٌن أسمابها بفاصلة عاد ٌّة تماما كما فعلنا فً .struct
جسم الصفّ ٌمكن أن ٌحتوي على أعضاء واألعضاء إمّا أن تكون تصرٌحات عن بٌانات )متغٌّرات( أو عن
توابع ,وهناك مستوى الوصول )السماح( وهو اختٌاريّ وٌكون إحدى الكلمات المحجوزة الثبلث التالٌة:
وصول مع ٌّ ٍن وهً تختلف عن
ٍ private, public, protectdوالتً توضع قبل األعضاء إلكسابها مستوى
بعضها كما سنب ٌّن فً الفقرة التالٌة.
: privateاألعضاء من هذا النوع فً صفّ ما ٌمكن الوصول إلٌها فقط من أعضاء الصفّ نفسه أو
من أي صفّ من النوع friendالذي ٌمكن ألعضابه أن ٌصِ لوا إلٌها )األعضاء .(private
: protectedاألعضاء من هذا النوع فً صفّ ما ٌمكن الوصول إلٌها من الصفّ نفسه أو من أيّ
صفّ من النوع friendوكذلك من أعضاء الصفوف التً ٌت ّم اشتقاقها من هذا الصفّ .
: publicاألعضاء فً هذا المستوى ٌمكن الوصول إلٌها من أيّ مكان ٌظهر فٌه الصفّ الذي
ٌحوٌها.
مالحظة :لو صرّ حنا عن أعضاء فً صفّ ما قبل أن نضع أيّ معرّ ف وصول فإنّ هذه األعضاء
س ُتعتبر من المستوى privateأل ّنه ٌعتبر مستوى الوصول االفتراضً لؤلعضاء التً ٌُصرّ ح
آخر.
عنها فً أيّ صفّ ما لم نحدّد لها مستوى َ
234
مثال:
{ class CRectangle
;int x, y
public:
;)void set_values (int,int
;)int area (void
;} rect
فً هذا المثال قمنا بالتصرٌح عن صفّ )نوع( أسمٌناه CRectangleث ّم أنشؤنا منه كابنا دعوناه .rectهذا
الصفّ ٌحتوي أربعة أعضاء ,متغٌّرٌن ) (x, yمن النوع intوهما من المستوى privateأل ّنه المستوى
وصول كما قلنا ,و ٌحتوي أٌضا على تابعٌن )(set_values
ٍ االفتراضً لؤلعضاء إن لم نح ِّدد لها أيّ مستوى
و )( areaفً المستوى , publicو قد صرّ حنا عنهما بالشكل prototypeكما تبلحظ.
المشتق منه ,فً المثال السابق اسم الصفّ هو Crectangleالذي ّ الحظ الفرق بٌن اسم الصفّ و اسم الكابن
ٌمثل اسم النوع الجدٌد الذي عر ّفناه ,بٌنما اسم الكابن هو rectوهو من نوع الصفّ )أل ّنه اش ُت َّق منه(ٌ .مكن
توضٌح هذه المسؤلة من خبلل المثال التالً:
; )rect.set_value(3,4
;)(myarea = rect.area
لكن ال ٌمكننا أن نفعل ذلك مع العضوٌن x, yأل ّنهما من المستوى الخاص ) (privateأي أ ّنه ال ٌمكن الوصول
إلٌهما ّإال من داخل الصفّ CRectangleالذي ُعرِّ فا داخله .إلٌك اآلن المثال كامبل:
235
الشًء الجدٌد فً هذا المثال هو معامل المدى ::الذي ظهر فً تعرٌف التابع )( set_valuesحٌث اس ُتخدِم
من أجل التصرٌح عن العضو )( set_valuesخارج الصفّ الذي عُرِّ ف فٌه.
الحظ أ ّننا قمنا بكتابة جسم )سلوك( التابع العضو )( areaداخل الصفّ CRectangleفً حٌن صرّ حنا عن
التابع )( set_valuesبالتعرٌف المبدبً للتوابع prototypeكً نستطٌع كتابة جسمه خارج الصفّ .فً هذه
عضو ما خارج الصفّ الذي ٌحوٌه ٌجب علٌنا أن نستخدم
ٍ تابع
الحالة عندما نرغب بكتابة جسم )سلوك( ٍ
المعامل .::
الفرق الوحٌد بٌن أن تقو َم بكتابة التابع العضو داخل الصفّ بشكل كامل ّ
وأال تفع َل ذلك هو أنّ المترجم فً الحالة
األولى سٌعتبر التابع من النوع inlineبشكل تلقابً .أمّا فً الحالة الثانٌة )التعرٌف المبدبً( فإنّ المترجم
سٌعتبر التابع من النوع الطبٌعً .not-inline
class Account
{
private:
;double balance
public:
} ;Account(double initial_balance) { balance = initial_balance
;)(double getBalance
;) double deposit( double amount
;) double withdraw( double amount
;}
236
التابع Accountوالذي ٌدعى مشٌّدا )انظر الفقرة القادمة( فً هذا المثال هو تابع من النوع inlineأمّا التوابع
األخرى مثل )( GetBalance(), Deposite(), Withdrawفهً من النوع الطبٌعً ّ not-inlineإال أ ّنه
ٌمكننا أن نحولها إلى توابع من النوع inlineبالشكل التالً :
)(inline double Account::getBalance
{
;return balance
}
إنّ التصرٌح عن التوابع على أ ّنها من النوع ٌ inlineجعلها تعمل بؤسلوب مختلف فبدال من استدعابها مثل
التوابع العادٌة ٌت ّم نسخ جسم التابع مرّ ة لكل استدعاء وٌن ّفذ كما لو كان جزءا من الشٌفرة التً اس ُتدعً فٌها.
ربّما تسؤل نفسك لماذا جعلنا العضوٌن x, yمن المستوى الخاص private؟ )تذ ّكر أ ّنه إذا لم نحدد مستوى
الوصول لؤلعضاء فهً من المستوى .(privateالجواب أل ّننا عرّ فنا تابعا )( set_valuesلٌقوم بقراءة قٌمِهما
فً محاولة لحماٌتهما من استقبال قٌم خاطبة )نستطٌع أن نكتب شٌفرة داخل التابع للتحقق من صحة البٌانات المدخلة( ولذا
فلٌس من حاجة لجعل البرنامج قادرا على التعامل معهما مباشرة .ربّما فً البرامج الصغٌرة والبسٌطة كالمثال
السابق لن تجد منفعة كبٌرة من ذلك ,ولكن فً المشارٌع الضخمة قد ٌكون من الضروري جدا أن تبقى قٌم
المتغٌّرات بعٌدة عن التحوٌر أو التغٌٌر)قد ٌنتج التغٌٌر عن خطؤ غٌر متوقع أثناء كتابة الشٌفرة .انظر فقرة التغلٌف
.(encapsulation
من أه ّم مٌزات الصفوف أ ّنه ٌمكننا أن نصرّ ح عن العدٌد من الكابنات منها .فً المثال السابق كان بإمكاننا أن
نصرِّ ح عن الكابن )المتغٌّر( rectbباإلضافة إلى الكابن .rect
237
{ )( int main
;CRectangle rect, rectb
;)rect.set_values (3,4
;)rectb.set_values (5,6
;cout << "rect area: " << rect.area() << endl
;cout << "rectb area: " << rectb.area() << endl
}
الحظ أنّ االستدعاء )( rect.areaال ٌعطً نفس نتٌجة االستدعاء )(.rectb.area
وذلك ألنّ كل كابن ٌُ ْش َت ٌّق من الصفّ ٌ CRectangleمتلك أعضاء الصفّ كلها من جدٌد .أي أنّ كل كابن منهما
صٌن به ,وتابعٌن )( set_value() , areaخاصٌن به أٌضا. ٌحتوي على متغٌّرٌن x, yخا ّ
من هنا نشؤت فكرة الكابنات والبرمجة كابنٌّة التوجّ ه .حٌث ُتعتبر البٌانات والتوابع خصابص )صفات( للكابن.
سنناقش فً فقرات قادمة مٌزات هذا األسلوب.
فً حالتنا السابقة الصفّ )نوع البٌانات للكابنات المشت ّقة منه( هو CRectangleحٌث أنشؤنا منه نسختٌن أو
كابنٌن هما rect , rectbوك ّل منهما له أعضاإه الخاصة )صفاته من متغٌّرات و توابع(.
-2اكتب ص ّفا جدٌدا اسمه Circleبحٌث ٌحتوي على األعضاء التالٌة :
متغٌّر نصف القطر .r
تابع لقراءة نصف القطر )(. set_radius
. 𝜋 تابع لحساب مساحة الدبرة calc_spaceحٌث أنّ المساحة هً
. 𝜋 تابع حساب محٌط الدابرة calc_perimeterحٌث أن المحٌط هو
ث ّم استخدمه فً برنامجك حٌث ٌدخل المستخدم نصف القطر و ٌطبع البرنامج المساحة و المحٌط.
238
المش ٌّدات Constructors
تحتوي الصفوف على تابع خاصّ ٌدعى المشٌّد constructorالذي ٌص ّرح عنه على أ ّنه تاب ٌع عضو فً الصفّ
مرة واحدة فقط وبشكل تلقائً عندما تقوم بإنشاء (اشتقاق) وهو ٌؤخذ نفس اسم الصفّ ٌ .ت ّم استدعاء المش ٌّد ّ
الصف وهو أوّ ل تابع ٌت ّم تنفٌذه فً الكابن.
ّ نسخة (كائن) جدٌدة من
كامل
ٍ بشكل
ٍ تحتاج الكابنات عموما إلى تبدبة متغٌّراتها أو حجز ذاكرة دٌنامٌكٌة أثناء عمل ٌّات بنابها لتصبح فعّالة
ولنتج ّنب القٌم غٌر المتو ّقعة أو العشوابٌّة ألعضابها خبلل فترة تنفٌذ الكابن والناتجة عن عدم ِ
فعل ذلك )التبدبة(.
مثال :ماذا سٌحدث فً المثال السابق لو أ ّننا استدعٌنا التابع )( areaقبل أن نستدعً التابع )(set_values؟
قد تكون النتٌجة غٌر معروفة )عشوابٌة( ألنّ المتغٌّرٌّن x, yلم ٌُسْ ند إلٌهما أٌّة قٌم ,وفً محاولة للتخلّص من
هذه المشكلة سنكتب الصفّ CRectangleوسنضٌف إلٌه مشٌّدا constructor
// classes example rect area: 12
>#include <iostream rectb area: 30
;using namespace std
{ class CRectangle
;int width, height
public:
CRectangle (int,int); //Constructor
};)int area (void) {return (width*height
;}
{ )CRectangle::CRectangle (int a, int b
;width = a
;height = b
}
{ )( int main
CRectangle rect (3,4); //try to remove (3,4) & run
;)CRectangle rectb (5,6
;cout << "rect area: " << rect.area() << endl
;cout << "rectb area: " << rectb.area() << endl
}
كما ترى نتٌجة هذا المثال هً نفس نتٌجة المثال السابق .حٌث قمنا باستبدال التابع )(- set_valuesالذي لم
ٌعد موجودا -بالتابع المشٌّد .constructor
الحظ كٌف مرّ رنا وسٌطٌن إلى المشٌّد فً نفس اللحظة التً أنشؤنا فٌها نسخة من الصفّ .كاآلتً:
ٌجب أن تضع هذا فً حسبانك دابما المشٌّد الٌعٌد قٌمة ولٌس من النوع .void
أضف مشٌّد ا إلى التمرٌن السابق بحٌث ٌمكنه أن ٌقرأ نصف القطر كوسٌط مباشرة دون الحاجة إلى التابع
.set_radius
239
الهادمات Destructors
مرة واحد اة عندماالهادم :هو تابع له وظٌفة تعاكس بشكل كامل وظٌفة المشٌّد حٌث ٌت ّم استدعاؤه بشكل تلقائً ّ
ٌتحرر الكائن من الذاكرة )إمّا أل ّنه أنهى كل تعلٌماته كؤن نعرِّ ف كابنا على أ ّنه متغٌّر موضعً ضمن تابع ما و ٌنهً التابع
ّ
تعلٌماته ,أو أل ّنه كابن ت ّم إسناد القٌم المطلوبة إلٌه ث ّم ت ّم تحرٌره من الذاكرة باستعمال معامل الحذف .( delet
الهادم ٌجب أن ٌؤخذ نفس اسم الصفّ مسبوقا بالرمز ~ كما وٌجب ّأال ٌعٌد الهادم قٌمة.
ٌستخدم الهادم عادة لتحرٌر الذاكرة -التً ٌحجزها الكابن أثناء تنفٌذه -فً اللحظة التً ٌنهً فٌها الكابن عمله.
{ class CRectangle
;int *width, *height
public:
;)CRectangle (int,int
;)( ~CRectangle
};)int area (void) {return (*width * *height
;}
{ )CRectangle::CRectangle (int a, int b
;width = new int
;height = new int
;*width = a
;*height = b
}
{ )( CRectangle::~CRectangle
;delete width
;delete height
}
{ )( int main
;)CRectangle rect (3,4), rectb (5,6
;cout << "rect area: " << rect.area() << endl
;cout << "rectb area: " << rectb.area() << endl
;return 0
}
23:
بما أنّ الصفّ السابق ال ٌمتلك مشٌّدا فإنّ المترجم سٌفترض أنّ هناك مشٌّدٌن افتراضٌٌن هما:
المش ٌّد العادي :وهو مشٌّد ال ٌمتلك وسطاء وٌُعْ َرفُ بـ ) nop (no parametersوهو ال ٌفعل أي شًء عادة.
;} { )( CExample::CExample
المش ٌّد النسخة ٌ :حتوي على وسٌط من نوع الصفّ ممرّ ر بالمرجع ,وهو ٌقوم بنسخ قٌم المتغٌّرات األعضاء
غٌر الثابتة non-staticمن الكابن الوسٌط وٌسندها إلى المتغٌّرات األعضاء المقابلة لها ) (non-staticفً
ّ
المشتق من صفّ من النوع non-staticأٌضا. الكابن a
{ )( int main
;)CRectangle rect (3,4
;CRectangle rectb
;cout << "rect area: " << rect.area() << endl
;cout << "rectb area: " << rectb.area() << endl
}
فً هذه الحالة الكابن rectbصُرِّ ح عنه بدون وسطاء ,لذلك فقد تمّت تبدبة متغٌّراته باستخدام المشٌّد العادي
nopوالذي ٌسند القٌمة 6إلى ك ّل من المتغٌّرٌن widthو height
مالحظة :إذا أردنا أن ننشؤ كابنا جدٌدا من صفّ ما واستخدامنا المشٌّد العادي فعلٌنا أن نذكر اسم
الصفّ و بعده اسم الكابن الجدٌد دون أن نضع أقواسا من الشكل )( .أمّا إذا كان فً صفّ ما
مشٌّد ات غٌر المشٌّد العادي ) (nopالذي ال ٌمتلك وسطاء لتمرّ ر إلٌه وأردنا استخدام أحدها
عندها ٌجب علٌنا أن نذكر القوسٌن )( بعد اسم الكابن الجدٌد وبداخلهما الوسطاء المطلوبة.
241
مثال :فً المثال السابق:
رظش٠ؼ طؾ١ؼ ألّٕٔب اعزخذِٕب اٌّشّ١ذ اٌؼبدCRectangle rectb; // ٞ
رظش٠ؼ خبؽئ! ّ
ألْ اٌّشّ١ذ اٌؼبد ٞل ٠ؾزبط ئٌ ٝاٌمٛعCRectangle rectb(); // )( ٓ١
-2فً التمرٌن ) 1الصفّ (Circleالذي أضفت إلٌه مشٌّد ا لقراءة نصف القطر هل العبارة التالٌة
صحٌحة :
; Circle circle
-3فً التمرٌن ) 3الصفّ (Pointأضف مشٌّد ٌن األول هو مشٌّد ٌقبل وسٌطٌن من خبلله تصبح قادرا
على أن تسند قٌمتً المتغٌّرٌن , x , yو المشٌّد العادي.
-4تؤمّل البرنامج التالً:
>#include<iostream
;using namespace std
)(int main
{
;"cout<<"Sweat plus sacrifice equals success.
;return 0
}
اجعل البرنامج ٌطبع الشكل التالً:10
Give the world the best you have, and the best will come to you.
Sweat plus sacrifice equals success.
If man hasn’t discovered that he will die for, he isn’t fit to live.
)تذكر أنّ المتغٌّرات الشاملة تت ّم تبدبتها فً بداٌة البرنامج قبل التابع mainو ٌت ّم هدمها بعد التابع .( main
10
العبارة األولى لـ Madeline Bridgeوالثانٌة لـ , Charles O. Finleyوالثالثة لـ Martin Luther King, JR
242
المؤ ّ
شرات على الصفوف Pointers to classes
بشكل حقٌقًٍ ,ولفعل ذلك علٌنا ببساطة أن ُنعرِّ ف مإ ّ
شرا على كابن ٍ شرا لٌشٌر على صفّ ما ٌمكننا أن ننشا مإ ّ
من نوع الصفّ كما ٌلً:
;CRectangle * prect
شرا على كابن من النوع ,CRectangleولكً نشٌر بشكل مباشر إلى عضو ما من شر السابق مإ ٌّمثل المإ ّ
ضح بعض العبارات الممكنة. أعضاء هذا الكابن ٌنبغً أن نستخدم المعامل > -والمثال التالً ٌو ّ
{ )( int main
;CRectangle a, *b, *c
;]CRectangle * d = new CRectangle[2
;b= new CRectangle
;c= &a
;)a.set_values (1,2
;)b->set_values (3,4
;)d->set_values (5,6
;)d[1].set_values (7,8
;cout << "a area: " << a.area() << endl
;cout << "*b area: " << b->area() << endl
;cout << "*c area: " << c->area() << endl
;cout << "d[0] area: " << d[0].area() << endl
;cout << "d[1] area: " << d[1].area() << endl
;return 0
}
رأ ّوذ ِٓ أّٔه رّ ّىٕذ ِٓ ف ُٙوً ٘زٖ اٌؼٍّ١بد ثشىً ربَٚ ,ئرا وبْ ٌذ٠ه أّ٠خ شىٛن ؽٌٙٛب فٕٕظؾه ثمشاءح فظٍٟ
ّ
ٚاٌغغالد .struct اٌّإ ّششاد pointers
243
الكلمة المفتاحٌة this
اٌظف اٌزُٕ٠ ٞفّز ؽبٌ١بً ٟ٘ٚ .رّضًّ ِإ ّششاً
ّ ّ
اٌظف رش١ش ئٌ ٝاٌؼٕٛاْ ف ٟاٌزاوشح ٌٍىبئٓ ِٓ ٘زا ٘زٖ اٌىٍّخ داخً
لّ١زٗ دائّب ً ػٕٛاْ ٘زا اٌىبئٓ.
ّ
طف ئرا ٌُ ٔمُ ٔؾٓ ثاػبدح رؾّ ً١اٌّؼبًِ = ٘ٚزٖ اٌش١فشح ٘ ٟاٌش١فشح الفزشاػ١خ ٌٍّؼبًِ = ِٓ أعً أٞ
ٚرغ١١ش اٌش١فشح.
مالحظت :األػؼبء ِٓ إٌٛع staticل ّ٠ىٓ أْ ٔش١ش ئٌٙ١ب ثبٌّإ ّشش .this
فاْ ػٕٛاْ اٌىبئٓ ّ ّ٠شس وٛع١ؾ خف ٟئٌ٘ ٝزا اٌؼؼٛ ػٕذِب ُ٠غزذػ ٝػؼِ ٛب ١ٌ -ظ ِٓ إٌٛع ِٓ -staticوبئٓ ّ
وّب :ٍٟ٠
;) myDate.setMonth( 3
ٚاٌز٠ ٞؼٕ: ٟ
;) setMonth( &myDate, 3
اٌزؼج١ش (٠ )*thisغزخذَ ػبدح ِٓ أعً ئػبدح اٌىبئٓ اٌؾبٌ ٟومّ١خ ٌٍزبثغ اٌؼؼ ٛوّب فؼٍٕب عبثمبً.
244
.ّخ٠ اٌمذC++ ٔغخٟدح فٛعِٛ غذ١ٌ this اٌىٍّخ:مالحظت
: this َػؼ اٌطشق اٌّّىٕخ لعزخذاٛ٠ ِضبي
// Example of the this pointer
class Date{itn month ; void setMonth(int);}
void Date::setMonth( int mn )
{
month = mn; // ٘زٖ اٌؼجبساد اٌضالس ِزىبفئخ
this->month = mn;
(*this).month = mn;
}
: ٌٟٕب اٌّضبي اٌزب٠ٌٕفزشع أْ ٌذ
// this keyword example -858993460
#include <iostream>
using namespace std;
class Example
{
int x;
public:
void setX(int x){ x = x; }
void printX(){cout<< x << endl; }
};
int main()
{
Example ex ;
ex.setX(5);
ex.printX();
return 0;
}
x ّٛش اٌؼؼ١ّخ اٌّزغ١ لٟ٘ ًطجغ ٘زا اٌجشٔبِظ قٍمتً عشىائٍّت١مخ األِش ع١ ؽمٟما هً وتٍجت هزا انبروامج ؟ ف
ّش١ّخ اٌّزغ١ ؟ ٘زا اٌزبثغ لبَ ثاعٕبد لset_x(int x) نكه كٍف؟ و مانزي فعهه انتابعٚ .ّخ١ّخ ل٠ٗ أ١ٌ ٌُ رُغٕذ ئٞاٌز
ّ اٌّشىٍخ ٌزٌهٟ٘ ٖؾ؟ ٘ز١عٌّٛش ا١ اٌّزغٛ٘ ّبّٙ٠أٚ ّٛش اٌؼؼ١ اٌّزغٛ٘ ٓ٠ّش١ اٌّزغٞ
ْفا ّ ٌىٓ أx ّش١ اٌّزغٌٝ ئx
ّ
طجغ اٌزبثغ١ّزٗ عشىائٍّت ٌزٌه ع١ثّب أْ لٚ ٗ ٔفغٌٝ ئx ّٛشاٌؼؼ١ّخ اٌّزغ١ ئعٕبد لٟ٘ ّخ١ٍؼزجش ٘زٖ اٌزؼ٠ ُاٌّزشع
:ٌٟ اٌّضبي اٌزبٟ نكه ما هى انحم؟ سالت اٌفشق ف.ّخ١ائٛ اٌؼشx ّٛش اٌؼؼ١ّخ اٌّزغ١ لprint
// this keyword example 5
#include <iostream>
using namespace std;
class Example
{
int x ;
public:
void set_x(int x) { this->x = x; }
void printX(){cout<< x << endl ;}
};
int main()
{
Example ex ;
ex.set_x(5);
ex.printX();
return 0;
}
245
انصفىف انمع ّرفت باستخذاو انكهمت انمحجىزة struct
اٌظف ِ classبػذا ّ
أْ أػؼبء اٌغغً رىِٓ ْٛ ّ ٚعّؼذ ِ C++ف َٛٙاٌىٍّخ اٌّؾغٛصح structئٌِ ٝفَٛٙ
ّ
اٌظف. اٌّغز public ٜٛثشىً افزشاػ ٟثذلً ِٓ أْ رى ِٓ ْٛاٌّغز private ٜٛوّب فٟ
اٌظف ٚاٌغغً ٌّٙب ٔفظ اٌٛظبئف رمش٠جب ً فٌ , C++ ٟىٓ ٠ structغزخذَ ػبدح ِٓ أعً
ّ ػٍ ٝأ٠خ ؽبي وًٌّ ِٓ
اٌج١بٔبد فمؾ أ ِّب classف ٟٙرغزخذَ ِٓ أعً اٌظفٛف اٌز ٟرؾز ٞٛػٍ ٝأػؼبء ِٓ اٌج١بٔبد ٚاٌزٛاثغ ٚ
اإلعشاءاد.
أربؽذ ٌٕب C++اٌخ١بس ف ٟاعزخذاَ ِؼبِالرٙب اٌم١بع١خ ث ٓ١اٌظفٛف اٌز ٟرٕشئٙب أٔذ ثبإلػبفخ ئٌ ٝئِىبّٔ١خ
اعزخذاِٙب ث ٓ١األٔٛاع األعبع١خِ .ضبي:
;int a, b, c
;a = b + c
ّ٠ىٕه ثبٌزأو١ذ اعزخذاَ ِؼبًِ اٌغّغ +ثِ ٓ١زغّ١ش( ٓ٠وبئٕ ِٓ )ٓ١إٌٛع األعبعٌ ٚ .int ٟىٓ ِبرا ػٓ اٌّضبي
اٌزبٌ:ٟ
ّئل إّٔٔب ّٔ ٛد ٕ٘ب أْ ٔم ّذَ اٌشىش ئٌ C++ ٝألّٔٙب رّ ّىٕٕب ِٓ ئػبدح رؾِّ ً١ؼبِالرٙب اٌم١بع١خ األِش اٌز٠ ٞغؼٍٕب
لبدس َٓ٠ػٍ ٝأْ ٔىزت اٌّضبي اٌغبثك ,فبٌىبئٕبد اٌّشزمّخ ِٓ أٔٛاع ِش ّوجخ وّب ف ٟاٌّضبي اٌغبثك رغزط١غ أْ رمجً
اٌّؼبِالد ثؼذ ئػبدح رؾٍّٙ١ب ,وّب عٕى ْٛلبدس ٓ٠ثزٌه ػٍ ٝأْ ٔغّ١ش ف ٟآٌ١خ ػًّ اٌّؼبِالد.
+ - * / = < > =+ =- =* =/ << >> =<<
=>> == =! =< => ++ -- % & ^ ! ~ | =&
=^ =| && || =% ][ )( new delete
246
:خ١ٌ ارّجبع اٌمبػذح اٌزبٌٝبَ ثزٌه ٔؾزبط فمؾ ئ١كٍف وقىو بعمم إعادة انتحمٍم عهى انمعامالث؟ ٌٍم
كما ٌمكننا أن نقوم بكتابة التابع بشكله العادي مباشرة داخلprototype ًوكما تبلحظ فقد التعرٌف المبدب
. ّالصف
:ً رأخز اٌشىٟاٌزٚ ّخ اٌجؼذ١ذاً ِٓ أعً األشؼّخ صٕبئ٠ذ أْ ٔىزت طفّب ً عذ٠و اآلن لنقل إ ّننا ٔش
اٌمبػذحٌٝٓ ئ١خؼغ عّغ شؼبػ٠ ش١ ؽ.ٓ١َ ثغّغ شؼبػٛم١ٌ + ًِ اٌّؼبًٍٝ صائذ ػ١َّ ثؼًّ رؾٛذ أْ ٔم٠ ٔشٚ
⃗ ⃗⃗⃗ ⃗ ⃗ ⃗⃗⃗ ⃗ :خ١ٌاٌزب
: ّحٍث أن
ّ
CVector ٌٍظف ّذ١ اعُ اٌزبثغ اٌّش: CVector (int, int);
ٟبػ٠ اٌّؼبًِ اٌشًٍٝ ػ١َّ ثاػبدح اٌزؾٛم٠ ٞ ربثغ ِؼبًِ اٌغّغ اٌز: CVector operator+ (CVector);
.CVector عٌٕٛذ ا١ؼ٠ ٛ٘ ٚ +
247
ّ٠ىٓ أْ ٔم َٛثبعزذػبء ٘زا اٌزبثغ ثأؽذ اٌشىٍ ٓ١اٌزبٌ:ٓ١١
;c = a + b
أٚ
;)c = a.operator+ (b
لؽع أ٠ؼب ً إٔٔب أػفٕب اٌّشّ١ذ اٌؼبد٠ CVector(){ }; ٞؼ ّذ ٘زا أِشاً ػشٚس٠ب ً ع ّذاً ألّٕٔب لّٕب ثزؼش٠ف اٌّشّ١ذ
;)ِ CVector(int, intب ٠ؼٕ ٟأّٔٗ ٌٓ ٠ىٕ٘ ْٛبن أّ٠ب ً ِٓ اٌّشّ١ذ ٓ٠الفزشاػ( ٓ١١ساعغ فمشح اٌّشّ١ذ اد ف ٟاٌذسط اٌغبثك)
ِّىٓ
ٍ أْ اٌزظش٠ؼ اٌزبٌ CVecotr c; ٟغ١ش ٌٚزٌه لثّذ ٌٕب ِٓ ئػبفزٗ ثأٔفغٕب ؽزّ٠ ٝؼًّ اٌجشٔبِظ ,فؼذَ ئػبفزٗ رؼّٕ ٟ
داخً اٌزبثغ )( mainأ ٚغ١شٖ( .ثّٕ١ب ٠ى ْٛاٌزظش٠ؾبْ ا٢خشاْ ِّىٕ ٓ١ثغجت ٚعٛد ِشّ١ذ ٠أخز ٚع١ط)ٓ١
ػٍ ٝأّ٠خ ؽبي ٠ ,غت ػٍ ّ ٟأْ أُػٍِّه أّٔٗ ِٓ األفؼً ػذَ رشن اٌّشّ١ذ اٌؼبد ٞأ nop Constructor ٚثذ ْٚرؼٍّ١بد ألّٔٗ
ٞوب٢ر: ٟٚوّب فِ ٟضبٌٕب ٌ ٛإّٔٔب طشؽٕب ػٓ وبئٓ ِب ثبعزخذاَ اٌّشّ١ذ اٌؼبد ّ
;CVector c
فاْ ل ٌٓ x, y ُ١رىِ ْٛؼشٚفخ (ػشٛائ١خ)ٚ ,ثبٌزبٌ٠ ٟفؼًّ أْ ٔم َٛثٛػغ ثؼغ اٌزؼٍّ١بد اٌز ٟرغبػذٔب ػٍ ٝاٌزؾىُّ
ثبألػؼبء ٚرجذئزٙب .وّب :ٍٟ٠
أْ اٌظفٛف رؾز ٞٛثشىً افزشاػ ٟػٍِ ٝشّ١ذ( ٓ٠وّب ِش ِؼٕب عبثمبً) ف ٟٙرؾز ٞٛأ٠ؼب ً ػٍ ٝرؼش٠ف وّب ّ
ّ
اٌظف .ؽ١ش ٠ؼٕ :ٟأِغخ وً األػؼبء غ١ش اٌضبثزخ(ِٓ )non-static ٌّؼبًِ اإلعٕبد = ث ٓ١وبئٕٔ ِٓ ٓ١فظ
اٌىبئٓ اٌز ٞػٍ ٓ١ّ٠ ٝاٌّؼبًِ ئٌِ ٝب ٠مبثٍٙب ِٓ أػؼبء اٌىبئٓ اٌز ٞػٍ٠ ٝغبسٖ.
ّ٠ ٚىٕه اٌزؾىُ ثزٌه ؽ١ش ّ٠ىٕه أْ رؾذد األػؼبء اٌز ٟرٛد ٔغخٙب.
ل رفشع ػٍ١ه ئػبدح رؾّ ً١اٌّؼبِالد أْ رغزخذِٙب ٚفمب ً ٌّؼٕ ً ٝػب ٍَّ أٌ ٚؼالل ٍخ س٠بػٍ ١خ ٚ ,ػٍ ٝاٌشغُ ِٓ رٌه
فاْ اعزخذاَ اٌّؼبِالد ٚفمب ً ٌٛظبئفٙب ٠ؼ ّذ أفؼً ,ئر ٌ١ظ ِٓ إٌّطم ٟأْ رؼ١ذ رؾّ ً١اٌّؼبًِ ١ٌ +م َٛثطشػ ّ
ِّىٓ ثشِغّ١بً.
ٌ ّ
وبئٕٔ ِٓ ٓ١فظ إٌٛع ػٍ ٝاٌشغُ ِٓ أْ ٘زا
فً تمرٌن الصفّ pointأعد تحمٌل معامل الجمع لٌقوم بجمع نقطتٌن .حٌث
248
األعضاء الثابتة من النوع static
ّ
اٌظف" ,ألٔٙب اٌظف ػٍ ٝأػؼبء ِٓ إٌٛع ٚ , staticاٌز ٟرُؼ َشف أ٠ؼب ً ثـ "ِزغّ١شاد ّ ّ٠ىٓ أْ ٠ؾزٞٛ
اٌّؾز ٜٛاٌز ٞل ٠ؼزّذ ػٍ ٝأ ٞوبئٓ ٟ٘ٚ .رّضً فمؾ لَِّ١ب ً فش٠ذح ِٛ ٚؽّذح ٌىً اٌىبئٕبد ِٓ ٔفظ إٌٛع.
وّضبي ,عٕم َٛثبٌزظش٠ؼ ػٓ ِزغّ١ش ِٓ إٌٛع ٌٕ staticغزخذِٗ ف ٟئؽظبء ػذد اٌىبئٕبد اٌز ٟع١زُ ئٔشبؤ٘ب
(٘ذِٙب) خالي اٌجشٔبِظ:
;cout<<a.n
;cout<< CDummy::n
249
:ً أوجد األخطاء فً البرنامج التال:
class Example
{
public:
Example ( int y = 10 )
: data( y )
{
// empty body
} // end Example constructor
private:
int data;
static int count;
}; // end class Example
24:
الفصل الثامن شصر:
وللقٌام بذلك فإ ّننا نمنع بٌانات الصفّ )متغٌّراته( من الظهور للمستخدم بشكل مباشر ونق ّدم له عوضا عن ذلك
توابع )أو ما ٌعرف فً لغات أخرى مثل javaو C#باسم الطرق (mehodsلتقوم بالتواصل مع بٌانات
الصفّ .لنفترض أن لدٌنا المثال التالً :
تستطٌع أن ترى أ ّننا تمك ّنا من الوصول إلى المتغٌّر ageفً الكابن my_personو تخزٌن القٌمة 12فٌه
مباشرة وهذه هً المشكلة تصوّ ر أنّ المستخدم أدخل رقما من خارج مجال األعداد الصحٌحة ماذا لو أدخل
المستخدم رمزا أو ح ّتى حرفا ؟ فً هذه الحالة سٌحدث خطؤ وقد ٌتسبب بتوقف البرنامج عن العملٌ .بدو مثل
هذا الخطؤ مستبعدا فً حالتنا ولك ّنه من المحتمل أن ٌحدث ومه ّمتك عزٌزي المبرمج أن تمنعه من أن ٌحدث.
ولكن كٌف ؟ ٌبدو هذا السإال ذكٌا واإلجابة علٌه ستكون سهلة ألنّ ما سنقوم به هو أ ّننا سنعمل تغلٌفا ألعضاء
هذا الصفّ بحٌث نمنع بٌاناته )متغٌّراته( من الظهور للمستخدم بشكل مباشر وسنقدّم له بدال من ذلك إحدى
الطرٌقتٌن التالٌتٌن:
251
: private للوصول إلى أعضاءpublic استخدام توابع-a
أضف المشٌّد التالً إلى البرنامج السابق )ال تنس أنّ المشٌّد العادي لن ٌكون موجودا بعدها: استخدام المش ٌّد ات-b
(ح ّتى تضٌفه بنفسك
Person(int p_age)
{ if (p_age > 100 || p_age < 1)
{ cout<< "you can't edit age like that";
m_age =1 ;
}
else
{ m_age = p_age;
cout<< "done";
}
}
252
قبل الحدٌث عن الوراثة لنتعرّ ف على التوابع الصدٌقة ألنها مهمّة لنا فً دراسة الوراثة
أْ ٕ٘بن صالصخ ِؼشّفبد ٚطٛي ٘ٚ private, public, protected :ٟلٍٕب ف ٟاٌؾبٌخ اٌز٠ ٟى ْٛفٙ١ب ػؼٛ ٔؼٍُ ّ
ّ
اٌظفٚ .ػٍ ٝاٌشّغُ ِٓ رٌه ِب ِٓ أؽذ اٌّغز private ٓ١٠ٛأ protected ٚفال ّ٠ىٓ اٌٛطٛي ئٌ ِٓ ٗ١خبسط
اٌظف ,ػٕذ٘ب ّ٠ىٓ اٌٛطٛي ئٌ٘ ٝزا ّ ّ٠ىٕه أْ رزؼ ّذ٘ ٜزٖ اٌمبػذح ثبعزخذاَ اٌىٍّخ اٌّؾغٛصح friendفٟ
ّ
اٌظف اٌظفٌٚ .فؼً رٌه ػٍ١ه فمؾ أْ رظشّػ ػٓ اٌؼؼ ٛاٌز ٞرش٠ذ اٌٛطٛي ئٌ ِٓ ٗ١خبسط ّ اٌؼؼ ِٓ ٛخبسط
ثبعزخذاَ اٌزؼش٠ف اٌّجذئ prototype ٟص ُّ رزوش ٘زٖ اٌىٍّخ أِبِِٗ .ضبي:
{ class CRectangle
;int width, height
public:
;)void set_values (int, int
};)int area (void) {return (width * height
;)friend CRectangle duplicate (CRectangle
;}
{ )( int main
;CRectangle rect, rectb
;)rect.set_values (2,3
;)rectb = duplicate (rect
;cout << rectb.area() << endl
}
من تعرٌف التابع duplicateنجد أنه من النوع friendفً الصفّ ,CRectangleما ٌجعلنا قادرٌن
على الوصول إلى المتغٌّرٌن widthو heightعلما أ ّنهما من المستوى privateوذلك من أي كابن
من النوع .CRectangle
الحظ أ ّننا لم نعتبر التابع duplicateعضوا من الصفّ CRectangleال فً التصرٌح عنه وال فً
االستخدام األخٌر فً التابع )( .mainكما ٌمكن له أن ٌؤخذ المستوى العام publicأو الخاص
privateفهذا لن ٌإثر على استخدامنا له.
ٌمكن استخدام التوابع من هذا النوع من أجل القٌام بعملٌات على ص ّفٌن من نوعٌن مختلفٌن .عموما هذا
االستخدام لٌس من مبادئ البرمجة كابنٌة التوجه OOPلذلك من األفضل استخدام أعضاء من ضمن الصفّ
فمثبل سٌكون من المفٌد )بغرض اختصار الشٌفرة( فً المثال السابق لو قمنا بكتابة التابع duplicateبشكل
كامل على أنه عضو من الصفّ .CRectangle
253
friend الصفوف من النوع
ً كصدٌق لصفّ آخر كما فعلنا فً التوابع من هذا النوع فfriend ٌمكننا أن نص ّرح عن صفّ من النوع
من الوصول إلى كا ّفة أعضاء الصفّ اآلخر ح ّتى التً منfriend الفقرة السابقة ممّا ٌم ّكن الصفّ الصدٌق
: مثال.protected أوprivate المستوى
// friend class 16
#include <iostream>
using namespace std;
class CSquare;
class CRectangle {
int width, height;
public:
int area (void)
{return (width * height);}
void convert (CSquare a);
};
class CSquare {
private:
int side;
public:
void set_side (int a)
{side=a;}
friend class CRectangle;
};
void CRectangle::convert (CSquare a) {
width = a.side;
height = a.side;
}
int main () {
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area() << endl;
return 0;
}
ّ لذلك فإنCSquare ّ للصفfriend على أ ّنه صدٌقCRectangle ّصرّ حنا فً هذا المثال عن الصف
.CSquare ّ ٌمكنه الوصول إلى كل أعضاء الصفCRectangle ّالصف
ما ٌعنً أنّ بإمكانه أنCSquare ّ للصفfriend صدٌقCRectangle ّفً حالتنا هذه اعتبرنا أن
أوprivate ح ّتى ولو كان من المستوىCSquare ٌّصل إلى أيّ عضو موجود فً الصف
صدٌقاSCquare ّممكن علما أ ّنه ال شًء ٌمنعنا من أن نجعل الصف
ٍ العكس غٌ ُر
َ ّ و لكنprotected
.CRectangle ّ للصفfriend
254
-2الوراثة بٌن الصفوف Inheritance between classes
آخر )أبٍ( حٌث
كابن َ ٍ تع ّد الوراثة ص ّفة مه ّمة من صفات الصفوف .فهً تسمح لنا بإنشاء كابنا )ابنا( مشت ّقا من
ٌصبح الكابنُ االبنُ حاوٌا على بعض صفات )خصابص( الكابن األبّ باإلضافة إلى صفاته األساسٌة) .الصفات
هً األعضاء العالمّة المعرّ فة فً الصفّ والتً تسمح بالتعامل معه( .لنؤخذ مثاال على ذلك:
لنفترض أ ّننا أردنا أن ننشا مجموعة من الصفوف تصف األشكال الهندس ٌّة ذوات األضبلع polygonsكالتً
أنشؤناها سابقا مثل CRectangleأو .CTriangleهذه األشكال تمتلك بعض الصفات األساس ٌّة المشتركة بٌنها
جمٌعا ,فك ٌّل هذه األشكال تمتلك قاعدة )عرض( وارتفاع.
لذلك سنقوم بالتصرٌح عن صفّ ٌحوي الصفات المشتركة )عرض و ارتفاع( لك ِّل األشكال المضلّعة وسنسمٌه
CPolygonحٌث أنّ كل شكل مضلّع ٌستطٌع أن ٌرث صفاته األساس ٌّة من الصفّ .CPolygonكما فً
الشكل:
الصفوف التً ُتش َت ّق من الصفوف األساسٌّة ترث جمٌع أعضابها الظاهرة .وهذا ٌعنً أ ّنه لو كان الصفّ
األساسًّ ٌمتلك عضوا Sولو صنعنا ص ّفا ّ جدٌدا فٌه العضو Bوٌرث الصفّ األساسًّ فإنّ الصفّ الجدٌد
سٌمتلك العضوٌن Sو Bمعا.
ا
وراثة بٌن ص ّفٌن؟ ٌت ّم ذلك باستخدام المعامل ) ( :الذي ٌُخبر المترجم بؤنّ الصفّ الذي كٌف ٌمكننا أن نجري
قبل )على ٌسار( هذا المعامل سٌرث الصفّ الذي بعده )على ٌمٌنه( .بالطرٌقة التالٌة:
255
{ class CTriangle: public CPolygon
public:
)int area (void
} ;){ return (width * height / 2
;}
{ )( int main
;CRectangle rect
;CTriangle trgl
;)rect.set_values (4,5
;)trgl.set_values (4,5
;cout << rect.area() << endl
;cout << trgl.area() << endl
;return 0
}
كبل من الص ّفٌن CRectangleو ٌ CTriangleحتوي على األعضاء كما ترى فإنّ ّ
)( width, height, set_valuesالموجودٌن أساسا فً الصفّ .CPolygon
نشتق )نرث( الصفوف من بعضها. ّ الكلمة protectedمشابهة للكلمة privateوالفرق الوحٌد ٌحدث عندما
نشتق )نرث( ص ّفا من صفّ ما آخر فإنّ األعضاء من النوع protectedالموجودة فً الصفّ األساسً ّ عندما
ٌمكن الوصول إلٌها من قبل أعضاء الصفّ الجدٌد بٌنما تلك التً من النوع privateفبل ٌمكن الوصول إلٌها
ّإال من خبلل الصفّ األساسًّ نفسه.
و ألننا نرٌد أن نتعامل مع ك ٍّل من العضوٌن width, heightمن خبلل الصفوف الجدٌدة المشت ّقة من الصفّ
CPolygonلذلك صرّ حنا عنهما على أ ّنهما من النوع .protected
فً مثالنا ,األعضاء الموروثة فً ك ّل من الص ّفٌن CTriangle, CRectangleتتبع نفس مستوٌات الوصول
فً الصفّ األساسً .CPolygon
256
أمّا استخدام الكلمة privateف ٌُعتبر األكثر انتشارا بعد الكلمة publicوذلك أل ّنها تإ ِّمن تغلٌفا كامبل ألعضاء
الصفّ األساسً حٌث ال ٌمكن الوصول إلى أعضاء الصفّ األساسً ّإال من داخله.
على ك ٍّل إذا لم تذكر معرّ ف الوصول بشكل صرٌح أثناء تعلٌمة الوراثة فإنّ المعرّ ف االفتراضً هو private
وذلك من أجل الصفوف المعرّ فة باستخدام الكلمة ,classأ ّما تلك المعرفة باستخدام الكلمة structفإنّ المعرّ ف
االفتراضً لها هو .public
صف األساسً؟ بحسب مبادئ الوراثة فإنّ ك ّل أعضاء الصفّ األساسً ما هً األشٌاء التً ٌت ّم وراثتها من ال ّ
ّ
)المشتق( ما عدا األعضاء التالٌة: ستورَّ ُ
ث إلى الصفّ االبن
;return 0
}
257
راقب الفرق بٌن المشٌّد من الصفّ األساسً الذي ت ّم استدعاإه عندما أنشؤنا الكابن xمن الصفّ daughterو
المشٌّد الذي ت ّم استدعاإه عندما أنشؤنا الكابن yمن الصفّ sonهذا الفرق سببه أ ّننا عرّ فنا المشٌّد فً الصفّ
daughterبالشكل التالً:
ٌمكنك فً C++أن تصنع ص ّفا ٌرث صفاته من أكثر من صفّ فً نفس الوقت وهذا ٌشبه تماما ما ٌحدث
لئلنسان فكلنا ٌعلم أنّ الصفات التً تكون فً المولود الصغٌر بعضُها قاد ٌم من األب و بعضُها اآلخر من األم أي
أ ّنه لو افترضنا أنّ لدٌنا ص ّفا ٌمثل المولود وآخر ّ
ٌمثل األب وثالث ٌمثل األم فإنّ بإمكان الصفّ المولود أن ٌرث
من األب واألم معا .تت ّم هذه العملٌة بؤن نضع فاصلة ) ( ,بٌن أسماء الصفوف التً نرٌد من الصفّ الجدٌد أن
ٌرثها كما ٌلً:
; class derived_class_name : public base_class_name1 , base_class_name2
مثال آخر ,لو عرّ فنا ص ّفا جدٌدا أسمٌناه COutputو أردنا من الص ّفٌن CTriangle, CRectangleأن ٌرثا
الصفات الموجودة فً هذ الصفّ باإلضافة إلى تلك التً ورثاها سابقا من الصفّ CPolygonفبإمكاننا أن نكتب
عندها :
{ class CRectangle : public CPolygon, public COutput
{ class CTriangle : public CPolygon, public COutput
إلٌك المثال كامبل:
258
void COutput::output (int i) {
cout << i << endl;
}
class CRectangle: public CPolygon, public
COutput {
public:
int area (void)
{ return (width * height); }
};
class CTriangle: public CPolygon, public
COutput {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
rect.set_values (4,5);
trgl.set_values (4,5);
rect.output (rect.area());
trgl.output (trgl.area());
return 0;
}
259
} ;){ return (width * height
;}
{ class CTriangle: public CPolygon
public:
)int area (void
} ;){ return (width * height / 2
;}
{ )( int main
;CRectangle rect
;CTriangle trgl
;CPolygon * ppoly1 = &rect
;CPolygon * ppoly2 = &trgl
;)ppoly1->set_values (4,5
;)ppoly2->set_values (4,5
;cout << rect.area() << endl
;cout << trgl.area() << endl
;return 0
}
شرٌن * ppoly1 , * ppoly2على كابنٌن من الصفّ .CPolygon فً التابع الربٌسً )( mainأنشؤنا مإ ّ
و أسندنا ألٌهما عنوانً الكابنٌن rect, trglوأل ّنهما كابنٌن من ص ّفٌن مشت ّقٌن من الصفّ األساسًّ CPolygon
شرات من نوع الصفّ األساسً لنشٌر بها على األعضاء فإنّ هذا اإلسناد ممكن .نستطٌع أن نستخدم المإ ّ
الموروثة فً الصفوف المشت ّقة منه فقط لذلك لم نقم باستخدامهما فً استدعاء التابع )( areaوقمنا باستدعابه
بالطرٌقة المعتادة.
إذن األعضاء من النوع virtualهً األعضاء المشتركة التً نرغب بؤن ترثها كل الصفوف المشتقة من
الصفّ األساسً والتً سنعٌد كتابة تعلٌماتها ) (overridingداخل بعض أو كل الصفوف التً ترث الصفّ
األساسً.
25:
;}
{ class CRectangle: public CPolygon
public:
)int area (void
} ;){ return (width * height
;}
{ class CTriangle: public CPolygon
public:
)int area (void
} ;){ return (width * height / 2
;}
{ )( int main
;CRectangle rect
;CTriangle trgl
;CPolygon poly
;CPolygon * ppoly1 = &rect
;CPolygon * ppoly2 = &trgl
;CPolygon * ppoly3 = &poly
;)ppoly1->set_values (4,5
;)ppoly2->set_values (4,5
;)ppoly3->set_values (4,5
;cout << ppoly1->area() << endl
;cout << ppoly2->area() << endl
;cout << ppoly3->area() << endl
;return 0
}
و اآلن جرّ ب أن تزٌل الكلمة المحجوزة virtualث ّم ش ّغل البرنامج ,ماذا ترى؟ النتٌجة ستكون 0فً الحاالت
الثبلث بدال من ,20, 10, 0ولكن لماذا؟ أل ّنك عندما أزلت الكلمة virtualمن أمام التصرٌح عن التابع
شرا من نوع هذا الصفّ لتشٌر إلى التابع )( areaفً ك ّل )( areaفً الصفّ CPolygonث ّم استخدمت مإ ّ
شر سٌشٌر إلى التابع فً الصفّ األساسً والذي ٌعٌد القٌمة ّ كما هو واضح من الكابنٌن rect , trglفإنّ المإ ّ
من تعرٌفه أمّا الكابن polyفهو أصبل من النوع CPolygonوالتابع المعرّ ف فٌه ٌعٌد 0دابما.
إنّ ما تفعله هذه الكلمة هو أ ّنها تسمح باستدعاء العضو من الصفّ المشتق والذي ٌمتلك نفس اسم العضو فً
الصفّ األساسً عندما ٌستخدم المإ ّ
شر ,كما فً المثال السابق.
شرات ففً هذه الحالة التابع )( areaهو أصبل من الصفات المشتركة ال ٌقتصر األمر فقط على استخدام المإ ّ
فً كل األشكال الهندسٌة المضلّعة المغلقة لذلك علٌنا أن نقوم بوضعه فً الصفّ األساسً CPolygonوألنّ
طرٌقة حساب مساحة كل شكل تختلف عن الطرق األخرى فإ ّننا نصرّ ح عن التابع )( areaفً الصفّ األساسًّ
على أ ّنه من النوع virtualث ّم نعٌد قٌادته فً الصفوف المشت ّقة.
ومثال ذلك لو افترضنا أنّ لدٌنا ص ّفا أساسٌّا للمركبات ث ّم اشت ّقٌنا منه ص ّفا للسٌارة وآخر للدراجة النارٌة ,معلو ٌم
أنّ ك ّل المركبات تستخدم الوقود لكً تسٌر لذلك سنعرّ ف التابع )( fuelفً الصفّ األساسً لٌحسب كمٌة الوقود
البلزمة لقطع مسافة معٌّنة لكن هل تستهلك السٌارة نفس الكمٌة من الوقود التً تستهلكها الدراجة لتقطعا
نفس المسافة؟ بالطبع ال و هذا االختبلف ٌجعل من األفضل أن نستخدم الكلمة virtualلنعٌد قٌادة التابع
)( fuelضمن الصفّ المشتق كلّما دَ َعت الحاجة لذلك.
261
// virtual members Vehikle need: 2 leters of fuel
#include <iostream > in 10 KM
using namespace std; Car need: 1 leters of fuel in 10
class Vehicle KM
{ MotoCicle need: 0.666667 leters
protected: of fuel in 10 KM
float distance ;
public:
Vehicle()
{
distance = 0.0;
}
void SetDistance(float d)
{
distance = d;
}
virtual float fuel()
{
return distance/5;
}
};
int main()
{
Vehicle myvehicle;
Car mycar;
Cycle mycycle;
myvehicle.SetDistance(10);
mycar.SetDistance(10);
mycycle.SetDistance(10);
cout<<"Vehikle need: "<<myvehicle.fuel()
<<" leters of fuel in 10 KM\n";
cout<<"Car need: "<<mycar.fuel()
<<" leters of fuel in 10 KM\n";
cout<<"Cycle need: "<<mycycle.fuel()
<<" leters of fuel in 10 KM\n";
return 0;
}
262
الصفوف األساس ٌّة المجردة Abstract base classes
الصفوف المجرّ دة البسٌطة هً ص ّفوف تشبه إلى ح ّد كبٌر الصفّ CPolygonالذي أنشؤناه سابقا والفرق
البسٌط ٌكمن فً التابع )( areaالمعرّ ف فً الصفّ CPolygonحٌث ال ٌمكن للص ّفوف المجرّ دة أن تحوي
على تعلٌمات فً توابعها التً من النوع virtualوبدال من كتابة التابع بك ّل تعلٌماته فً الصفّ األساسً
سنكتفً فقط بالتصرٌح عن التابع دون كتابة أيّ تعلٌمة فٌه ولن نضٌف له األقواس }{ أٌضا لكن ٌمكننا فً
حالتنا هذه أن نضٌف إلى التعرٌف قٌمة ابتدابٌة لٌعٌدها التابع وذلك بإضافة اإلسناد التالً:
; virtual int area (void) = 0
الحظ كٌف أ ّننا أضفنا المساواة = 0إلى التعرٌف عن التابع عوضا عن كتابة جسمه كامبل .هذا النوع من التوابع
ٌدعى ,pure virtual functionوك ّل الصفوف التً تحتوي على مثل هذا النوع من التوابع تدعى صفوفا
مجرّ دة .abstract classes
االختبلف األكبر لهذه الصفوف عن غٌرها أ ّنه ال ٌمكننا أن ننشا منها نسخا جدٌدة فهً غٌر قابلة لبلشتقاق,
لك ّنه ٌمكننا أن نشٌر إلٌها باستخدام مإ ّ
شر .
غٌر صحٌحة ألنّ الصفّ CPolygonأصبح اآلن من النوع المجرّ د .abstract class
;CPolygon * ppoly1
;CPolygon * ppoly2
وهذا ألنّ التوابع من النوع pure virtual functionال تحتوي على تعلٌمات بداخلها وهذا ٌجعل من
المستحٌل إنشاء ُنسخ من الصفّ المجرّ د إذ أنّ بعض أعضابه ال تمتلك تعرٌفات كاملة لوظابفهاّ ,إال أ ّنه ٌمكننا
أن نشٌر إلى الصفّ الذي ٌرث الصفّ األساسً المجرّ د باستخدام مإ ّ
شر كما فً المثال التالً:
// virtual members 20
>#include <iostream 10
;using namespace std
{ class CPolygon
protected:
;int width, height
public:
263
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
};
class CRectangle: public CPolygon {
public:
int area (void)
{ return (width * height); }
};
class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
};
int main () {
CRectangle rect;
CTriangle trgl;
CPolygon * ppoly1 = ▭
CPolygon * ppoly2 = &trgl;
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
return 0;
}
لو أعدت النظر فً المثال السابق لرأٌت أ ّننا استطعنا أن نشٌر إلى كابنات من أنواع )صفوف( مختلفة باستخدام
ًعضو ف
ٍ ٍ تصوّ ر أ ّننا نرٌد اآلن إنشاء. هذا الشًء مفٌ ٌد للغاٌة.* CPolygon شرات
تابع ّ نوع واحد من المإ
لٌطبع المساحة على الشاشة دون أن نع ّرف نوع الصفّ الذي ورث هذا التابع منCPolygon ًالصفّ األساس
.ًالصفّ األساس
// virtual members 20
#include <iostream> 10
using namespace std;
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void) =0;
void printarea (void)
{ cout << this->area() << endl; }
};
264
{ )( int main
;CRectangle rect
;CTriangle trgl
;CPolygon * ppoly1 = &rect
;CPolygon * ppoly2 = &trgl
;)ppoly1->set_values (4,5
;)ppoly2->set_values (4,5
;)(ppoly1->printarea
;)(ppoly2->printarea
;return 0
}
إنّ الصفوف المجرّ دة و األعضاء virtualهً التً تمنح لغة C++خاصٌّة تعدد األشكال Polymorphism
التً تع ّد إحدى أه ّم مبادئ البرمجة كابن ٌّة التوجّ ه .OOP
بالطبع التطبٌقات التً أنشؤناها بسٌطة للغاٌة و لك ّنها فقط لتوضٌح هذه المبادئ و المٌزات ,و لكن تخٌل لو
أكثر نفعا.
أكثر إثارة و َ
ط ّبقناها على مصفوفة من الكابنات بالطبع سٌكون األم ُر َ
265
الفصل التاسع شصر:
مالحظة :القوالب من المٌزات الحدٌثة التً ت ّم إنتاجها مع لغة ANSI-C++القٌاس ٌّة .لذلك إذا كنت
تستعمل مترجما ا ال ٌدعم هذه اللغة القٌاس ٌّة فمن الممكن ّأال تكون قادراا على استخدامها.
تابع القوالب
تسمح القوالب بإنشاء توابع عموم ٌّة تستطٌع أن تقبل أي نوع من البٌانات كوسطاء وتعٌد القٌمة المطلوبة من
دون إعادة تحمٌل التابع أبدا .وهذه التوابع العمومٌة تخضع للقاعدة التالٌة:
; template < typename identifier > function_declaration
: typenameهو نوع البٌانات الممرّ رة و قد ٌكون نوعا أساس ٌّا أو نوعا معرّ فا )مثل الصفوف(.
: identifierاسم الوسٌط.
مثال :هذا التابع ٌعٌد أكبر كابن من الكابنٌن الممررٌن إلٌه )من النوع)الصفّ ( .(GenericType
حتى اآلن لم ٌمثل النوع المعرف GenericTypeأي نوع منفصل من البٌانات ,ولكن عندما سٌستدعى التابع
سنكون قادرٌن على استبدال هذا النوع بؤي نوع آخر والذي سندعوه نموذجا .patternللقٌام بذلك ٌمكننا أن
نستدعً التابع العمومًّ بالطرٌقة التالٌة:
266
// function template 6
>#include <iostream 10
;using namespace std
>template <class S
{ )S GetMax (S a, S b
;S result
;) return ( result = (a>b)? a : b
}
{ )( int main
;int i=5, j=6, k
;float l=10.0, m=5.0, n
;)k=GetMax<int>(i,j
;)n=GetMax<float>(l,m
;cout << k << "\n" << n << endl
;return 0
}
فً هذه الحالة دعونا النوع العام باالسم Sبدال من االسم GenericTypeكما وٌمكننا أن نستخدم أي اسم آخر
علما أنّ االسم Tهو األكثر شهرة مع القوالب )أل ّنه أوّ ل حرف من الكلمة .(template
تستطٌع أن ترى كٌف استخدمنا التابع )( GetMaxمع نوعٌن مختلفٌن من البٌانات ( )int , floatمع أ ّننا لم نقم
بإعادة تحمٌل التابع لٌستقبل أكثر من نوع.
تستطٌع أن ترى أٌضا أ ّننا تمك ّنا من تعرٌف متغٌّر من النوع Sداخل التابع )(GetMax
;S result
سٌت ّم استبدال المتغٌّر من النوع Sبآخر من النوع المذكور بٌن القوسٌن >< عند استدعاء التابع )(.GetMax
مالحظة :فً هذه الحالة الوسطاء الممرّ رة إلى التابع هً من النوع Sوهو نفس نوع البٌانات التً
سٌعٌدها التابع لذلك فإنّ المترجم ٌستطٌع أن ٌعرف نوع البٌانات من خبلل الوسطاء الممرّ رة
مباشرة دون أن نذكره بٌن القوسٌن <> .كما ٌلً:
; int i, j
;) GetMax ( i , j
267
بٌنما ال ٌمكننا كتابة التعلٌمات التالٌة بسبب االختبلف بٌن األنواع الممرّ رة إلى التابع :
;int i
;long l
;)k = GetMax (i,l
حٌث أنّ التابع ٌنتظر م ّنا أن نمرر إلٌه متغٌّرٌن )كابنٌن( من نفس النوع )الصفّ (.
ٌمكننا أن نصنع تابعا عموم ٌّا ٌقبل أكثر من نوع من البٌانات كما فً المثال التالً :
صف القوالب
ّ
ٌمكننا أن نكتب ص ّفا لٌقبل أعضاء من أنواع عا ّمة ,و كمثال على ذلك:
268
// class templates 100
#include <iostream>
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T getmax ();
};
template <class T>
T mypair<T>::getmax ()
{
T retval;
retval = a>b? a : b;
return retval;
}
int main () {
mypair <int> myobject (100, 75);
cout << myobject.getmax()<<endl;
return 0;
}
:template <class T> بالتعلٌمةgetmax() ال حظ كٌف سبقنا سطر تضمٌن )كتابة تعلٌمات( التابع
// Template specialization 25
#include <iostream> 0
using namespace std;
template <class T>
class mypair {
T a, b;
public:
mypair (T first, T second)
{a=first; b=second;}
T module () {return 0;}
};
template <>
int mypair<int>::module() {
return a%b;
}
269
int main () {
mypair <int> myints (100,75);
mypair <float> myfloats (100.0,75.0);
cout << myints.module() << '\n';
cout << myfloats.module() << '\n';
return 0;
}
26:
الفصل العصرون :
تم ّكننا فضاءات األسماء من تجمٌع ع ّدة صفوف عا ّمة فً مجموعة واحدة ,من الكابنات و)أو( التوابع تحت اسم
واحد لك ّل هذه المجموعة حٌث تصبح كلُّها أعضاء داخل المدى الذي ٌش ّكل فضاء االسم ,وٌكون ك ّل عضو منها
قادرا على الوصول إلى األعضاء األخرى.
الشكل الذي ٌمكننا من خبلله التصرٌح عن فضاء اسم جدٌد هو :
namespace identifier
{
namespace-body
}
حٌث أنّ :
:identifierهو أي اسم تختاره أنت شرٌطة أن ٌكون صحٌحا )ٌخضع لقواعد تسمٌة المتغٌّرات(.
:namespace-bodyمجموعة من الصفوف و)أو( الكابنات و)أو( التوابع.
مثال :
namespace general
{
;int a, b
;class S
;}…{()void B
}
و لكً نصل إلى أحد أعضاء فضاء االسم generalمن خارج الفضاء علٌنا أن نستخدم معامل المدى ::
مثال:
;general::a
;)(general::B
الوظٌفة التً ٌشغلها فضاء االسم مفٌدة خصوصا فً الحاالت التً ٌُح َتمل فٌها وجود أعضاء أو كابنات شاملة
تمتلك نفس االسم داخل نفس البرنامج ما ٌعنً أنّ علٌنا أن نعٌد تسمٌتها لكً نستطٌع أن نتعامل معها كلّها ّإال أنّ
فضاءات األسماء تق ّدم ّ
حبل مناسبا لهذه المشكلة .راقب المثال التالً :
271
فً هذه الحالة لدٌنا متغٌّران شامبلن لهما نفس االسم varلكنّ األوّ ل موجو ٌد فً الفضاء firstأ ّما الثانً فهو
موجو ٌد فً الفضاء secondلذلك لن ٌكون من الخطؤ وجود متغٌّرٌن لهما نفس االسم كما كان سٌحصل لو
أزلنا الفضابٌن السابقٌن وأبقٌنا على المتغٌّرٌن فقط.
مثال :
// using namespace example 5
>#include <iostream 3.1416
;using namespace std
namespace first
} ;{ int var = 5
namespace second
} ;{ double var = 3.1416
{ )( int main
{
;using namespace first // scope of
;cout << var << endl // namespace first
}
{
;using namespace second // scope of
;cout << var << endl // namespace second
}
} ;return 0
272
std الفضاء
حٌث ت ّم تضمٌن كل صفوف. القٌاسٌة نفسهاC++ وهو مكتبة,واح ٌد من أفضل األمثلة حول فضاءات األسماء
.std القٌاسٌة فً الفضاءC++ و كابنات وتوابع مكتبة
: ِضبي
. رزّىٓ ِٓ اٌزؼبًِ ِغ أػؼبء ٘زا اٌفؼبءٟ ٌىٜغت أْ رغزخذَ اعُ اٌفؼبء ص ُّ ِؼبًِ اٌّذ٠ :مالحظة
ُ ٌٕزّىٓ ِٓ العزغٕبء ػٓ روش اعusing namespace std ; ّخ١ٍّىٕٕب أْ ٔغزخذَ اٌزؼ٠ ّّٗٔئل أ
: ٍٟ٠ ب ِغ أػؼبء ٘زا اٌفؼبء وّبٙ١ ِٓ أعً وً ِشّح عٕزؼبًِ فٜ ِؼبًِ اٌّذٚ اٌفؼبء
int main ()
{
cout << "Hello world in ANSI-C++\n";
return 0;
}
مارا تجذ؟ ما هى انسبب؟. ص ُّ ش ّغً اٌجشٔبِظusing namespace std ; ّخ١ًٍ اٌزؼ٠عشّة أْ رض
273
274
حلول التنارين غري احمللولة
بنية الربنامج يف لغة الـ C++
.2
)(main
بفاصلة منقوطة ) ; (
تعلٌق.
التعلٌق هو قطعة من الشٌفرة مهملة من قبل المترجم.
إنهاء البرنامج بطرٌقة سلٌمة.
القوسٌن }{
تضمٌن الملف المصدري > <iostreamالستخدام التعلٌمات الموجودة فٌه.
.3
;"!cout<<"In the name of Allah. The peace upon you, Hello world
275
املتغيّرات
276
اإلدخال و اإلخراج
.2
*
**
***
****
*****
.3
#include <iostream>
using namespace std;
int main ()
{
float f = 0.0 , c = 0.0 ;
cout<<"Enter celecius degree: ";
cin>>c;
f = (9/5)*c + 32 ;
cout<<'\n'<<f<<"\n";
return 0;
}
.4
#include <iostream>
using namespace std;
int main ()
{
float f = 0.0;
cout<<"Enter fehrnhite degree: ";
cin>>f;
float c = 5*(f - 32)/9 ;
cout<<'\n'<< c <<"\n";
return 0;
}
.5
#include <iostream>
using namespace std;
int main ()
{
float a = 0.0 , d = 0.0,v =0.0 ;
int t = 0;
cout<<"Enter accelration of body by m.s^-2: ";
cin>>a;
cout<<"Enter time of movement by seconds: ";
cin>> t;
d = 0.5*a*t*t;
277
v = a*t;
cout<<"distance = "<<d<<" meters\n";
cout<<"velocity = "<<v<<" m.s^-1\n";
return 0;
}
.6
#include <iostream>
using namespace std;
int main ()
{
float f = 0.0 , x =0.0;
cout<<"Enter x: ";
cin>>x;
f = 5 - x*x;
cout<<"\nf("<<x<<") = "<<f<<endl;
return 0;
}
.7
#include <iostream>
using namespace std;
int main ()
{
int n = 0;
cout<<"Enter n: ";
cin>>n;
cout<<"\nsum of numbers from (1 to "<<n<<") = "<<n*(n+1)/2<<endl;
cout<<"\navg = "<<(float)(n*(n+1)/2)/n<<endl;//avg = sum / n
return 0;
}
.8
#include <iostream>
using namespace std;
int main ()
{
cout<<"Just remember \"Allah created You\'.\n";
return 0;
}
278
.9
#include <iostream>
using namespace std;
int main ()
{
int x1,x2,x3;
cout<<"Enter three numbers plz: ";
cin>>x1>>x2>>x3;
cout<<"\nAverage of ["<<x1<<','<<x2<<','<<x3<<"] = "
<< float(x1+x2+x3)/3<<endl;
return 0;
}
279
املعامالت
.2
int x = 0, a = 0, b = 1, d = 3, c = 2;
bool e = true , r = true, t = false;
العبارة الجواب
a += (b = c = d - 5) ; -2
d %= 2 * c / ++b ; 3
a = d - (b += (c * (1-a))); 0
e = !e 0
r = e || t 0
t = e && r 0
e = !( (e && r ) || (e && t ) ) ; 1
.3
العبارة الجواب
x=7+3*6/2-1; 15
x = 2 % 2 + 2 * 2 -2 / 2 ; 3
x=(3*9*(3+(9*3/(3)))); 324
c = 2*b - 3/d + a++; 1
.4
cout<< ++a ; 1
cout<< a++ ; 0
cout<< a++ / 2 ; 0
cout<< ++a / 2 ; 0
27:
بنى التخكه
.2
#include<iostream >
using namespace std;
float avg =0;
int main()
{
cout<<"Enter Average: ";
cin>>avg;
if(avg > 89 && avg <= 100 )
cout<<"Excellent!\n";
else if(avg > 79 && avg <= 89)
cout<<"Very Good\n";
else if(avg > 69 && avg <= 79)
cout<<"Good\n";
else if(avg > 59 && avg <= 69)
cout<<"Passed\n";
else
cout<<"Not passed\n";
return 0;
}
.3
البرنامج التصحٌح
while ( c <= 5 ) while ( c <= 5 )
{ { product *= c;
product *= c; ++c;
++c; }
if ( gender == 1 ) if ( gender == 1 )
cout<< "Woman" ; cout<< "Woman" ;
else; else // ال ٌوجد فاصلة منقوطة هنا
cout<<"man"; cout<<"man";
while ( z >= 0 ) while ( z >= 0 )
sum += z; {
sum += z;
z--;
}
// nested loop // nested loop
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int main () int main ()
{ {
int j = 1; int j = 1;
for( int i = 1 ; i<=3 ; for( int i = 1 ; i<=5 ; i++)
i++) {while( j<=i )
while( j<i ) {cout <<"* " ;
{ j++;
cout <<"* " ; }
j++; cout<<endl;
} j = 1;}
return 0; return 0;
} }
281
.4
#include <iostream>
using namespace std;
int main ()
{
int x,y,z,max,med,min;
cout<<"Enter three numbers: ";
cin>>x>>y>>z;
if (x > y && x > z && y > z)
cout<<z<<"\t"<<y<<"\t"<<x<<endl;
else if (x > y && x > z && z>y )
cout<<y<<"\t"<<z<<"\t"<<x<<endl;
.5
البرنامج الشكل
#include <iostream> 3 4 5 6
using namespace std; 4 5 6 7
int main () 5 6 7 8
6 7 8 9
{ for(int i = 3;i<=6;i++)
{ for(int j = i;j<i+4;j++)
cout<<j<<" ";
cout<<"\n";
}
return 0;
}
#include <iostream> 3
using namespace std; 4 5
int main () 5 6 7
6 7 8 9
{ for(int i = 0;i<=3;i++)
{
for(int j = 0;j<=3;j++)
if(i>=j) cout<<j+3+i<<" ";
cout<<"\n";
}
return 0;
}
282
#include <iostream> 3 4 5 6
using namespace std; 5 6 7
int main () 7 8
9
{
for(int i = 0;i<=3;i++)
{
for(int j = 0;j<=3;j++)
if(i<=j)
cout<<j+3+i<<" ";
else cout<<" "; // 2 spaces
cout<<"\n";
}
return 0;
}
#include <iostream> 6
using namespace std; 6 7
int main () 6 7 8
6 7 8 9
{
for(int i = 0;i<=3;i++)
{
for(int j = 0;j<=3;j++)
if(i+j>=4-1)
cout<<j+3+i<<" ";
else cout<<" ";//2 spaces
cout<<"\n";
}
return 0;
}
#include <iostream> 3 4 5 6
using namespace std; 4 5 6
int main () 5 6
6
{
for(int i = 0;i<=3;i++)
{
for(int j = 0;j<=3;j++)
if(i<=j) cout<<j+3<<" ";
cout<<"\n";
}
return 0;
}
#include <iostream> 3 4 5 6
using namespace std; 4 7
int main () 5 8
6 7 8 9
{
for(int i = 0;i<=3;i++)
{
for(int j = 0;j<=3;j++)
if(i == 0 || i == 3)
cout<<j+3+i<<" ";//2 spaces
else
{
283
if(j == 0 || j == 3)
cout<<j+3+i<<" ";
else cout<<" ";// 2 spaces
}
cout<<"\n";
}
return 0;
}
.6
#include <iostream>
using namespace std;
int main ()
{
cout<<"Enter n: ";
int n;
cin>>n;
if(n%10 == 0)
cout << "yes\n";
else
cout<<"no\n";
return 0;
}
.7
#include <iostream>
#include<cmath >
using namespace std;
int main ()
{
double x, fx =0.0 ;
err:
cout<<"Enter x ecept (1 or 3): ";
cin>>x;
if(x == 1 || x == 3)
{cout << "Infinite Error You can't Enter 1 or 3\n";
goto err;}
else{
fx = (pow(x,3) - 7)/(pow(x,2)-4*x+3);
cout<<"f("<<x<<") = "<<fx<<endl;
}
return 0;
}
284
.8
#include <iostream>
using namespace std;
int main()
{
int i,sum=0;
for(i=1;i<=99;i++)
if(i%2==0 && i%3==0)
sum+=i;
cout<<"sum="<<sum<<endl;
return 0;
}
.9
#include<iostream>
using namespace std;
void main()
{
int a,b,lcm ;
cout << "enter a and b" << endl;
cin>>a>>b;
if (a == 0 || b == 0) lcm = 0;
else if ( a>b && a%b==0 )
cout <<"lcm="<<a<<endl ;
else if(b>a && b%a==0)
cout <<"lcm="<<b<<endl;
else
lcm=a*b;
cout <<"lcm="<<lcm<<endl;
}
.:
285
.21
#include<iostream >
using namespace std;
void main()
{ int n; char c;
cout<<"Enter charactor then number: ";
cin >> c >> n;
for(int i = 0; i<n;i++){
for(int j = 0; j<n;j++)
if(i>=j) cout<<c<<" ";
cout<<endl;}
}
.22
#include<iostream.h>
void main()
{
float x,y;
char c = 'n';
while(c == 'n' )
{
cout<<"Enter two numbers: ";
cin>> x >> y;
ZeroErr:
if(y != 0)
{
cout<< x/y << endl;
}
else
{
cout<<"Error You can't enter 0";
cout<<"ReEnter second number without 0 plz: ";
cin>> y;
goto ZeroErr;
}
inputErr:
cout<<"press n for new operation,(e to exit): ";
cin>> c;
if(c == 'n' || c == 'N') continue;
else if(c == 'e' || c == 'E') break;
else goto inputErr;
}
}
.23
#include<iostream >
using namespace std;
void main()
286
{
int x;
cout<<"Enter x: ";
cin>>x;
int i = 1;
while(i<=x)
{
if(x%i == 0)cout<<i<<endl;
i++;
}
}
التوابع
.0
التابع األخطاء
int Sum(int a , int b) وٌجب أن ٌعٌد قٌمة إال أنه الint هذ التابع من النوع
{ return statement; ٌحتوي على التعلٌمة
int sum = a + b; return sum; // return a+b;
}
int divide(int a , int b) و هو ٌعٌد قٌمة من النوعint هذا التابع من النوع
{ .float فعلٌنا أن نغٌر نوع التابع إلىfloat
return (float)a/b; float divide(int a, int b({…}
}
void subtract(int a , int b) وٌجب ّأال ٌعٌد قٌمة لكنهvoid هذ التابع من النوع
{ لذلك سنغٌرreturn a-b; ٌحتوي على التعلٌمة
return a-b; int نوعه إلى
}
int subtract)int a, int b({…}
.3
البرنامج الناتج
#include<iostream> x b a
using namespace std; 0 0 -1.07374e+008
int x = 0; 0.5
float b; 0 2 1
float d(float a , float& b)
: أ ّما بعد التعدٌل
{
a--; x b a
b++; 0 0 -1.07374e+008
x = a/b; 0.5
return (x+1)/2.0; 1 2 1
}
int main() هً قٌمة-1.07374e+008 القٌمة:مالحظة
{
عشوابٌة تختلف دوما وهً عشوابٌة ألن المتغٌّر
float a;
cout<<"x\tb\ta\n"; متغٌّر موضعً ولقد قلنا إنّ المتغٌّراتa
cout<<x<<"\t"<<b<<"\t"<<a<<endl; الموضعٌة تؤخذ قٌما عشوابٌة إذا لم تت ّم تبدبتها أ ّما
a = b = ++x; المتغٌّرات الشاملة فهً تؤخذ القٌم الصفرٌة للنوع
cout<<d(a , b)<<endl;
cout<<x<<"\t"<<b<<"\t"<<a<<endl;
return 0;
}
.2
287
#include<iostream>
using namespace std;
float sum(float a,float b);
float sub(float a,float b);
float mult(float a,float b);
float divide(float a,float b);
void main()
{
float x,y;
char op ;
cout<<"Enter x: ";
cin>>x;
cout<<"Enter operator from{+,-,*,/}: ";
cin>>op;
cout<<"Enter y: ";
cin>>y;
switch(op)
{
case '+': cout<<sum(x,y)<<endl; break;
case '-': cout<<sub(x,y)<<endl; break;
case '*': cout<<mult(x,y)<<endl; break;
case '/':
if(y!=0) cout<<divide(x,y);
else cout<<"Error divide by 0\n";
break;
}
}
float sum(float a,float b)
{
return a+b;
}
float sub(float a,float b)
{
return a-b;
}
float mult(float a,float b)
{
return a*b;
}
float divide(float a,float b)
{
return a/b;
}
.1
#include<iostream >
using namespace std;
float rec_power(float a,int b);
float frec_power(float a,int b);
288
void main()
{
float x;
int y;
cout<<"Enter x, y: ";
cin>>x>>y;
cout<<"Recutrivity power = "<<rec_power(x,y)<<endl;
cout<<"Frecuently power = "<<frec_power(x,y)<<endl;
}
float rec_power(float a,int b)
{
if(b == 0)
return 1;
else if(b>0)
return a*rec_power(a,b-1);
else
return 1/(a*rec_power(a,-b-1));
}
float frec_power(float a,int b)
{
float res = 1;
if(b==0)
res = 1;
else if(b>0)
for(int i=1;i<=b;i++)
res*=a;
else{
for(int i=1;i<=-b;i++)
res*=a;
res = 1/res;
}
return res;
}
.5
#include<iostream >
using namespace std;
float frec_power(float a,int b);
float pi(long n);
void main()
{
long n ;
cout<< "enter n: ";
cin>>n;
cout<<"\n"<<pi(n)<<endl;
}
float pi(long n)
{
float p = 0;
for(long i = 0;i<n;i++)
289
p += 4*frec_power(-1,i)/(2*i+1);
return p;
}
float frec_power(float a,int b)
{
float res = 1;
if(b==0)
res = 1;
else if(b>0)
for(int i=1;i<=b;i++)
res*=a;
else
{
for(int i=1;i<=-b;i++)
res*=a;
res = 1/res;
}
return res;
}
.6
#include<iostream >
using namespace std;
int frec_gcd(int a, int b); // frecuently
int rec_gcd(int x, int y); // recursivity
void main()
{
int a , b;
cout<<"Enter a , b: ";
cin>>a>>b;
cout<<"\nfrequently result: "<< frec_gcd(a,b);
cout<<"\nrecursivity result: "<< rec_gcd(a,b)<< endl;
}
int frec_gcd(int a, int b)
{
while(a != b)
{
if(a>b)
a-=b;
else
b-=a;
}
return a; // or return b : a = b
}
int rec_gcd(int x, int y)
{
if(x == y)
return x;
else if (x>y)
return rec_gcd(y,x-y);
28:
else
return rec_gcd(x,y-x);
//second way to finding gcd
/*if(y == 0)
return x;
else
return rec_gcd(y,x%y); */
}
.7
#include<iostream >
#include<math.h>
using namespace std;
long fact(int a);
double Compination(int n, int k);
double Permitation(int n, int r);
void main()
{
int n , k , r ;
cout<<"Enter n: ";
cin>>n;
cout<<"\n"<<n<<"! = "<<fact(n);
cout<<"\nEnter k < " << n << " : ";
cin>>k;
cout<<"\nc("<<n<<","<<k<<") = "<<Compination(n,k);
cout<<"\nEnter r < " << n << " : ";
cin>>r;
cout<<"\np("<<n<<","<<r<<") = "<<Permitation(n,r)<<endl;
}
long fact(int a)
{
long f = 1;
for(int i =1; i<=a ; i++)
f*= i;
return f;
}
double Compination(int n, int k)
{
double c = fact(n)/(fact(n-k)*fact(k));
return c;
}
double Permitation(int n, int r)
{
double p =Compination(n,r)*fact(r);
return p;
291
}
.8
#include<iostream >
using namespace std;
void multiple(int a, int b);
bool multiple1(int a, int b);
void main()
{
int n , k ;
cout<<"Enter n, k: ";
cin>>n>>k;
if(multiple1(n,k))
cout<<"true\n";
else
cout<<"false\n";
multiple(n,k);
}
void multiple(int a, int b)
{
if(b>a && b%a ==0)
cout<<"true\n";
else
cout<<"false\n";
}
bool multiple1(int a, int b)
{ if(b>a && b%a ==0)
return true;
return false; // no need to else statement. why?
}
.9
#include<iostream >
using namespace std;
void print_primes(int a);
bool is_prime(int a);
void main()
{
int n;
cout<<"Enter n: ";
cin>>n;
if(is_prime(n))
cout<<"true\n";
else
cout<<"false\n";
print_primes(n);
}
bool is_prime(int a)
{
292
if(a>0 && a != 1)//positive and not 1 (1 isn't prime)
{
int sum = 0;
for(int i = 1; i <= a ; i++)
{
if(a%i == 0)
sum++;
}
if(sum == 2)
return true;
}
return false;
}
void print_primes(int a)
{
for(int i = 1; i <= a ; i++)
if(is_prime(i))
cout<<i<<"\n";
}
.01
#include<iostream>
using namespace std;
double abs_val(double x)
{
if(x>0) return x;
else return -x;
}
void main()
{
double n;
cout<<"Enter n: ";
cin>>n;
cout<<"| "<<n<<" | = "<<abs_val(n)<<endl;
}
.00
#include<iostream>
using namespace std;
const double pi = 3.141592;
double Circl_space(double r)
{ return (pi*r*r); }
double Rect_space(double a , double b)
{ return (a*b); }
double Trgl_space(double b , double h)
{ return (0.5*b*h); }
void main()
{
cout<<"1- Calculate circle spsace\n";
293
cout<<"2- Calculate rectangle spsace\n";
cout<<"3- Calculate triangle spsace";
cout<<"\nEnter number from list above to select: ";
int ch ;
cin>>ch;
cout<<"\n";
switch(ch)
{
case 1 :
cout<<"Calculating circle space.. .\n";
double r ;
cout<<"Enter r: ";
cin>>r;
cout<<"S ="<<Circl_space(r)<<endl; break;
case 2 :
cout<<"Calculating rectangle space.. .\n";
double a, b ;
cout<<"Enter width: ";
cin>>a;
cout<<"Enter height: ";
cin>>b;
cout<<"S ="<<Rect_space(a,b)<<endl;
break;
case 3 :
cout<<"Calculating triangle space.. .\n";
double h;
cout<<"Enter base: ";
cin>>b;
.03
cout<<"Enter height: ";
cin>>h;
cout<<"S ="<< Trgl_space(b,h)<<endl;
#include<iostream> break;
using namespace
default: std;
int print(int h); cout<<"program will terminate now!.";
int main() break;
{ int h;//h} is hieght
}cin>>h;
print(h);
return 0; }
int print(int h)
{ int i,j,k;
for(i=1;i<=h;i++)//number of rows
{
for(j=1;j<=h-i;j++)//from line beginning to the first star pos print space
cout<<" ";// 2 spaces
for(k=1;k<=2*i-1 ;k++)// from last space in line to (2*line number -1)
cout<<"* "; // print * where (2*line number -1) is number of
// * in each line (i)
cout<<"\n"; // print new line
}
return 0;
}
294
املصفوفات
-2
for ( int i = 0; i<= 10; i++ ) (a
i<10 غٌر موجود إذا ٌجب أن ٌكون شرط التوقفb[10] والعنصر21 سٌؤخذ العداد القٌمة
int i = 1 أي2 القٌمةi ًأو ٌمكن أن نعط
d[ 1, 9 ] = 2.345; )d
d[ 1][9] = 2.345; ٌجب أن ٌكون كل دلٌل ضمن قوسٌن أي
-3
.p[3] وp[2] وp[1] وp[0] (a
.تعرٌف (b
.d[2][4] (c
.20 (d
-4
const int arraySize = 10; (a
double fractions[ arraySize ] = { 0.0 }; )b
fractions[ 9 ] = 1.667; fractions[ 6 ] = 3.333; (c
(d
for(int i=0; i<arraySize;i++)
cout<<"fractions["<i<<"]="<<fractions[i]<<endl;
-5
#include<iostream>
using namespace std;
const int n=8;
void print(int a[])
{
for(int i=0;i<n;i++)
cout<<a[i]<<" ";
}
int main()
{
int A[n]={1,5,4,3,7,2,9,0},i,j,temp;
for(i=0;i<n;i++)//ascending
for(j=0;j<n-1;j++)
if(A[j]>A[j+1])
{temp=A[j];A[j]=A[j+1];A[j+1]=temp;}
cout<<"ascending: ";
print(A);
295
for(i=0;i<n;i++)//descending
for(j=0;j<n-1;j++)
if(A[j]<A[j+1])
{temp=A[j];A[j]=A[j+1];A[j+1]=temp;}
cout<<"\ndescending: ";
print(A);
cout<<endl;
return 0;
}
-6
#include<iostream>
using namespace std;
const int n=10;
int a[n],b[n],c[2*n],i,j;
-7
#include<iostream>
using namespace std;
const int n=10;
int main()
{
int a[n],frq[4]={0},i;
cout<<"enter array of 10 integers:\n";
for(i=0;i<n;i++)
296
cin>>a[i];
for(i=0;i<n-1;i++)
{
if(a[i]<a[i+1])
frq[0]++;
else if(a[i]>a[i+1])
frq[1]++;
else if(a[i]==a[i+1])
frq[2]++;
else
frq[3]++;
}
if(frq[0]==9)
cout<<"the array is growing.\n";
else if(frq[1]==9)
cout<<"the array is decreasing.\n";
else if(frq[2]==9)
cout<<"the array is constant.\n";
else
cout<<"the array is growing and decreasing.\n";
return 0;
}
-8
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n,mark[100],i,j,temp;
string name[100],strTemp;
cout<<"enter students number ";
cin>>n;
for(i=0;i<n;i++)
{
cout<<"student "<<i+1<<" name:";
cin>>name[i];
cout<<"student "<<i+1<<" mark:";
cin>>mark[i];
}
for(i=0;i<n;i++)
for(j=0;j<n-1;j++)
if(mark[j]<mark[j+1])
{
temp=mark[j];mark[j]=mark[j+1];mark[j+1]=temp;
strTemp=name[j];name[j]=name[j+1];name[j+1]=strTemp;
}
297
-9
int main()
{
int m,n;
cout<<"number of rows=";cin>>m;
cout<<"number of columns=";cin>>n;
add(a,b,c,m,n);
print(a,m,n);
cout<<"\n +\n\n";
print(b,m,n);
cout<<"\n =\n\n";
print(c,m,n);
return 0;
}
void print(int arr[][MAX],int m,int n)
{
int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cout<<arr[i][j]<<" ";
cout<<"\n";
}
}
void add(int a[][MAX],int b[][MAX],int c[][MAX],int m,int n)
{
int i,j;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
cout<<"a["<<i+1<<"]["<<j+1<<"]=";cin>>a[i][j];
cout<<"b["<<i+1<<"]["<<j+1<<"]=";cin>>b[i][j];
c[i][j]=a[i][j]+b[i][j];
}
}
-:
#include<iostream>
#include<string>
#include<cstdlib>
#include<ctime>
using namespace std;
298
int main()
{
cout<<"enter your Choice :\n";
cout<<"R\tfor Rock\n";
cout<<"P\tfor Paper\n";
cout<<"S\tfor Scissors\n";
cout<<"The computer chose\n";
int cmpCounter = 0;
int YourCounter = 0;
lbb:
cout<<"\nYour points:\t\t" << YourCounter;
cout<<"\nComputer points:\t" << cmpCounter;
string mesg ;
srand(time(0));//seed rand
int r = rand() % 3 ;
switch (r)
{
case 0:
mesg = "Computer choice's Rock";
break;
case 1:
mesg = "Computer choice's Paper";
break;
case 2:
mesg = "Computer choice's Scissors";
break;
}
cout<<"\nChose please:";
string PlayerChosen ;
cin>>PlayerChosen ;
if (PlayerChosen == "R" || PlayerChosen == "r")
{
cout<<mesg;
switch (r)
{
case 0:
cout<<"\nNo Winner";
cmpCounter = cmpCounter;
YourCounter = YourCounter;
goto lbb;
break;
case 1:
cout<<"\nComputer Won...";
cmpCounter+=1;
goto lbb;
break;
case 2:
cout<<"\nYou Won...";
YourCounter+=1;
goto lbb;
299
break;
}
}
else if (PlayerChosen == "P" || PlayerChosen == "p")
{
cout<<mesg;
switch (r)
{
case 0:
cout<<"\nYou Won...";
YourCounter+=1;
goto lbb;
break;
case 1:
cout<<"\nNo Winner";
cmpCounter = cmpCounter;
YourCounter = YourCounter;
goto lbb;
break;
case 2:
cout<<"\nComputer Won...";
cmpCounter+=1;
goto lbb;
break;
}
}
else if (PlayerChosen == "S" || PlayerChosen == "s")
{
cout<<mesg;
switch (r)
{
case 0:
cout<<"\nComputer Won...";
cmpCounter+=1;
goto lbb;
break;
case 1:
cout<<"\nYou Winner";
YourCounter+=1;
goto lbb;
break;
case 2:
cout<<"\nNo Winner...";
cmpCounter = cmpCounter;
YourCounter = YourCounter;
goto lbb;
break;
}
}
else if (PlayerChosen == "E" || PlayerChosen == "e")
{
29:
cout<<"Do you want to exit the game? (y/n)";
string anser;
cin>>anser;
if (anser == "Y" || anser == "y")
return 0;//exit main func
else
goto lbb;
}
else
{
cout<<"\nBe sure from your inserting...";
goto lbb;
}
return 0;
}
2:1
الربدلة كائنية التوجه
.2
#include<iostream>
using namespace std;
const double pi = 3.141592;
class Circle
{
private :
double radius;
public:
void set_radius(double r);
double calc_space();
double calc_perimeter();
};
void Circle::set_radius(double r)
{
radius = r;
}
double Circle::calc_space()
{
return pi*radius*radius;
}
double Circle::calc_perimeter()
{
return 2*pi*radius;
}
void main()
{
Circle c1;
double r;
cout<<"Enter radius: ";
cin>>r;
c1.set_radius(r);
cout<<"c1 Space = "<<c1.calc_space()<<endl;
cout<<"c1 perimeter = "<<c1.calc_perimeter()<<endl;
}
.3
#include<iostream>
#include<math.h>
using namespace std;
class Point
{
public:
double x, y;
void set_point(double p_x, double p_y);
double distance(Point p1, Point p2);
};
2:2
void Point::set_point(double p_x, double p_y)
{
x = p_x; y = p_y;
}
double Point::distance(Point p1, Point p2)
{
return( sqrt( pow( (p2.x-p1.x),2) + (pow((p2.y-p1.y),2) ) ) );
}
void main()
{
Point p1,p2;
double x1,y1,x2,y2;
cout<<"Enter x1, y1: ";
cin>>x1>>y1;
cout<<"Enter x2, y2: ";
cin>>x2>>y2;
p1.set_point(x1,y1);
p2.set_point(x2,y2);
cout<<"Distance between p1 and p2 is :"
<<p1.distance(p1,p2)<<endl;
}
.4
#include<iostream>
using namespace std;
const double pi = 3.141592;
class Circle
{
private :
double radius;
public:
Circle(){}
Circle(double r){radius =r;}
void set_radius(double r);
double calc_space();
double calc_perimeter();
};
void Circle::set_radius(double r)
{
radius = r;
}
double Circle::calc_space()
{
return pi*radius*radius;
}
double Circle::calc_perimeter()
{
return 2*pi*radius;
}
void main()
2:3
{
Circle c1;
double r;
cout<<"Enter radius: ";
cin>>r;
Circle c2(r);
c1.set_radius(r);
cout<<"c1 Space\t"<<"c2 Space\t"<<"c1 perimeter\t"<<"c2
perimeter\n";
cout<<c1.calc_space()<<"\t\t"<<c2.calc_space()
<<"\t\t"<<c1.calc_perimeter()<<"\t\t"<<c2.calc_perimeter()<<endl;
}
#include<iostream>
#include<math.h>
using namespace std;
class Point
{
public:
double x, y;
Point(){}
Point(double p_x, double p_y) { x = p_x ; y = p_y ; }
void set_point(double p_x, double p_y);
double distance(Point p);
};
void Point::set_point(double p_x, double p_y)
{
x = p_x;
y = p_y;
}
double Point::distance(Point p)
{ return sqrt( pow( (p.x-this->x),2) + (pow((p.y-this->y),2) ) ); }
int main()
{
Point p1,p2;
p1.set_point(1,2);
p2.set_point(2,1);
cout<<p1.distance(p2)<<endl;
return 0;
}
2:4
.7
#include<iostream.h>
class Printing
{public:
Printing(){
cout<<
"Give the world the best you have, and the best will come to you.\n"; }
~Printing(){
cout<<
"\nIf man hasn't discovered that he will die for, he isn't fit to live.\n"; }
}print_that;
int main()
{
cout<<"Sweat plus sacrifice equals success.";
return 0;
}
( قد ال ٌعمل البرنامجusing namespace std; )ال تستخدم#include<iostream.h> ال تغ ٌّر التعلٌمة:مالحظة
( بشكل كامل ) قد ال ٌطبع العبارة الثالثة الموجودة فً الهادم
.8
#include<iostream>
#include<math.h>
using namespace std;
class Point
{
public:
double x, y;
void set_point(double p_x, double p_y);
double distance(Point p1, Point p2);
Point operator+ (Point p);
};
void Point::set_point(double p_x, double p_y)
{
x = p_x;
y = p_y;
}
double Point::distance(Point p1, Point p2)
{
return sqrt( pow( (p2.x-p1.x),2) + (pow((p2.y-p1.y),2) ) );
}
Point Point::operator+(Point p)
{
Point temp;
temp.x = this->x + p.x;
temp.y = this->y + p.y;
return temp;
}
void main()
{
Point p1,p2;
2:5
double x1,y1,x2,y2;
cout<<"Enter x1, y1: ";
cin>>x1>>y1;
cout<<"Enter x2, y2: ";
cin>>x2>>y2;
p1.set_point(x1,y1);
p2.set_point(x2,y2);
cout<<"Distance between p1 and p2 is :
"<<p1.distance(p1,p2)<<endl;
cout<<"c(x,y) = ("<<(p1+p2).x<<", "<<(p1+p2).y<<")\n";
}
.9
.getIncrementedData من أمام التصرٌح عن التابعconst أزل الكلمة
. لذلك علٌك أن تزٌل التعلٌمة الخاصة بالطباعة منهstatic من النوعgetcount التابع
2:6
اخلامتة
كل ما عليك أن تتعلّمو في البرمجة ,وليس ىذا ىو آخر الكتب التي ألفت
أخيراً ال يحوي ىذا الكتاب على ّ
في ىذا المجال؛ لذلك إن كنت ترى أ ّن البرمجة ىي الشي الذي كنت تبحث عنو فعليك أن تبحث عن كتاب
آخر لتكمل معو رحلتك.
هم من كان سبباً في إنجاز ىذا الكتاب فحرمو على النار وارزقو الجنّة برحمتك يا أرحم الراحمين.
اللّ ّ
هم ما كان من صواب فمنك وحدك ال شريك لك ,وما كان من زلل أو نسيان فمن أنفسنا والشيطان.
اللّ ّ
رب العالمين.
وآخر دعوانا أن الحمد هلل ّ
***
https://docs.google.com/spreadsheet/viewform?formkey=dDVxYmV5UFgwaHBFZkQ0U3RiO
TNNSUE6MQ&ifq
2:7
املراجع
2:8