صفحه 1:
صفحه 2:
دانشگاه
RE cy
اطلاعات
صفحه 3:
صفحه 4:
:مقدمه
obj 2 یک زبان همه منظوره است.
دستورالعملهاى اين زيان بسيار شبيه
عبارات جبرى و نحو آن شبيه جملات
انگلیسی می باشد. این امر سبب
مىشود كه 0 يك زبان سطح بالا
ل Pre rl pei در آن آسان
eae oe |
صفحه 5:
1 ا fad 4S
را بهارث برده است. اما برترى فنى )0
دیگری هم دارد: 2 اكنون دشىكراء
است. میتوان با استفاده از این خاصیت.
برنامهدهاى شى كرا توليد نمود. برنامههاى
7
كردناندء به سهولت تغيير و بهبود مى يابند
و قابليت اطمينان و يايدارى بيشترى دارند.
صفحه 6:
: اهم مطالب این کتاب
جلسه اول: «مقدمات بر نامه نویسی با لبب»
۳ «انواع اصلی»
«جلسه سوم: «انتخاب
جلسه چهارم: «تکرارب»
«جلسه پنجم: «توابع
جلسه ششم : « آرایهها»
صفحه 7:
«رجلسه هفتم: «اشارهگرها و ارجاعها
ORCC a eee 001
جلسه نهم: «شبیگرايي»
eS)y ا
جلسه يازدهم: «تركيب و وراثت»
صفحه 8:
(۷
مقدمات بر نامهنویسی با +C
ne
صفحه 9:
آنچه در این جلسه می خوانید
ند
۲- تاریخچهةه )+
00007
۴- شروع 009
۵- عملگر خروجی
ع۶- لیترالها و کاراکترها
/ا- متغيرها و تعريف آنها
PAP Eee Rr 0
53
٠-عملكر ورودى
صفحه 10:
هدف كلى:
آشنایی با تاریخچه و مزایای زبان برنامهنویسی (++و
ا ا اا يت
Oy
صفحه 11:
:هدفهاى رفتارى
0 مىرود 2000 يايان این حلسه بتوانید:
- مزاياى زبان ()2++ رابر زبانهاى مشابه ذكر كرده و
تفاوت آن را با زبان ) بیان کنید.
PPE ET OST Se MEY Se oe ae Ee
رابيان كرده و مشكلات هر دوره را به اختصار شرح
دهید.
1 SMB ENP eI as bee
- اصول سهگانهةً شیگرایی را نام برده و هر یک را به
اختصار شرح دهد. >
صفحه 12:
000 Lege enn] Peay arene ned De OTe) pte Cena Ce
م SER Tepe Tey
PEL e Tew Ee 0 SUC NT TY Sy eas eae
برنامهها استفاده کنید.
- نحوهّ اعلان متغیرها و شیوهٌ مقداردهی به آنها را بدانید.
- سه موجودیت د«لیترال» «کاراکتر» و «عدد» را شناخته و فرق بین
آنها را شرح دهید.
- علت و شيوههاى افزودن توضيح به كد برنامه را شرح دهيد.
- علت و شيوةٌ معرفى ثابتها در برنامه را شرح دهيد.
صفحه 13:
مقدمه
در دهه ١917١ در آزمايشكاهدهاى بل زبانى به نام © ايجاد
شد. انحصار اين زبان در اختيار شركت بل بود تااين كه در
ا 2-0 Ree
زبان منتشر شد و به سرعت نظر برنامهنویسان حرفهای را
Ey aed
هنگامی که بحث شی گرایی و مزایای آّن در جهان نرمافزار
رونق يافت. زبان 0 كه قابليت شى كرايى نداشت ناقص به
نظر مىرسيد تا اين كه در اوايل دهة ١9/8٠١ دوباره شركت
as Cl at ata eds) Ce Renn INE) ل 0 0 ل
طراحی نمود
صفحه 14:
OTe SEB pacman ioe] ی
شیگ رلیین یز دلشتاز آتززمانبه بعد شر کهای
Fon aye pelle eer yan pn yh Te
وجود بیاید و از قابلب تس از گاربیو لنتقال] نک استه
2
شود.
به همين دليل در سال ۱۹۹۸ زبان ()++ توسط موسسة
ene eeo] Relet ل ل 0 0
يك يارجه درآمد.
صفحه 15:
1-جرا 0 ++؟
Obj SO obj” رت
<در این زبان عملگرهایی تعبیه شده که برنامهنویسی
سطح يايين و به زبان ماشين را نيز امكانيذير مىسازد
ا را(
اين زبان بسيار كوتاه است
صفحه 16:
< -زبان ) براي اجراي بسياري از دستوراتش از توابع کتابخانهاي
استفاده ميکند و بیشتر خصوصیات وابسته به سختافزار را به اين
۳ Se
برنامة مقصدي که توسط كامپايار هاي ) ساخته ميشود بسیار
فشردهتر و كمحجمتر از برنامههاي مشابه در ساير زبانها است.
۱ 0 0 ل ا ا Ole
بردم لست
< و سرانجام آخرین دلیل استفاده از ()++ ورود به دنياي #0 است.
صفحه 17:
"- قار يخجة 10+
در دهه ۱۹۷۰ در آزمایشگاههای بل زبانی به نام © ايجاد
es ewe noe) weve eae) ا Pe Oye) ey
ا 0۱۰۱ Pere
SRE AB ا ae eee تا
ا ا ا Been RCS Ce eno fe Roe
ee Tee eee ROMKS) Sm nC ST SBS.) Dee) d
نداشت ناقص به نظر میرسید تا این که در اوایل دهة ۱۹۸۰
دوباره شر کت بل دست به کار شد و ©18[3112
۱
صفحه 18:
ب+ ترکیبیاز دو نبان ۵ و ان بود و قابلیهای
شجريئنيز دلشطز تنزمانبه بعد شركهائزيادى
كاميايلرهايىبرلى 0 ++ طرلحمىكرهند ليزلمر سبب
شد ت-فامهایی یب ا دن
بيايد و از قابليحتسانكابىو لنتقلل]-نكاسته شود.
به هميرجليزدر سلل99! نبان0)++ توسط موسسةً
لستانداردهاىملى]مريكا (00081©) به ش كإ[يستاندارد
ويتمابيه درآمد كاميايلزهاىكنونى به لين
لستاندارد يايبندند كتابهاضر نيزبرمبتاىهمين
لستاندارد نكابشيافته لست
صفحه 19:
2
اإيى «برنامه» دستورالعملهاى متوالى است كه مى تواند
توسط يك رايانه اجرا شود. براى نوشتن واجراى هر
dob به یک «ویرایش گر متن» و یک 9 احتیاج
داریم.
۱
نمونههای جالبی از محیط مجتمع تولید برای زبان /)++
به شمار میروند.
صفحه 20:
0 —F
ار را لستيعني8) و ه- 7 Oi
يكونمدلند Vy
مثال : اولین برنامه
۱ oars MLN pment)
Bree
NNN eS eee mcecharsid
م9
SI ce ee UR ara cca AN } م
aN acd 0
{
صفحه 21:
اولین خط از کد بالا یک «راهنمای پیشبر دازنده»
ا ار
-١ * كاراكتر # كه نشان مىدهد اين خطء يك راهنماى
پیش پردازنده است. این کاراکتر باید در ابتدای همةٌ
خطوط راهنماى يبش يردازنده باشد.
0
> نام بى دفايل كتابخانهاى» كه ميان دو علامت < >>
ین(
صفحه 22:
اين خط به كاميايلر ميكويد كه «بدنة اصلي برنامه» از كجا شروع
ميشود. اين خط داراي اجزاي زير است:
aul +4+O كت" | ew ed)
1۳ OM Ke ل ا nr rep rere!
Re Re hr rep ea Ors RECT) Ib Bertier)
صفحه 23:
خط آخر برنادء. «بدثة اصلى . . را تشکیل میدهند
دستورات برنامه از خط سوم شروع شده است.
دستور خط سوم با علامت سميكولن : يايان يافته است.
صفحه 24:
توضيم
<توضیم. متنى است كه به منظور راهنمايى و
درک بهتر به برنامه اضافه مى شود و تاثيرى
در اجرای برنامه ندارد. . کامیایلر توضیحات
ری ۶۱
< استفاده از توضیم سبب میشود که سایر
افراد كد برنامة شما را راحتتر درك کنند.
صفحه 25:
به دو صورت میتوانيم به برنامههای ++ توضیمات اضافه کنیم:
bill Sal cure 99 jl old La - >
متتی که بعد از دو علاهت اساش بیلید تا بایان
همان سطر یک توضیح تلقی میشود .
هر و ۳
علامت /: شروع شود و با علامت */ پایان
یابد یک توضیح تلقی میشود.
صفحه 26:
۵- عملکر خیوجی
علامت << عملكر خروجى در 0+ ناه دارد (به كن عملكر
درج نيز مىتويند).
ee] ا ا ا 6 م2
۳
Os ری مت مر نی خرس
|
[oe haa ye
مقدار ۶۶رابه خروجی اجه میفرستد که انح معمولا به
صفحهنمايش اشاره دارد. در نتيجه مقدار *؟ روى صفحه نمايش
درج مى شود.
صفحه 27:
2000
يك « »© رشتداى از حروف. ارقام يا علايم جايى استحد كه
ميان دو علامت نقل قول " ' محصور شده باشد.
GY > »یک هرف. رقم یا علامت قابل هاب است كه
ميان دونشانة '' محصور شده باشد. پس 7 و ۲۲و ۱ هر
کدام یک کاراکتر است.
به تفاوت سه موجودیت عدد» و «کارکظر» و «لیترال
رشتهاى» دقت كنيد: » يك عدد اسح '' يك كاراكتر اسحءدو
Neetu 52
صفحه 28:
/ - متغيرها و تعريف آنها:
«متغير» مكانى در مافظه است كه مهار مشخصه دارد:
202020602020606 .وقتى متغيرى را تعريف
مىكنيم. ابتدا با توجه به نوع متغير. ادرسى از حافظه
در نظر كرفته مىشود. سيس به آن آدرس يك نام
تعلق میگیرد.
صفحه 29:
در ++ قبل ازاين كه بتوانیم از متغیری استفاده ی
1
نحو اعلان یک متغیر
ANON She ۱۷
عبارت عمرةنوع متغير را مشخص مى كند. نوع
متغير به كاميايلر اطلاع مىدهد كه اين متغير جه
ل ال OE Ae eee
روی آن انجام داد.
صفحه 30:
عبارت حححه نام متغیر را نشان میدهد. این نام مداکتر
مىتواند اللا كاراكتر باشد. نبايد با عدد شروع شود. علايم
رياضى نداشته باشد و همهنين «كلمة كليدى» نيز نباشد.
مقداردهی اولیه
عبارت عدداندةاه: عبارت «مقداردهى اوليه» نام دارد. با استفاده
ازاين عبارت مىتوان مقدار اوليداى در متغير مورد نظر قرار
۰
دستور زير تعريف يك متغير صحيح را نشان مىدهد:
5 لك 10
صفحه 31:
- مقداردهی او لیه به متغیرها
در بسیاری از موارد بهتر است متغیرها را در همان محلی که اعلان
میشوند مقداردهی کنیم. استفاده از متغیرهای مقداردهی نشده
ممکن است باعث ایجاد دردسرهایی شود.
دردسر متغيرهاى مقداردهى نشده وقتى بزركتر مىشود كه سعى كنيم
متغير مقداردهى نشده را در يك محاسبه به كار ببريم. مثلا اكر »درا كه
مقداردهى نشده در عبارت © + ,د > بر به كار ببريم. حاصل برغير
قابل بيشيبينى خواهد بود. براى اجتناب از ينين مشكلاتى عاقلانه است
كه متغيرها ر! هميشه هنكام تعريف. مقداردهى كنيم.
a
۷ 209:
:جره
صفحه 32:
-٩ ثاتها
در بعضی از برنامهها از متغیری استفاده میکنيم که فقط یک بار لازم ۱ i
مقداردهی کنیم و سپس مقدار آنن متغیر در سراسر برنامه بدون تغییر باقی
میماند. مثلا در یک برنامعٌ محاسبات ریاضی. متغیری به نام ۱<) تعریف
مىكنيم و لن را با عاا.نا مقداردهى مىكنيم و مىخواهيم كه مقدار اين متغير در
TN ا ل ا ا ل ل 0ك
يك .يك نوع متغيراست كه فقط يك بار مقداردهى مىشود
د 1ن آن در ادامة برنامه ممكن نيست.
تعريف ثابتها مانند تعريف متغيرهاست با اين تفاوت كه كلمه
كم = shila ا ل 0
صفحه 33:
مثال تعریف ثابتها:
fot wuia()
I oo INN CoN AAU ACH
Daca haan miele eet ca
رت م۱ ROU A Aer noel تک
Pract ras MODOC ONC جر ار
ات ما
)۳۱29 9
retura OD;
0
ل لك
صفحه 34:
CS Bee
براي اين كه بتوانيم هنگام اجراي برنامه مقاديري را وارد کنیم از
SESE D TIS Arts 0
3
od دور << واو
حاطنس.: ناه يكستغير لست
صفحه 35:
ات تن
مس
ا Peek (one
ا
Ma كعدوا ۳ >> انوس
صفحه 36:
عملگر ورودی نیز مانند عملگر خروجی به شکل جریانی
رفتار میکند. یعنی همان طور که در عملگر خروجی
میتوانستیم چند عبارت را با استفاده از چند عملگر <<
|
میتوانیم با استفاده از چند عملگر >> چند مقدار را به
|
Faye)
abies ا ا
ae bead ا لل ل ل ا 0
ee ee eel el eee ا ا ل يي لل د
Mere pen) ل ال 0 ا اال 1
IDE Tey ae econ nee 1
صفحه 37:
مثال ١ - ١١ جند ورودى روى يك خط
1۳ ل On eae see Le
از ورودی گرفته و همان اعداد را دوباره در خروجی نمایش
مى دهد:
رم
صفحه 38:
(0
صفحه 39:
صفحه 40:
آنچه در ابن جلسه می خوانید
(- انواع دادةٌ عددی
1 متیر کب eee
le محاسبات اعداد صحيح
ا 0
3- عملكرهاى مقداركذارى مركب
7- انواع مميز شناور )ا
صفحه 41:
|
اا 0
book oy 2, ~'
Ns a زرا
ا 2 سر مرس
200101117
>?
صفحه 42:
با 0
| - سرريزى عددى
0 RCTs) rena)
-|١7 حوزة متغيرها
صفحه 43:
امعرفیر زواع Te) Ria 0
ا ا مشحیح در +برانام ببریدو
شعت اا ل هارا اه ار رك
ie ل ل ا ال 00
Se ne BNL era) ال لا لل ۱
- نوع بولین را تعریف کرده و متغیرهایی از این
۱ ل Sl
<<<
صفحه 44:
ed oD) eh Sie ۱۳ ازاين نوع
را در برنامهها به کار ببرید.
- مفاهیم «تبدیل نوع» و «گسترش نوع» را شناخته
Fa pe cee eI 1
rues Cee ا ا UPPER SERPENTS
رادانسته و بتوانيد محل وقوع آنها را كشف كنيد.
- عملكرهاى حسابى وافزايشى و كاهشى و
Be uCe ECB) ENT) ۱
صفحه 45:
مقدمه
ل ا ا لت
مى كنيم: اعداد . تصاويرء. نوشتهها يا حروف الفباء
صداهاء بوها و ... . بايردازش اين دادهها
el ET ا ا 2
SES) oon) ا الت ا Fae LD
قراراست همين كاررا انجام ات
دادههايى را بكيرند. آنها رابه شكلى كه ما تعيين
مى كنيم يردازش كنند و در نتيجه اطلاعات مورد
صفحه 46:
(-انواع دادهة عددی
در ()++ دو نوع اصلى داده وجود دارد: «نوع
صحيح و «نوع مميز شناور». همة انواع ديكر
FOO a at lt idee ERC Ce EL
دقت كنيد).
ساب
صفحه 47:
نوع صحبح
2 براى نككهدارى اعداد
صحيح (اعداد ٠ و ١ و " و...) استفاده
Ces ee nee et Tee)
به کار میروند و دامنه محدودی دارند.
صفحه 48:
صفحه 49:
نوع ممی شناور بای نگهداری اعداد اعشاری اسستفاده میشود.
اعداد اعشاری بیشتم برای اندازه گیمری دقیق به کار میروند و
دامته بر رگاتری دارند. یک عدد اعشاری مفل ۳6۲/۱۸۷ را
میتوان به شک[ ۷۳۹۳/۱۸۱۰ ۳۹۳/۱۱۰۱۲ ۸۷ ب۱"
۰ ۰ و با ... نوشت.
به این ترتیب با کم و زیاد کردن توان
عدد ۱۰ ممیز عدد نیز جابهجا میشود. به
همين دليل است كه به اعداد اعشارى
«اعداد ore 9 0 كويند.
صفحه 50:
عتغیر عدد صحیح -6
7 ey DSS per rary Se fe ا
| eee ele ah ee
محدودةٌ مقاديرىواسمنكه هر كدام ميتولنند
دلشته باشند
این ا eR EST Se SEES
ee ae BIS ere RCL Re arn) سا
عامل دارد. يعنى ممكن است روى يك رايانه, نوع
ا دو بايت از حافظه را اشغال كند در حالى كه روى
رايانهاى از نوع ديكر نوع ابه جهار بايت حافظه
520030006
صفحه 51:
حداكثر مقدار قابل | حداقل مقدار قابل ۳
روم و رگ گرگ 2 ۶5
وقتى برنامهاى مىنويسيد.ء توجه داشته باشيد
000 ron pera cer Ser ree ete)
FOOWOnE DEES STE NEU ep ESE Ope
للاراهدر ندهيد. لام
1ك wy ك1 1۳1۳۳1
999
APP Pose =
0 93
FS
صفحه 52:
۳ RY fe On Eee
)++ مانند اغلب (بانهاى
برنامهنویسی برای محاسبات از
عملترمان مسع (ج) ر تفریق (-) ر
ضرب )4( ess s )7( ر بافیداندد
استفاده میکند.
صفحه 53:
eS g nt 551 cla Klos — F
براىدستكارىمقدار متغيرهاىوصحيح دو عملكر ++)(
ما ار
اما هر کدام از این عملگرها دو شکل
متفاوت دارند: xe » PSS
000 1
a KS
RUS WORE ies Teen pee Tee eH
صفحه 54:
ذر شكل ر زر اند منعیر ماس
i eae
CUP (oly yaks aed yl
ورگ عاذ همل شوه : 1 =
سل 7227 انتذا مقدار متعبر در
محاسبات به کار میرود و بس از ان
مقدار متقی ر بتک واه و افزای ش را
کاهت م باند.
صفحه 55:
++ عملكرهائديكرئدارد كه مقداركذارئدر
ا الس ل ا ال
عملكر +- موتولنيم هشر واحد به ب لضافه
end rend ا لا
Local, gtd Jolee UL poi
این تفاوت که کوتاهتر است. به عملگر +- «عملگر
- مرکب» میگویند زیرا ترکیبی از عملگرهای + و
08
صفحه 56:
عملگر هایقدل رکنلووع رکب 5
قبلا از عملكر - براى مقداركذارى در متغيرها
استفاده كرديم. )++ عملكرهاى ديكرى دارد كه
مقداركذارى در متغيرها را تسهيل مئنمايند.
م ار
| 0
صفحه 57:
نحوة عمل اين عملكرها به شكل
ل
||
sw
صفحه 58:
0 ta
eee eT Poa UOe 7 | re ere ECs
7 7 ree Bam a)
رایانه ذخیره شود. ابتدا باید به شکل دودویی تبدیل شود:
199.۳9 < 0000.00 001
۱
سمت راست ممیز منتقل میکنیم. البته با هر جابجایی ممیز. عدد
حاصل باید در توانی از ۲ ضرب شود:
499.9 2 *
OY Ur sie cae nl Levy edo le
39,20 48S en al 93 59) Wg
صفحه 59:
در Cos aw ٠ ممیز ناور وود دارد:
انواع ممیز شناور
نوج acer ea
عدد استفاده میکند.
2
ار
صفحه 60:
جدول تخصيص حافظه براى متغيير هاى مميز شناور
تعداد بیت برای ذخیرهسازی
الا سس ۳ اس ۳ سس
فوع متغیر
ها بیتی
double OF
(Cre
صفحه 61:
Tee Se eee |
ام
od ام
lm Acie
double x,y=O;
صفحه 62:
اعداد مميز شناور به دو صورت در ورودى و خروجى
نشان داده میشوند: به شکل.«ساده» و به شکل
«علمی».
.۲ ۳ علمى- ©
1 9997
مشخص است كه ا
دادن اعداد خيلى كويت و همينين siacl
ا |
35
صفحه 63:
٩ - نوع بولین اس
این نوع فقط میتوانند مقدار ۲۶ با ۳۵۲
vec ae eee) 0
معنى نادرست است.
اما اين مقادير در اصل به صورت ١ و - درون
رايانه ذخيره مى شوند: ١ براى 057و ١ براى
Pate
صفحه 64:
وق یت
یک کاراکتر بک حرف. رقم با نشانه است که یک
شمارهة منحصر به فرد دارد. به عبارت عامبانه. هر
کلیدی که روی صفحه کلید خود میبینید یک
کاراکتر را Olas, میدهد.
مثلا هر یک از ae 0 تا ابا و ر ‘a تال و هر
یک از اعداد "۰ تا 54 هی نا
روی صفحه کلید را یک کاراکتر =a
صفحه 65:
1 ne epee
کلیدی 2۵7 استفاده میکنيم. یک کاراکتر باید
درون دو علامت آپستروف 7
باشد. پس () یک کاراکتر است؛ همچنین ۸"
ار( ره را
یک عدد صحیح است .
Ue,
thar 7 2007
صفحه 66:
0002
يك نوع شمارشى يك نوع صحيح است كه توسط
poe ws س ترد تسر تتريت بك نرق
شمارشی به شکل زیر است:
TNT ار در ره
on eed pened ۰ ۶
ee eS Cay Way ee 2 TINA ett
رم ل
صفحه 67:
به عنوان مثال به تعريف زير دقت كنيد:
0301١ , 60707 , 026007 POC OEO MIND, ERT, ره( مسمم
امه اف دب ای Pia
59 جدبد ر.زا) و محدوده Sor ر
ی من تس aoe مت رت
> ۱
کر از نوع ر را تعریف شدهاند. آنگاه ار
بامقدار 700200 2و2 ا DAD DE
مقداردهى شده است.
صفحه 68:
میتوان Presb) fence elo كم رابه شمارشكرها
نسبت داد:
Ow
همچنین دو یا چند شمارشگر در یک فهرست
میتوانند مقادیر یکسانی داشته باشند:
(0,00-0- :1:00:00 4- 00ج ٠ ()- ا نا را(ز):), (0- 0 ()) وسح 9 «سحم
ااانا
DODO, POE, OEO, PLY, CR} راف
> ee ee ee ee eee Y oe ee ۱۳ | | ee rs
۳۳۲۲۳ 7 re
صفحه 69:
نحوةٌ انتخاب ناموشمارشكرها آزاد است اما بيشتر
ا ا ا
| - برای نام ثابتها از حروف بزرگ استفاده
ناکنشمارشگر باید معتبر باشد-
eye sere Te een ag
۷ ا
21000005
eed ا ال
صفحه 70:
شمارشگرهای :ام تباید در محدودههای
مشترک استفاده شوند. برای مثال تعر یفهای زیر
را در نظر بگیرید:
eau )سرت 69۱۵۵, ,00[
pun Croup, B,C}
دو تعريف بالا *.ر :از است زيرا شمارشكر 00 در
ا 0
صفحه 71:
ا eae للم
DIC) ا ا ا ا PE
به توضيحات اضافى نداشته باشد.
مثلا تعاريف زیر مررر هستند زیرابه راحتی
تام و نوع کاربرد و محدوده مقادیرشان درک
مى شود:
ORPOGE) اه
۱ ۱(
۹( ی
pon Dorney o (۳07۱/۷ ۱۸۱۱۷
pre Brak {OOLE,PEOOLE}
صفحه 72:
وا
در محاسباتی که چند نوع متغیر وجود دارد.
جواب همیشه به شکل متفیری است که دقت
بالاترى دارد. يعنى اكر يك عدد صحيح رابا
سک عدد مسر اور عم 0 با
pe ream ere age pe 2 00
شناور را به نوع صحیح تبدیل کنیم از عبارت
0 0 نوع
گفته می شود
صفحه 73:
مثالهاى زير تبديل نوع و كسترش نوع را نشان مىدهند.
مثال گسترش نوع
پرنامةً زیر یک عدد صحیح را با یک عدد ممیز شناور جمع میکند:
اسمن
double udue: 0 ا اي 100
۸۰۶ 7
:9.0 2 م بل
تشه
pou << "pH" <<p <<" qe" << << pod
Peake
صفحه 74:
۳- برخی از خطاهای برنامهنویسی
«فطای (مان کامپایل»
an Oo re ار
ل ال رلك
آنها را رفع نمود.
«خطاى زمان اجرا»
کشف اینگونه خطاها به راحتی ممکن نیست و
keer tee eee Lely 2
خطاهای زمان اجرا سبب میشوند که برنامه به طور
با رت تر برس
صفحه 75:
-١6 سرريزى عددى
0 ا KUT peo) treed e
آن متفیر بیشتر باشد. اگر سعی کنیم در یک
۱۹ eo متغير
متغير فراتر باشد. متغير «سر ريز» مى شود.در
جنين حالتى مىكوييم كه خطاى سرريزى رخ
دادة است.
صفحه 76:
مثال ۱۳ - ۲ سرریزی عدد صحیح
۱
مر
۳ «گردانیده» میشود
ا از ۱
سرريز شود., نماد “ا به معناى
بىنهايت رابه دست مى دهد.
صفحه 77:
صفحه 78:
eowa aye 2ك
اصطلاح «بلوک» در ()++ وایه مناسبی است
که میتوان به وسيلة آن حوزة متغير را
مشخص نمود. یک بلوک برنامه. قسمتی از
برنامه است که درون بک جفت علامت
كروشه 1 محدود شده است.
eee a ee oz
ما
صفحه 79:
|02 nn Sle
میشود وتا پایان همان بلوى ادامه مى يابد.
خارج از لن بلوى نمى توان به متغير دسترسى
داشت. همچنین قبل از این که متفیر اعلان
شود oll Pel Spe را استفاده نمود.
مى توانيم در يك برنامه. جند متغير متفاوت با
1 يك نام داشته باشيم به شرطى كهدرا
صفحه 80:
يايان جلسه دوم
صفحه 81:
<¢ aa 5 اد
صفحه 82:
آنچه در این جلسه می خوانید
-دستور “ا
aa aT ee
ام 00 رت
ا 0
اا كت
-ارزیابی میانبری >>>
صفحه 83:
/- عبارات منطقى
4 - دستورهاى الك تودرتو
ا ا oa
اا د
۱ ۱- عملگر عبارت شرطی
(- کلمات کلیدی
صفحه 84:
koa ناه نی تکار وشيوة
یت e: زرا شناخته و آمن را در برنامهها به کار
Pee 0 noe ri پیچیده استفاده کنید.
Ferre AES Yer UCIT Ua Pee BEAU Toe Se
25
- بلوک دستورالعمل را تعریف کنید.
a WT Ome IAF BCS ete ال ا
شرطى به كار ببريد.
- از شرطهاى مركب استفاده كرده و ارزيابى ميانبرى را شرح دهيد.
- «كلمة كليدى» را تعريف كنيد. <<<
صفحه 85:
مقدمه
همه برنامههایی که در دو جلسه اول بیان شد. به
شکل ترتیبی اجرا میشوند. یعنی دستورات برنامه به
ترتیب از بالا به پایین و هر کدام دقیقا یک بار اجرا
eS bee) Oe Orne ge] Ey oP) 00
ا pete
Sis له
صفحه 86:
de) Ins
ره رم 000 ۴
رب_ ریگ که شرط ناسیده میشود بک عبارت
صحیح است (عبارتی که با یک مقدار صحیح برآورد
eel 7 eet eye IP) ۱
با ۳ اس اد در 3
ردم ری مقدار عبر صفر داشته باشد. دفت کنید که
شرط باید درون پرانتز قرار داده شود.
صفحه 87:
۲- دستور صاد. .1
دستور Rebbe مى شود بسته به اين كه
Ber) ل ل الل ا 37
اجرا گردد. این دستور به شکل زد
فرعى اجر! كردد. نإو اين «ستوع بع ۱۳2
9 9 1 7۳*۳77
فرمانهایقابل جرا هستند اگر مقدار شرط غیر
صفرباشد !..... . لجرا خولهدشد
وگرنه 6
صفحه 88:
۱ | Re Sens |e
70[
:0 لک 1
ا ا ا ا ال
e << و << بر
ا ل ا ل لضا
رس Sr of ere ie 5
صفحه 89:
ی
در (++ شش عملگر مقایسهای وجود دارد:. و
Se مد کت ارات و هر بت ازااین
شش عملكر به شكل زير به كار مىروند:
« کوچکتر از بلستتا بت«
بزر-گتر از 7 لستا/ ۸
« کوچکتر یامساویر لستاا رت :
«< بزر گر بامساویب لست// ,۰ -.-..:
> سات كا PAY Heal py
> مساووعبانیسار ح1 .:
صفحه 90:
اينها مى توانند براى مقايسة مقدار عبارات با
هر نوع ترتیبی استفاده شوند. عبارت حاصل به
عنوان يى شرط تفسير مىشود. مقدار اين
شرط صفر است اگر شرط نادرست باشد و غیر
pe wee y Rasen ge o) ۱
عبارت برابر باصفرارزيابى
مىشود.ء به اين معنى كه اين شرط نادرست
است.
صفحه 91:
عتغیر عدد صحیح -6
7 ey DSS per rary Se fe ا
| eee ele ah ee
محدودةٌ مقاديرىواسمنكه هر كدام ميتولنند
دلشته باشند
این ا eR EST Se SEES
ee ae BIS ere RCL Re arn) سا
عامل دارد. يعنى ممكن است روى يك رايانه, نوع
ا دو بايت از حافظه را اشغال كند در حالى كه روى
رايانهاى از نوع ديكر نوع ابه جهار بايت حافظه
520030006
صفحه 92:
دقت کنید که در ++ عملگر با
عملگر eee Slee mS EE
يك مساوى تكى " -"است ولى عملكر
برابری. دو مساوی " - - " است.
مثلا دستور DO = «۶ مقدار ۳۳را در JS x
میدهد ees) 00 99 ا الك
OSE ee ed oe ames wee ay
تفاوت اهمیت زیادی دارد.
صفحه 93:
۴- بلوکهای دستورالعمل
يك بلوك دس تورالعمل زنجيرداى از
دستورالعملهاست که درون براکت }{ محصور
شده. مانند :
} مها ۱
may
1 = tevop
۱
و 00 مانند 256 By
صفحه 94:
(QS تسم 4 Wl
ee)
00 ال رو زا ۱۳9۳
0 ات ان Sees cae
(مر< 6 ۸
1 Wan eae ncn 89a
له >> رر >> ۲ > ۲ >> و ک> ام
0
صفحه 95:
int wain()
- EPR
A ih ا ا
۱ 2
7 0
۲7۲ << ۲
زلجج >> و >> 2۲ و >> ابرم 1
۱ ا ا لي
صفحه 96:
Tea ae aa)
شرطهايى مانند و re) لت ا
oe لت ا ل ل لات
ازعملگرهای منطقی ری و فك (wot)
oe DSc ee REDE Te Rasy ۱
EE
درسنلستلاگر و تنهااگر هم وهم هر دو درسساشند
ا ا ا ا ا 0ك
درست است اگر و تنها اگر نادرست باشد
يز 2 0
اكر 900 براير صفر و كوجك تر از ب باشد.
صفحه 97:
Spe Pear و معمولا با
استفاده از جداول درستى به كونة زير بيان مى شوند:
©! م Ply و م +88۵ و م
تس 2 ۱ ۳ 4 4۳ ۳ TD Ay
cay 0001
۳ کر &€ ٩۳۲۹
طبق جدول = ز 2
ابه ماس © نا
درست است.
صفحه 98:
0 SS a
به دو عملوند نیاز دارندتا ۳
درستی «dd مقايسه راروى آنن د سم
ا ل عم حالت گفته شده. يا ارزيابى
عملوند اول به سرعت نتیجه معلوم میشود. این
کار . ...7 نامبده میشود.
صفحه 99:
fier.) bere) By Pe oad
یک عبارت منطقی شرطی است كه يا درست است
ال ee DEP اا ك6
معنای نادرست و هر مقدار غیر صفر به معنای
درست است. به عبارات منطقی هم
مى كو يند.
صفحه 100:
چون همه مقادیر صحیح ناصفر به معنای
تغيير قيافه مىدهند. براى مثال دستور
وقتى غير صفر است عبارت را
چاپ میکند زیرا عبارت منطقی وقتى
مقدار . غیر صفر است به عنوان درست تفسیر
رک ری
صفحه 101:
کد زیر را نگاه کنید:
ل ان جارج ب اج جز ب" >> انون ( 200
دستور خروجى فقط وقتى كه ناصفر
ا ۰( وقتى ناصفر
ممكن است فراموش كنيم كه عبارات منطقى
مقادير صحيح دارند و اين فراموشى باعث
ايجاد نتايج غير منتظره و نامتعارف شود.
صفحه 102:
یک خطای منطقی دیگر. این برنامه خطادار است:
( )ددص int
00 11 2
Prat A (ran ا
۱ woo
LOS eal wee) a Sen UH
i
منشأ خطا در برنامة بالا اين اصل است كه عبارات
منطقى مقدارهاى عددى دارند.
صفحه 103:
دستور ها عنتخابتودیتو 6۰
دستورهاى انتخاب مىتوانند مانند
دستورالعملهاى مركب به كار روند. به اين
ا 0 000
اين روشء جملات تودرتو مى كويند.
صفحه 104:
Ws
وقتی دستور -حا..:به شکل تو در تو به
کار مییود. کامپایلر از قانون زیر جهمت
تجزیه این دستورالعمل مر کب استفاده
نس تاد
.هر حطو با آخرین جفت مى شود.» 1
صفحه 105:
phe P bly —4
ee TCD ee at ا | ee
مجموعهای از حالتهای متتاوب یاموازی به
ebe rang Or مىرود. در این حالات فقط 01
شامل دستور بعدی خواهد بود. این قبیل
ا ل ا ا
صفحه 106:
ا 0 000
برنامة زير يك نمرةٌ امتحان را به درجهٌ حرفى معادل تبديل م ىكند:
)0 با
مت ۱۱
ied A ا De atk ce
(Sore > (00) cou << "Crm: the sore & out oP range”;
be P (sere >= OO) cout << "You wate & 00 @." << ead;
eee (sare >= CO) cout << "You gate & ©." << pod;
(Gere >= TO) rot <5 "Your gk & 1 0.” << ead;
BO) cout << "Your yates & oO." << ead => ۱
tiated) Doo nce A SS ۱
vat << "Cro: tot score ts vu DP raaw.")
صفحه 107:
er) id یر
دستور ,.... , میتواند به جای ساختار , ,, , برای
۱
به كار رود. نحو دستور . . . به شكل زير است:
صفحه 108:
ابن دستور ابتدا تسووومووو را براورد می کند
ay
عبارت یک عبارت اختیاری است.
ا 70 آن راقید Tene)
نكنيم. -20200 بايد به شكل يك نوع
هابايد 2 ١ صحيح ارزيابى شود و
9 تها کار ۳
ثابتهای صحیح باشند ,
cap ene)
fo a هاء. سم val
اس
صفحه 109:
۱ دستور
قرار بگیرد. بدون این دستور. اجرای برنامه
پس از این که مربوطه را اجرا کرد از
دستور وت نمیشود. بلکه همةً
های زیرین را هم خط به خط میپیماید
و دستورات مقابل آنهارا اجرا میکند. به
۱
PAPAS SNC e aer ae OR 1
صفحه 110:
1- عملگر عبارت شرطی
3 2
عبارت برابر با مىشود واكر
2 اا yr)
= میشود. 7
نشانههاى 12و ' كل زير استفاده مى كند:
ل ل لك
صفحه 111:
مثلا در دستور انتساب زير:
Qxiv } ركم ) = wia
اگر W992 ly glade WAL 2<<y نت قرار
میدهد واكر ر>:. نباشد مقدار .ب را درون
als <i مىدهد. يعنى به همین سادكى و
اختصار مقدار کمینة ::و :درون متغير
SESS قرار میگیرد.
صفحه 112:
ا Pp
Pe ar cen an Comer a Cone
أيك كلمة كليدى در يك زبان|
إبرنامهنويسى كلمهاى است كه از قبل |
اتعريف شده و براى هدف مشخصى |
sw! dud 7
با آمعراع ی 77 نوع۲ تن[ لک 7337777
صفحه 113:
qtr
كاد ال
Dust
dodouble
delete
صفحه 114:
اه
۲7۷
:
نله
ادن
wit
Dr
eprotevted
سم سم مس رها
منود
ost _ اد
اه
PROE
۱1199 ۰
صفحه 115:
rigid
صفحه 116:
دو نوع كلمة کلیدی وجود دارد:
۱
00
ك5 كلة رررو كد : كليةاى است كه رى دستور
Bere ا اك ا ان 2 ام
م ا 20077
يك شناسة استاندارد كلمهاى است كه یک نوع دادةٌ
استاندارد از زبان را مشخص مى كند. كلمات كليدى
إددطا و شناسههاى استاندارد هستند
صفحه 117:
پابان جلسه سوم
صفحه 118:
صفحه 119:
: آنچه در این جلسه می خوانید
کر را
'!- خاتمه دادن به يى حلقه
NPA ae
eae yee ae ie
OE eee) وا
7- دستئور 7712
۷- دستور 1۳۳
- تولید اعداد شبه تصادفی
صفحه 120:
re 0 ا از مطالعة این جلسه بتوانید:
-شخاخستینانلواع! فناخاخهاز های اتکیوار وتنهتوآکها و
ares Byte te ایک واگ ر| شناخته و تفاوت آن با دستور
while را بیان کنید.
- نحو دستور را شناخته و با استفاده از آن حلقههای
گوناگون بسازید.
- حلقههای فوق را به یکدیگر تبدیل کنید.
- علت استفاده از «دستورات يرش» را ذكر كرده و تفاوت
سه دستوز ا ل ل ل
- اهميت اعداد تصادفى را بيان كرده و نحوةٌ توليد «اعداد
شبه تصادفى» را بدانید.
صفحه 121:
dovio
"را احرای بی در بی یک دستور بابلوکی از
دستورالعملها در يك برنامه است. با استفاده از
تكرار مى توانيم كنترل برنامه را مجبور كنيم تابه
200 0 ا ل SPCC ce yee.
ب+ دارلیسه دستور تکرار لستدستور ...۰
gid 9 gw ۳۲
به علرمطبيعرجر خهمانند شا حلقه نيز ناميده
6
تست رت
صفحه 122:
el oer
به جای .یک شرط قرار میگیرد و به جای
دستورى كه بايد تكرار شود قرار مى كيرد.
سر مر ی 0
eG ۳3 بعد از
صفحه 123:
ا 000
اين برنامه مقدار ١ 7۰ 7۰ بر -.,- را براى عدد ورودى > محاسبه مى كند:
سم زر
Scns ies
0 (onc eh ee casi e ee
۳
0 7(
(۰ > طابر
00
Pe Nessa ed ec SSS en creo
<< an;
صفحه 124:
00
| eo 7 eC
اي لت ا سب
لك 001 cae
تنفاده اد
) ۶ )< a) breck;
ا ae
i
Pr Noe aan one ee ل
1
صفحه 125:
ese ee ea ee
۱ ارت ررق پا OPCS
معادلههای زیر تعر یف میشوند:
| اور تا وتا لا ۱
مثلا براى 1-2 داريم:
F,=F,,+F,,.=F,+F,=0+1=1
يا براى 1-3 داريم:
F,=F,,+F,,.=F,+F,=1+1=2
و برای 1-24 داریم:
F,=F,,+F,,=F,+F,=2+1=3
صفحه 126:
1 OTe D
ا 0
4 ا
7 سین 3 ay
ارات
se <<" << bound << ":\n0, 1"; نت
long f0=0, 4
raat .)1۳۷6(
f2 = f0 + fl; {
nt acl.) ل fe
eee ۰ 2
fl; زا
2۶۳ < ۲1
ی 1
صفحه 127:
odie (0) Pep ese YUL)
Pre ee Se ore eRe SE NON NE Mle pats EE SOND. 18 (0) 1
بلافاصله اجراى كل برنامه را يايان مىدهد:
اس
iat
Pea Sone ence Vcd ot ee
۱ arate nce
Dea BAS Coens ا oN SOD
بسا ۳۵۶۵, ۳2۵:
{ loo PO = PO + FA;
P (PO > bowed) ext(O);
pout <<", "<<PO;
PO = Pd;
بهم د مم (
صفحه 128:
متوقف كردن يك حلقة نامتناهى :
با فشردن کلیدهای 0۳۱*0) سیستم عامل یک
برنامه رايه احبار خاتمه مىدهد. كليد 001 را Perle)
نكّه داشته و کلید ()روى صفحهكليد خود را فشار
O 000
صفحه 129:
| را
۱
ات ال
AS ASA اهلد
م
اين دستور ابتدا 25-7264 را اجرا م ى كند و 7
شرط درست بود حلقه دوباره تكرار مى شود
و
و
1
صفحه 130:
دستور عالانب..ع مانند دستور علاربه است.
rae اين
Gale 45 Cowl lp Soda ١
هميشه بدون توجه به مقدار ٩<..بنطلاع
Soe eed) eee ا Bes
ماما حلقةٌ حانطار میتواند اصلا اجرا نشود. . ۰
ز نم رون
آن تنظتم 3p
صفحه 131:
و
eee ore Pee ence 1
مر
ل 0 1
Vice a ae ا A Cohn
صفحه 132:
PO Pppec Ce kes ee Wo
FREE ااا
زير تعريف مى شوند:
0۲-4 , ۱ - ارمیه
برای مثال. به ازای < « در معادلةٌ دوم داریم:
7ك 1010
همچنین برای 2 داریم:
2) 99
0
6۱ - 5) 5 215055 5
صفحه 133:
برنامةٌ زیر همةّ اعداد فاکتوریال را که از عدد داده شده کوچکترند. چاپ
میکند:
6
سا
Von oc لانن
joi >> bout
۱
۳
2
mews ۲
رسک ۲
i
white (P< bourd)
{
صفحه 134:
عبارت 05ص دبراى ييش-بردن متغير كنترل
حلقه به كار مىرود. اين عبارت يس از اجراى
210۷ ارز یابی می گر دد.
صفحه 135:
بنابراین زنجيرة وقايعى كه تكرار را ايجاد میکنند
عبارتند از:
| - ارزیابی عبارت له
۳ -بررسی شرط .._.. .اگر نادرست erie)
ee ا ري يد 7
a صهلبعبارتهای اختیاری هستند. یعنی
مى تواني آنها را در حلقه ذكر ذ awe
صفحه 136:
eer See Ree oe meen a Cael on heen Mele)
اين برنامه همان تأثير مثال ١-ه را دارد:
الا
{ فش
۱ ی
كا eaten
foag su=O;
<=
regen pene 7 als Fae rye e ا ال
ey as مىشود (مانند ادر مثال بالا) حوزةً آلن متغير به هان
ا متا ocd eee eC
۳ نتبجة دیگر این است که میتوان از نام مشابهی در خارج از حلقةً
0000 dy soe cep eee Te eT pe)
صفحه 137:
مثال ۱۲ Ie و
برنامة زير ده عدد صحيح مثبت مثبت را به ترتيب نزولى جاب مى كند:
صفحه 138:
۱
دارد: Oe SIDE CLIPS a et tie
اه نز
Por (at w=OS, v=, w%u > O; w -= 9, ot +) {
ل Sy ا ل 0
/
صفحه 139:
م ل PPPS
ا ل 1م
|
صفحه 140:
35
et) ا
وقتى دستور و درون
فا
روی حلقهای که مستقیما درون آن
|
حلقههاى بيرونى بدون هيج تغييرى
ai
دهد.
صفحه 141:
332 سا ها
دستور Oa تورهای درون بلوک
حلقه را نادیده گ این دستور بیرون
57 این 2 م
رالغو كرده و اجراى دور
۹ بعدى حلقه را آغاز م ىكند.
صفحه 142:
ST Eee A neem Ed دمم يما
ST eee TE eel] 10
iat wuin()
۳ ویر {
Ne ao
Por(; rt )
SS ee ESE
ا rout
vin >> ۳
م۱
میت
i
زو ا يي ل لا يي
Mi
صفحه 143:
۷- دستور اس
۱9 eee BC es Rey aren
تزسط مت برحسب ee) است, متسه
معين مى شود.
برجسب شناسهاى است كه جلوى آنن علامت
eated ا ل ا ل
مى كيرد.
یک مزیت دستور ۰۲7 این است که با استفاده
ee reais | را زر
شد و به مكان دلخواهى در برنامه يرش نمود.
صفحه 144:
۱ سل از رم رت را
ist c7aini()
7
ار یا
cal Osi Os enim)
{ Por (ist K=O; K<@; K++)
iP (FARO) pte esr;
fee ar a ا
ارو
1
ا تا
j
i
صفحه 145:
2000 Reo ere
ee LD oe) en SSS) ne ee)
«شبیهسازی» سیستمهای دنیای واقعی است.
تحقیقات و توسعههای بسیار پیشرفته به این
راهکار خیلی وابسته است. به وسيلة شبيهسازى
میتوانیم رفتار سیستمهای مختلف را مطالعه
کنیم بدون این که لازم باشد واقعاانهارا
پیادهسازی تماییم. در شبیهسازی نیاژ اسست
G توسط رایانهها توليد شود FEE ey اعدا
نادانستههاى دنياى واقعى مدلسازى شود.
صفحه 146:
رايانهها «ثابت كار» هستند يعنى با دادن دادههاى
مشابه به رایانههای مشابه. هميشه خروجی یکسان
ل ا ل ل يت
كرد كه به ظاهر تصادفى هستند؛ اعدادى كه يه طور
یکنواخت در یک محدودة خاص گستردهاند و برای
ploS qu الكوى مشخصى وجود ندارد. ۳
Peel Ree DL heed De MP ETD De |
صفحه 147:
ar} توليد اعداد شبه تصادفى
اين برنامه از تابع 4-(() براى توليد اعداد شبهتصادفى استفاده مى كند:
#include<cstdlib>//defines the ۳۵۳۵ 0
RAND_MAX
#include <iostream>
int main(),
{ // prints pseudo-random numbers:
for (int i = 0; i < 8; i++)
cout << rand() << endl;
cout << "RAND MAX =" << RAND MAX << endl;
}
هر بار که برنامة بالا اجرا شود. رایانه هشت عدد صحیح
2 تولید میکند که به طور یکنواخت در فاصلةً ۰ تا
)1٩61201(6(_۷ گسترده شدهاند. 629 _606060) در این
رابانه برایر با ۲:۱۲۴۷,۴۸۳:۶۴۷ است.
صفحه 148:
هر عدد شبهتصادفی از روی عدد قبلی خود ساخته
میشود.
اولين عدد شبهتصادفى از روى يك مقدار داخلى
که« . . گفته میشود ايجاد میگر دد.
هر دفعه که برنامه اجرا شود. هسته با یک مقدار
:10000
براى حذف اين اثر نامطلوب كه از تصادفى بودن
اعداد مى كاهدء مى توانيم با استفاده از تايع sraad()
خودمان مقدار هسته را انتخاب كنيم.
صفحه 149:
۳3 دعر له Vanes.) | طور
محاورداى
اين كه مىتوان هستة توليدكنندةٌ اعداد
تصادفى را به شكل محاورداى وارد نمود:
صفحه 150:
پابان جلسه جهارم
صفحه 151:
صفحه 152:
آنچه در ابن جلسه می خوانید
۳ توابع كتابخانهاى ()++ استاندارد
'!- توابع ساخت كارير
۳ برنامةً آزمون
۳- اعلانها و تعاریف تابع
کامپابل جداکانة توابع
7 یرس محر تایه نی
صفحه 153:
را
توارع بولق
ا ا 46
-١ ارسال به طريق ارجاع (درس)
۱ - ارسال از طریق ارجاع ثابت
1
)>
صفحه 154:
Eee ee le
0 كك ني
00 to) a
صفحه 155:
هدفهای رفتاری؛
ا ا 7
neu «تعريف» ee را بدانيد و خودتان توابعى را ايجاد
PolPen prem ip ISS arr I OVEN RpCarer Septal DiTUye ey Oper
peer ben) مفهوم دآ ركومان» -
- تفاوت ارسال به طريق ى «ارجاع» و ارسال به طريق «مقدار» و
ارسال به طريق «ارجاع ثابت» را بيان كنيد و شكل استفاده از هر
يكد را بدانيد.
200
صفحه 156:
- «تابع ی را شناخته و نحوةٌ معرفى bol
۳
- جندشكلى توابع را تعريف كنيد وشيوة آلن را
بدانید.
- طریقة به کار گیری آر گومانهای پیشفرض را
صفحه 157:
( سرتررد
برنامههای واقعی و تجاری بسیار بزرگتسر از
برنامههايى هستند كه تاكنون بررسى كرديم.
برای این که برنامههای بزرگ قابل مدیریت
باشند. » gi dol 7 7
a TP ed Le BB] بندى مىكنند. اين
زيربرنامههها «تایسع» Pewee) مى شوند. توابع ۳
ree) ا 0
lado» y> ل ا 0 ا
SS
صفحه 158:
وراه ردان زارد
1ه © استاندارد» مجموعهاى است كه
eerie) ل |
برنامه است. این توابع و عناصر از طریق «... »
قبلا برخی از آنهارا استفاده کردهایم: ثاببت
"1011-١1 كهدر < ١ > تعريف شده.
تابع ()021< كه در < 20١ > تعريف شده است
wed
صفحه 159:
200 نسدد
00 ERC-Tul eke OMT E RC TES) ريشة دوم
تابع 20000 كاملء داراى روند ورودى -
پردازش - خروجی است هرچند که پردازش.
مرحلهاى ينهان است. يعنى نمىدانيم كه تابع روى
عدد ۲ چه اعمالی انجام لي كي رك إل رسن كنا
حاصل میشود.
صفحه 160:
برای اجرای یک تابع مانند تابع اجح() کافی
reese ae a eel fr noe |
00 ا ESL oe USER TONG Ces py eery
p=sqnt(x);
صفحه 161:
م تاییع» با اخضار تابعة گفته
ye Tee) ا ال ا ل 1ت
6 فراخوانی میگردد. عبارت درون پرانتز
Reel nae pe pC 7 OSL ETC
et ll oe RR al DEE ed
«مقدار» به نت فرستاده مى شود. BY} وقتى )
است, با اجراى كد ()1»< تابع 0<() فراخوانى
شده و مقدار ۳ به لن فرستاده میشود. تابع مذکور
نيز حاصل 2-2 رابهعنان ياسسخ
برمى كرداند...
صفحه 162:
ا 0
رم نج
5
متغيرهاى « و بر در تابع ۵() تعریف شدهاند. مقدار « که برابر
با ااست به تابع #4() فرستاده مىشود و اين تابع مقدار
۵ .را به تابع ل ا ا 000
را نشان مىدهذ به رنك تيره است, به اين معنا كه فرايند داخلى و
ا 5 05957
صفحه 163:
۱ ا any]
اين برنامه هم از سرفايل <21ك> استفاده مىكند. هدف اين
است كه صحت رابطة +«وم0.م:8) 6-,:92ج:8) به شكل تجربى
بررسى شود.
سم
Por Poa x=O; x < S; x += O.C) {
rout << x << "WW" << (G*x) << "WF"
>>( رم 2۳ >>
صفحه 164:
io لان
0 0
خروجى نشان مىدهد كه براى هر مقدار
ا DNC
>ود 708510 برابر است.
0
۷
ده تا
سر ۳۱۱۱۹
جاب میکند. ORE ۳
act
0
ری
ae
9
۳9
صفحه 165:
i a Sc م Tee
ریت شده است. بعفيى إن لين ae
را ee
00 ا ل
asin(x) 1, 0.201358
aie سينوس معكوس + ابه راديان)
(8830)0.2 مقبار
atan(x) 1, 0.197396
بر تنزانت معکوس (بهرادیان)
ceil (3.141593)
ceil(x) 0 aie
5 0 cos (2)
cos (x) 1,0.416147
در رط کسینوس (به رادیان)
suis exp (2)
صفحه 166:
floor(x مقدار كف (كرد floor(3.141593)
مقدار 3.00 را برمیگردلند شده) )
۳۹
0.693147 ,| لگاریتم طبیعی عد (در و۱0
بسرمیگردلند پایه ع)
rere jus Log (2) لك
۹ [
pow(x,p 1, 8.0 ,vi pow(2,3)
جردا نه «به تولن )
صفحه 167:
7 ay Spee Corser EES
lee eae ea eee SD نوع
تابع فرستاده شود, قبل از اين كه تابع ان را يردازش
yl 3 ۳ ۳۳ eS میدهد.
صفحه 168:
۵
0 بع" ,عي :۶
715۳5
این سرفايلها از كتابخانة ) استاندارد gee
شدهاند. استفاده از آنها شبیه استفاده از
سرفایلهای )++ استاندارد (مانند
> >> ) الست. براى مثال اكر
بخواهیم تابع اعداد تصادفی له را از
سرفایل <2ت> به کار ببریم. باید
دستور پیشپردازندةٌ زیر را به ابتدای فایل
برنامةً اصلی اضافه کنیم:
۸ ۸۱ | ۸
<vstdlib> مش
صفحه 169:
رد تب نات در
كرجه توابع بسيار متنوعى در كتابخانة HHO
استاندارد وجود دارد ولى اين توابع براى بيشتر
وظايف برنامهنويسى كافى نيستند. علاوه بر اين
برنامهنویسان دوست دارند خودشان بتوانند
توابعی را بسازند و استفاده نمایند.
صفحه 170:
eat eo Ole
Pye Cgoes rt eas Sane | oy
tat دك )عطي
1 00 ate eS
ca ed
return کرک
صفحه 171:
یک تا
بع سا< 3
خت کاربر دو ق
لح
0 ee Sirs) ers
3 چم
| 0
من
صفحه 172:
رم روص و۲۳ ae عمده 1
اجراء ل 35 ل * اه م 5 1 ae 0
نها eee 7 ور
pq استفاده eh» et oe od
اصلى» را تعريف مى كند. نوع باز كشتى
اين تابع از نوع 9 است. نام آلن 5د
ا ا كه
ست؛ يعنى هيج يارامترى ندارد. وع
سس
= 3 Ass
صفحه 173:
بسرنامة Paygasd
تنها هدف این برنامه. امتحان
كردن تابع و بررسی صحت
بر = - 2
برچسبها و راهنماهای خوانا - را لحاظ کنید.
صفحه 174:
مثال ۵-۴ یک برنامهةً آزمون برای تابع علح()
Pome elmer SIKH SEN) AC en eee EC?
tot mube(int x)
برنامهً حاضر اعداد صحیح
رااز ورودى Eyre)
مكعب انها راجاب بر و
ف كلد شااكن كه كارير
مقدار ٠ را وارد كند. ict coin)
aco O Osc Cac 0000
20 ۱
white (a |= O)
eras
rat << "\imube(" << a <<") =" << pube(a) << eo); }}
صفحه 175:
هر عدد صحیحی که خوانده میشود. با استفاده از
( به تابع Orbe فرستاده مى شود.
۱ 0 ام ان و ۰ 52
دقت كنيد كه on Fan EO AC ar تعریف
RO eee et ce Cae CLs Tees
رودء كاميايلر (00++ بايد در بارةٌ آن اطلاع حاصل كند.
main() cube()
ع 5
۳ ۳ ۰ بین لتك ا آل
aly a تصور نمود:
صفحه 176:
(eed ae eer aL A pene ee WO
تابع زير دو بارامتر دارد. اين تابع از دو مقدار فرستاده شده به آن مقدار بزركتر را برمى كرداند:
سوت سم ها
را EN ea ee
2
Sl tel Coe
2 ما
صفحه 177:
رت
(شبیه دستور . . )زیرااجرارابه
ee و ی اگرچه
معمولا ١ 2020202 درانتهاى تابيع قرار
95۱ 9
دیگری از تابع قرار داد.
صفحه 178:
۵- اعلانها و تعار بف تابح
به دو روش ميتوان توابع را تعريف نمود:
ا ال تن
مربوطه اورده شوند.
اه دیگری که بیشتر رواج دارد این گونه
1
0
قرار بكيرد.
صفحه 179:
لد لا تسایس ات مه لس اد
اعلان تابع شبیه اعلان مد رس
pe aid ole! مس
در انتهای آن قرار دارد.
ایک متغیر زر زر رب ور برن ردب ۱
.اعلان شود. تابع هم همین طور است یا این فرق
که متعیر (۱ در هر جایی از برفاعه میتوان اعلان
ترد انا تابم را باب قبل از برنامة اصلی اد رد
نمود.
صفحه 180:
te ae oly فقط Mahe oir
1 rene pee cape FL Pe Con peg Seen
كاميايل برنامه را آغاز كند. سيس در زمان اجرا
به تعريف بدنة تابع نيز احتياج مى شود كه اين
بدنه در انتهاى برنامه و يس از تابع 5ه<ت() قرار
می گیرد.
صفحه 181:
BC ee renee.
) متفیرهایی هستند که در فهرست
يارامتر يك تابع نام ا 6
See) ا ی
مىشوند؛ يعنى فقط در طول اجراى تابع وجود
۳
آ رگومانها متغیرهایی هستند که از برنامةً
اصلى به تابع فرستاده مى شوند.
صفحه 182:
:كارا )عدت لها
لمان
a
0-1
{ زو << مه << وو
rout << "\eax(" << 7 << ")"<< a >> "-"
CA >> الس (
صفحه 183:
۱ ترابع بهارساند 3 ۱2٩ eee) oe
پیادسازی شدداند ر سای كا یکی از آن. als را
در برناناءمايتان به كاز م بريد اند نش برر
راسشدای پیش بردازندد: ثایل آلبن توابع رابه
برتادا-تان بیدا کید
0 ع fe
صفحه 184:
۱- اولین مزیت «مخفیسازی اطلاعات» است.
۲-مزیت دیگر این است که توابع مورد نیاز را مینوان قبل
از این که برنامة اصلی نوشنته شود. جداگانه آزمایش
نمود.
۳سومین مزیت این است که در هر زمانی به راحتی
میتوان تعریف توابع را عوض کرد بدون این که لازم
باشد برنامة اصلی تغییر یابد.
۴-چهارمین مزیت هم این است که میتوانید یک بار یک
تابع را کامپایل و ذخیره کنید و از تن پس در برنامههای
مختلفی از همان تابع استفاده بیرید.
صفحه 185:
رت
صفحه 186:
حال کافی است <tochide <test.cppHi he را به
اول برنامه اصلى وقبل از ١ اضافه كنيم:
ber acd cee Rec ee
اه ز
:مصتعصخا wax() ۱۱
00000
2
۱
--" |
<< wax(w,a) << eo;
صفحه 187:
rang vont eer erence en ye
كت TN el rent See ence)
POE 0 Dede ol ot cer PEED] Darr)
و ذخیره Jools DLL رادر فايلهايى از نوع
0 2020 yy etc wpe)
مینمایند. فایلهای بابلا رابه دو طریق ایستا و
1۳ 7 ener)
بيشتر بافايلهاى ,ارا(ا) به مرجع ويندوز و
كاميايلرهاى (0++ مراجعه كنيد.
صفحه 188:
ا د ی
متغيرها فقط در دا<
يارامترهاى تابع
محلی برای آن تابع هستند.
صفحه 189:
۱
011101111 11 1 0 BENIN OP ecL EI
(6()©()0)..(هم) رمم" - اه
BR Pe re SCAN ele eT
ta BS]
{ Mretures a! = o*(oHl)*(r-@)*...*(C)*(0)
P (a< ©) retro O;
۷ < :
۱
PAS or;
ca
صفحه 190:
Bee Pepe ye oom ercmy ee) باشند تن
باشند.
1 Sl Ree Mey oS © geen ee eS
oa eve we elke ree eee Bee eee alee BES a
ساخت. به مثال زير نكاه كنيد.
0000 Te
Polar ا ل ا ا ا r Y
- مىكند كه به جند طريق مىتوان >اعنصر دلخواه از يك مجموعة
7 ۰
استفاده مى شود:
صفحه 191:
SE. EY otro oe رل
ا ۳
شرط به کار رفقته در دستور *برای محدود کردن
Tene ا ا ال ل ا ا ا 0
تابع مقدار ٠ را برمى كرداند تانشان دهد كه يك ورودى
اشتباه وجود داشته است.
Desc RA LD)
SY eNews Gl CA) ene cee Se et emcee ee
F(a <Q) [| k<O || k> 5) retro O;
retura Pact(a)/Pact(e-k);
صفحه 192:
POMBE ac ent pers Aes
TA ee
امد
Oe tonne
"20 0
۱
aT oC)
pout << eed; } 7
۱ ۵9
صفحه 193:
۷- تایع اب
ا ا Meee 0 000
مشخص كردن جنين توابعى از كلمة كليدى لاصمابه عنوان نوع
باز كشتى تابع استفاده مى كنند
S) از ۱
از آنجا که یک تابع لس مقداری را برنمی گرداند. نیازی به دستور 9
reser SBIR eee eee ele Sec Crowe
به شکل تنها استفاده کنیم بدون این که بعد از کلمةٌ نم تم .۶
دیگری بیاید:
۳۳2
CSW ال NaN ay re Ren caus] a)
صفحه 194:
peut omy te BSW se rope ۳
استفاده مى شود بسيار مفيد است. ere
رت ا ee
5 را ی را
۱ et Se re ie ed Oo ا owe ters]
صفحه 195:
مثال ۵-۱۰ تابعی که اول بودن اعداد را بررسی میکند
كد زير یک تابع بولی است که تشخیص میدهد آیا عدد صحیح ارسال شده به آن, اول است یا خیر:
زاس مها
P ais prive, Pause vihenwise! 010
a) موی مسا
OCR Rear ccd لي ۱
[CO od 9 oe the Pret prives ۱
PF (a%C == O) retura Poe} // © is the vy eves prive
(cme cela a He tad) يكنا
(QM SO) ae Nal ean esas
retura fru; USN aaa aa es cece
صفحه 196:
۳0( توابع ورودق /خروجی -٩
بح 1۱۳
به هدف اصلى برنامه مربوط نيست را مىتوان به توابع سيرد. در
چنین شرایطی سودمندی توابع محسوستر میشود.
Seer NES ا cere الم
كرددايد كه سوابق تحصيلى دانشجويان را نكه مىدارد. در اين
نرمافزار لازم است كه سن دانشجو به عنوان يكى از اطلاعات يروندة
دانشجو وارد شود. اكر وظيفة دريافت سن را به عهدةٌ يك تابع
.۰ جزيياتى از قبيل كنترل ورودى معتبرء يافتن سن
از روى تاريخ تولد و ... را در اين تابع ييادهسازى كنيد 0
از مسير برنامة اصلى منحرف شويد.
صفحه 197:
۱۱ Cr wen ec
ا ا لل ان ل
SO ear ls) فقط براى جاب
إن نات بات إن تولبع خروجی . -. یعنی توابعی که
فقط برای le نتایج به کار میروند و هیچ مقدار باز گشتی
ندارند.
اا .سا یز به همین روش کار میکنند اما در جهت
ا ا ا ا لت اال
ا ا ل ل ل a ل
ندارند.
صفحه 198:
rent) مثال ۵-۱۱ تابعی برای دریافت سن کاربر
رس عفص ارسي ا ع سي 007
7
PEE bo5) cruelgs y2 4 Se DE ede eel CaN eae ok SED
1۱ Ot ga thea 1 ee eRe er Caen | cacy
مى ين ست
زه << ميو
PF (a < O) wu ل ا wt
be vexnive.";
ebe F (oc > (CO) pou << “lalou coud wot
aa el
eee 5
"م اميه بوايادا" >> تنوم
صفحه 199:
fom eM AN Brel bn ener pear eres A eres
اسف
مب
{ Mess the رات
)صم د سم
م ا وال ی ام
و7779
00 مه سا بو له توب
تسم
0
سنطكيوكه صط اص للنوص جكب عسويو نا
ماده بصا
512101011116
امس ا
0
صفحه 200:
تااين لحظه تمام يارامترهايى كه در توابع ديديم به
طریق ارسال شدااند. يعنى ابتدا مقدار متغيرى
ROO ES TEES er Scene eer cy
TE RCE ae NC Bers) ew Ee gs]
Pee E Se ware te) mee pC EE cy
سيس اين مقدار به متغير محلى > در تابع فرستاده
را آغاز میکند. در Te Oe ne! is Pee Ey TP)
طی اجرای تابع ممکن است مقدار « تغییر کند اما چون
۰ محلی است هیچ تغییری روی مقدار « نمی گذارد.
صفحه 201:
پس خود به تابع نمیرود بلکه مقدار آن درون تابع کپی میشود.
ee Oe ee See ae an eS SEE eer ee ne Leer)
به اين ترتيب تابع مى تواند مقدار »ارا بخواند اما نمى تواند مقدار »درا
تغيير دهد.
به همین دلیل به « یک پارامتر «فقط خواندنی» میگویند.
SS as Re rer Se reap Coed eRe, eer NU BC)
استفاده كرد.
ا ال ا ا ل ا ان 5
ات مور مات ما 0
۱
آن مقدار به تابع فرستاده میشود.
صفحه 202:
۰ ارسال به طریق )5 !2 (آدرس)
ا ا ل ا ا
con ped es) peer Ov OS ا 00
eel ee
و Pen اوقات عمدا میخواهیم این اتفاق رخ
دهد. یعنی میخواهیم که تابع بتواند محتویات
7 فرستاده شده به ol را دستکاری کند. در
زا
میکنیم.
صفحه 203:
براى اين كه مشخص كنيم يك يارامتر به طريق ارجاع
ارسال مىشود. علامت رابه نوع يارامتر در فهرست
پارامترهای تابع اضافه میکنیم. این باعث میشود که تابع
Pe Cree ee melt ic ann ۳
خود آرگومان محلی را به کار بگیرد.
به این ترتیب تابع هم میتواند مقدار آر گومان فرستاده
شده را بخواند و هم میتواند مقدار آن را تغییر دهد. در
اين.حالت آنن يارامتر يك يارامقر 22000
ص۳۰۳
صفحه 204:
هر تغييرى كه روى يارامتر ا 7
مستقيم روى متغير برنامة اصلى اعمال مى شود. به مثال زير نكاه كنيد.
0 ena oe
تابع كوج زير در مرتب كردن داددها كاربرد فراوان دارد:
votd swap(Ploot& x, Ploot& (مر
۱0/۳ و مت مر
هدف این تابع جابجا کردن دو عنصری است
rr cae ل ree 1۱
پارامترهای >«و مربه صورت پارامترهای
۱
ماما سنا
صفحه 205:
ee SIE Re ee Tee Sa eae pees ارسالی
econo) ا Pow
ed) مد
وت رم رات رت
تیمک
ntsc, ca |
Ha biel oleh oil ol wlohe)
eek ee <a ee |
صفحه 206:
وقتی فراخوانی ا میشود. »<به "اشاره
|
1
۹۳ ا ا ل
فى كيرد و آنگاه»هقدار as ۳(
crow 06 2 2
جابجا مى eye) . شکل ne نشان مى دا
جابجايى ae a oe 5500006
1
float&
float&
لت
float
صفحه 207:
00
ای سد لصا oan oO ears 9)
اين اعلان شامل عملكر ارجاع © براى هر يارامتر است.
برنامهنويسان 4 ۳۹ ا و6 ۳ به
عنوان پیشوند نام 0
1
است (مثل »« مها
1
د
صفحه 208:
۲ Beebe ENO ato)
eat ed RCM Cape y eNO ee FCO ل
كه nn}) poe wot eee) ا CA ))
27 Rye EY ل S| era eo
AR eee dma
۳ OS |
Pb)
wou << "a= "<<u<<"\b="<<b << ocd
ارت وت
eS SE eR >> للج >> ط
0 7( 2و 99,۲۶۶
2606 ات
6 ۱
صفحه 209:
00 RIN Cod
Cha Rae pear ced
۲)(
۳ 22
10
cane
صفحه 210:
در جدول زير خلاصة تفاوتهاى بين ارسال از طریق مقدار و ارسال
7
00
jint x
Cee wee
*مترادفبا آركومازلست
| و
آ رگومان ارسال شده از طبریق ارجاع فقط باید
يك متغيس باشد
آركومان نواندنى- نوشتنى است
a اه
Pah a 4
eee Pee.
Cee Pe sen
CORP Ar Sia io wer)
آركومان ارسال شده از طبریق مقدار میتواند
يك ثابته يك متغيس یا یک عبارت باشد
آركومان فتط خواندنى است
صفحه 211:
يكى از مواقعى كه يارامترهاى ارجاع مورد نياز
هستند جايى است كه تابع بايد بيش از يك مقدار را
باز گرداند.
اا ۰۳ ۱ میتواند یک مقدار را
2
بنايراين اكر بايد بيش از يك مقدار بر كشت داده
eye) اين 067 0 پارامترهای ارجاع انجام مى دهند.
صفحه 212:
۷ FY ea av OME?
ae At PP ee dee SNCS Pe Be ioc
جح أمس جوج (محيط و مساحت) براى دايرهاى كه شعاع آن عدد
مفروض «است:
arcu, double& vircucPereue, ل ب 0
ام
۸/۱ ان Ne AS ahh ane ee oats
Pac tg
رت ارت بت ره رت رت ره یت لا ل
Cod baat ال
ماس ات تس مت المع
1
صفحه 213:
برنامة آزمون تابع فوق و يك اجراى آزمايشى آن در شكل زير نشان
داده شده است:
double) گت مس مگ رز
oF a circle wits // ام لعن يا يس يدا
مه
هط
۱
Pe oe ain id
He AC ata
صفحه 214:
7 5 4 5
الوسداز طميؤلوجاع تلبت 06
ارسال يارامترها به طريق ارجاع دو خاصيت مهم دارد:
BC Srp pr ele SUNT SPC PP ek ie
ان كه از إشتال بى دورد حافظه 1
SES) ل ل اك
.اين روش مانند ارسال از طريق
ارجاع است با اين فرق كه تابع نمى تواند محتويات يارامتر ارجاع
nel Ment) Cromny By 1 ۱
براى اين كه يارامترى رااز نوع ارجاع ثابت اعلان كنيم بايد
es ا ا 0
صفحه 215:
مثال ۵-۱۵ ارسال از طریق ارجاع ثابت
و ا ل
Dee En tn 2(
تک
تصش
Peet ee ee I eo Sd
لو >> >>
صفحه 216:
۱
FR eH
امین
ea anaes acd
CO lc FE ado lar
Peet he ed a
وت 1 eC SRT Cre
Seay | ل CRE be Ser
سس« Rs aR ۰
3 Se PILES Tee)
CO Re we. wikis eerie)
EIT OO Tae See beatae)
روى آركومان طهم تاثير مىكذارد زيرا ط
از طريق ارجاع به تابع فرستاده شده.
صفحه 217:
ارسال به طریق ارجاع ثابت بیشتر برای توابعی
استفاده مىشود كه 0
eeC ep ا ا ا Pee age) Ce
Lanes ام ل eee
كه pes Re. Wee) eee We Oe
ee De net Te ele BES) ا لت
Yoy ren epre ل ا 50
صفحه 218:
تسولبع بسپلسطه -19
تابعی که به شکل بیواسطه تعریف میشود. ظاهری شبیه به تولبع
معمولی دارد با این فرق که عبارت ۲ در اعلان و تعریف آنن
قبد شده است.
ها
اين همان تابع ۱
اس مرا
Race A aes
خم
ار ها تما
صفحه 219:
0 SHS
امه
۱
ار وه سس
داشته باشد. مثلا اگر یک تابع بیواسطه مات
۰ خط کد باشد و این ey ۳
مختلیف ابو نامه اصیلی فراخوانی شوه هنگلمت.
phi reser A
رت ۲
9 تلف کاهش د
صفحه 220:
چندشکلیسوایع -46
در + میتوانیم چند تابع داشته باشیم که
همگی race) دارند. در اين حالت coer ee)
تابع مذکور چندشکلی دارد. شرط این کار آنن
CE ane eS Omer ror
تفاوت داشته باشد. يعنى تعداد يارامترها متفاوت
باشد يا دست كم يكى از يارامترهاى متناظر هم
نوع نباشند.
صفحه 221:
مثال 0-11 جندشكلى تابع >5 ()
۱ Same) oe)
9 eee Ee i ee Ray) cea)
میگیریم:
رسمه
000 0
DR te
رسمه
تور 0
(66.6 .)وس >> ۲۰
i
صفحه 222:
tat cax(tet 2, tot v)
) | یه the wontkour oP the tty qed iiexers:
vets (x < مر 2? x tp);
}
it wardtat x, toy, tz)
:وه مورف oP he tere موم the بو | )
(ى, بای دص دجم عم
rea (z> a 22: w);
}
۳ es ae eae
eis etiersd Ose xin nay ae MERE xe
vehed Geet xt),
۷
صفحه 223:
1
ات مر
1
0
0 م ا م ا مر BED es
00 > tat 7-۳ ارسال ا نسخهای که دو
يارامترهايش دارد فراخوانى مىشود. اكر اين نسخه
وجود نداشته باشد. کامپایلر #اهارابه عطط ارتقا
میدهد و سپس نسخهای که دو پارامتر عاط دارد را
فرا میخواند.
صفحه 224:
(kod تابع -۴
Fee EC ل ل Rey om ا eine Celt gs)
۳۳۳7 MONA
ا ا Pe tp Pee eel
مر ۳
در حقیقت هر برنامه کامل, از یک تابع 2-5 () به همراه
توابع دیگر تشکیل شده است که هر یک از این توابع به
شكل OL SIO Li er ce rece ات هرا
abe, 0
صفحه 225:
خود برنامه با فراخوانی تابع ۵۳() شروع میشود.
چون این تابع یک نوع باز گشتی ۱ دارد. منطقی است که بلوک
ا eS
از كاميايلرهاى 0++اين خط اجبارى نيست و مىتوان آن را
ذكر نكرد.
مقدار صحیحی ا ل ا ل برمی گردد
م ا |
به این معنا که برنامه بدون خطا پایان گرفته است.
oy ee el Te a gy mere DL mec) a)
Peer Se Cee U eer Bers
صفحه 226:
مثال 0-١ استفاده از دستور هؤْه: براى يايان دادن به يى برنامه
اماد
۱
Casey oe) ل ل 30 :لك ره ها
SSCs res res pC Fa 530000
3
که اجرای دستور ا لضن
owe ره << و << ويم
feed) hata kOe ۱
d << "=" << dd << ocd << تا
i
نت يمد ين
تت
صفحه 227:
6 که بتوا epee yer
به شك mA
۳ ۱
a 7
je که اجر aes ی بر
ree 5
دج ۳
رش وجوه ee
رود 5 ;
cee ل از این تمه
oe :
a) بلوک اصلی برسد) خا
دهیم:
ستفاده از دستو ۱
90
-١ اه اد ها
صفحه 228:
مثال ۵-۱۹٩ استفاده از تابع ۳۳4 برای پایان دادن به برنامه
تمس Se OO دس رز
pout bbe و
Re a a
دراين برنامة اكر كاربر عدد ٠ را و ی
وارد كند. تابع كدص عدت )(١ خاتمه مم
مییابد و برنامه بدون هیچ مقدار :» عاططط )
ا ا << و
:(0)سمواطجر >> لحو
}
buble reviprovd (double x) — Cxvepion
RN A haa a es
م ل الس سان dd ara acd
م00 یمس +
صفحه 229:
توكومارهائه يثؤ رض 08
در (0)++ مىتوان تعداد ۱۳ يكد تابع را در زمان اجرا به
دلخواه تغيير داد.
BO per eR TS Rests oer co sore ee ger |
امکانپذیر است.
9 SON SOG we Bee ROSE neve iC be
فهرست پارامترهای تابع و جلوی پارامتر مربوطه به همراه علامت مساوی
۱
Ore Rey TP rd nl ee) nd a PORES De ا
BMP res econ on el SIT ael Op cs
صفحه 230:
Bee ER URN be ذا
سم
١ 5 0-7
برنامة زير حاصل جند جملهاى درجه سوم را بيدا eos
اين مقدار از الكوريتم هورنر استفاده شده. به ی برأى كرأ
بیشتر. محاسبه به صورت نوی نود
داس ل ما
part << "p(x,P,Q) =" << p(x,P,O) << euch
ont << "p(x,P,O,9) =" << p(x,P,O,9) << edd
mnt << "p(x,?,98,5,F) =" << p(x, ?,9,S,€) << ead;
0
علط =O, الط ,420 الط oral تیا
2-0
1 || جصموور oD + ol*x + O*%O + WO*O: 2-7
rete WD + (ol + (GO + WO*K)*x) "x; ری
۱ ی = 66.0060 —
1 يا
©0106 د ( ۱۳
صفحه 231:
دقت كنيد كه يارامترهايى كه مقدار يب شفرض دارند بايد در فهرست
ل ل ا ل ل
OM // ال اي الي P( tata, tab, ةا
void u(tat a, tot b=O, tat o=P, tad, tot =O); // GRROR
Seep Ree See BoE NC. ely OL a Les ter Boece
Seen Be Ore ل لل San Oe ee TP RO rere Rec y)
لاسرم Peep ee een) FEE ee) ارا سار
Fer Oe Ney ۰
صفحه 232:
پایان جلسه پنجم
صفحه 233:
صفحه 234:
آنچه در این جلسه می خوانید
- يردازش آرايهها
- مقداردهی آرایهها
- ایندکس بیرون از حدود آرایه
- ارسال آرایه به تابع
oreo OTe ۱۳
-مرتبسازی حبابی 21:1
Ce ye ee 0
صفحه 235:
0 on ae
تعریف انواع -
1
صفحه 236:
هدف هاى رفتازی:
ا ام ا 00
ا ل ا 0
- آرايههاى ديك بعدىء و «جندبعدى» را تعريف كنيد.
ا ا ا ا 1
- طريقة ارسال آرايه به توابع را بدانيد.
- دجستجوى خطى» و «جستجوى دودويى» را به اختصار شرح دهيد.
- «مرتبسازى حبابى» را به اختصار شرح دهيد.
صفحه 237:
وال ههد
در برنامههايى كه دادههاى فراوانى را يردازش مى كنند
ا ar ل معمولى کار tee ات زيرا
بسیا
et یر
صر ce) يرو Sere زر شود. به
Neem eA) See EI ogee)
تدارک دیده شدهاند.
صفحه 238:
ا ا 0 0 د
یک نوع هستند.
به اين متغيرها 0١١ مىكويند.
eC ل ا ا Orage)
شماره « » پا « » مى كويند
عناصر يك آرايه در خانههاى يشت سر هم در حافظه
ذخیره میشوند. به این ترتیب آرایه را میتوان بخشی از
ص ey ca at
مساوی تقسیم شده و هر قسمت به یک عنصر تعلق
دارد.
صفحه 239:
1
عنصر [2]0 حاوى مقدار 11.8 وعنصر [2]1 حاوى 19.0 وعنصر
|
صفحه 240:
پسردلزشآپلیدها -6
۱
برنامة سادة زير يك آرايةٌ سه عنصرى را تعريف مىكند و سيس مقاديرى رادر
0
استفاده كرد. با اين تفاوت كه آرايه يك ملافيبر "
مرکب است و برای دستیابی به هر یک از خال ایآ
er ۱ 000 0
-]0[ > 9
لمج >> [0]ه >> " - [00]ه" >> نوم
اد اس
لمم >> [8]ه << "= mat << "o[C]
}
صفحه 241:
نحو کلی برای اعلان آرایه به شکل زیر است:
اس ماس رم سر
تبارت ۷۳۶ تز2 حناعر آرایه را مشخص میکند.
1 ل لت
EC Raa: as ا لت
a ree re OLD EC CH) ۳
بايد داخل كروشه | قرار بكيرد.
صفحه 242:
neew roe OME) ا ا ا
3
Ha al] = 66 66 666
به این ترتیب مقادیر داخل فهرست به همان ترتیبی که چیده
بر 00
EEL See ae) Dea) له
يس همين خط مختصرء آرايهاى از نوع وبانام وبا تعداد
ی رها هی ااا
فهررست. ترس مى كند.
0 ۵9
4
68.8
صفحه 243:
مثال ۶-۳ مقداردهی آرایه با استفاده از فهرست مقداردهی
ESS CHE SOCAL: 0 1
int main()
float al] = { 22.2, 44.4, 66.6 }; {
int size = sizeof(a)/sizeof(float);
for (int i=0; i<size; i++)
ceed NN ga (eee) ee) eer > الاو
endl;
y ره
صفحه 244:
هنكام استفاده I براى اعلان آرايه.
مى توانيم تعداد عناصر آرايه را هم به طور صريح ذكر
كنيم. در اين صورت اكر تعداد عناصر ذكر شده از تعداد
عناصر موجود در فهرست ۳ پیشتر باشد.
خانههای بعدی با مقدار صفر پر میشوند:
float a[7] = { 55.5, 66.6, 77.7 };
ol Secor nas ah Gig oa a a Ica SS aS
دك سكي وفيس رس تعن سو سي ارو و ل
اش 9
float a{3] = { 22.2, 44.4, 66.6, 88.8 }; // ernon: too many &
یی
ون 5
۵.00 م
صفحه 245:
یک آرایه را میتوائیم به طور کامل با صفر مقداردهی اولیه کنیم.
برای مثال سه اعلان زیر با هم برابرند:
float a[ ] = { 0, 0, 0, 0, 0, 0, 0, 0, O };
float a[9] = { 0,0};
float a[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Lee مسد ye wee RCN Que! لاسي هس با و کت
امتفاده نشود.
درست مثل یک متفیر معمولی. اگر یک آرایه مقداردهی اولیه
yee Sear lip een arse tel ew nye)
صفحه 246:
مثال ۶-۵ یک آرايةٌ مقداردهی نشده
برنامةً زیر آرایةً 8 را اعلان میکند ولی مقداردهی نمیکند. با وجود
اين: مقادير موجود 00 راجاب مىكند:
int main()
{ const int SIZE=4; // defines the size N for 4
elements
float a[SIZE]; // declares the array's elements as
float
for (int i=0O; i<SIZE; i++)
cout << "\ta[" << i << "] =" << afi] <<
صفحه 247:
آرايهها را مى توان با استفاده از عملكر جايكزينى مقداردهى
:کرد اما نمیتوان مقدار آنها را به یکدیگر تخصیص داد
ا تك ا نر
;} .7° رس
Ain HR C(O acca et
همچنین نمیتوانیم یک آرایه را به طور مستقیم برای
مقداردهى به لا در رن Pred
ارق فونه ميهف د إسادونة
Pou bP] = uj ۱ نتب orreps coset be wed ow carers!
صفحه 248:
۴- ایند گس بیرون از حدود آرابه
1
نمیتواند از محدودهٌ تعریف شده برای آن بیشتر باشد.
۳ ۳3 در پاسکال اگر آراية با تعداد ينج عنصر
تعریف شده باشد و آنگاه [ 7 ]3 دستیابی شود. برنامه از
این سیستم حفاظتی در وجود ندارد.
مثال بعدی نشان میدهد که ایندکس یک آرایه هنگام
دستیابی میتولند بیشتر از عناصر تعریف شده برای OF
باشد و باز هم بدون این که خطایی گرفته شود. برنامه
ادامه یابد.
صفحه 249:
مثال ۶-۶ تجاوز ایندکس آرایه از محدودةّ تعریف شده برای آن
7 یک خطای o ley] 0
ی
Ea)
{ woost ct GILE=4;
pa Ama) ee oe)
pes وت
صفحه 250:
سا ره ۳ ۲
ep OE Ree EOr RAE Cree yo Se Oe TS Meee bBo Hse
متغير به طور ناخواسته تغيير كند:
۱
const int SIZE=4;
float al] = { 22.2, 44.4, 66.6 };
float x=11.1;
صفحه 251:
بعد از اعلان شده. يس يى سلول جهاربايتى
بلافاصله بعد از دوازده بایت آرایه به آتن تخصیص مییابد.
بنابراين وقتى برنامه تلاش مى كند مقدار 88.8 را در [3]3 قرار
دهد (كه جزو آرايه نيست) اين مقدار به شكل ناخواسته در
[Sus 0 00
منبع خطا را كشف كنيم. حتى ممكن است به
اين روش دادههاى برنامههاى ديكرى كه در
pea ees ca 1
x 88.8 7 erm e i -corecde <a Re) a
میگویند. این وظيفةٌ برنامهنویس
۱
ی ۱
رس
۲ ۶۶۶
صفحه 252:
مثال ۶-۸ ایجاد استثنای مدیریت نشده
مه نر ا ا ا a) ل اك ae
۰0
vost et OVLO=P; {
Poa of] > ) 69.6, 660.62, 69.6
:200.0 مراع
mat << "x=" << x << ocd;
صفحه 253:
وقتى اين برنامه روى رايانهاى با سيستم عامل ويندوز
اجرا شود. یک صفحهٌ هشدار که در شکل نشان داده شده
Syl etwas) و
این پنجره بیان میکند که برنامه تلاش دارد به نشانی
06 از حافظه دستیابی کند. این مکان خارج از
reat ol pene) tt pen a reer] py vere a etc |
بنابراين سيستم عامل برنامه را متوقف مى كند.
صفحه 254:
صفحه 255:
ارسل[آیلیه سه تسلبع 5۰
۱
كاميايلر مى كويد:
۱-اين که نام آرایه 3 است
۲- عناصر آرایه از نوع 1031] هستند.
سمبل 3 تشانی حافظة آرایه را ذخیره میکند, ارم 2 برد
ا ا ا ا
Tee) ا ا
..یعنی فقط نوع آرایه و نشانی حافظةً
آن به عنوان پارامتر به تابع فرستاده میشود.
صفحه 256:
ا ا ل ل
int sum(int[],int);
int main()
int al] = { 11, 33, 55, 77}; {
int size = sizeof(a)/sizeof(int);
cout << "sum(a,size) = "<< sum(a,size) << endl;}
ee Cae) PD)
4 نو 0>-طاناد ام[
for (int i=0; i<n; i++)
اب ده :111 <+ با
اناك اناعم
صفحه 257:
هنكام فراخوانى تابع نيز از عبارت SuM(a,SIZE)
استفاده شده كه به تابع ارسال شده.
نام آرایه در حقیقت نشانی اولین عنصر آرایه است (یعنی
ات
تابع از این نشانی برای دستیابی به عناصر آرایه استفاده
مى كند. همجنين تابع مى تواند با استفاده از اين نشانى,
يس ارسال آرايه به تابع شبيه ارسال متغير به
طريق ارجاع است.
صفحه 258:
3/۰ ی
CAB ا er) 0 در این برنامه از تابع
COIN ese Sema Ups ne ney eS CAD
ساب د شرك
void read(int[],int&;)
void print(int[],int);
int main()
{ const int MAXSIZE=100;
int a[MAXSIZE]={0}, size
Pa
صفحه 259:
void (int a[], int& n)
cout << "Enter integers. Terminate with 0:\
5
۲۱ < 0:
do
{ cout << "a["<<n<<"]:";
cin >> a[n];
{ while (a[n++] !=0 && n < MAXSIZE);
--n; // don't count the 0
صفحه 260:
7010 (صغصا ,[]ه غما)
for (int i=0; i<n; i++)
we >> []ة 22 نوه
جون ١ يك متغير است, براى اين كه تابع [30©() بتواند
مقدار كن را تغيير دهد اين متغير بايد به شكل ارجاع ارسال
شود.
همجنين براى اين كه تابع مذكور بتوائد مقادير داخل آرايه
3 را تغيير دهد. آرايه نيز بايد به * طریق ارجاع ارسال شود؛
1 ۱
صفحه 261:
Cr Sy Pe SAH DP OOS) HID Ieee he eto D ICH Sires OMB)
استفاده میشود: ۱ soa orga) bee
oes)
تعداد
نوع
تابع با استفاده از اين سه عنصر مىتواند به تىك تى
pecan ome Fl pd rr 4
صفحه 262:
آدرس اولين خانة آرایه. همان نام آرايه است.
پس وقتی نام آرایه را به تابع بفرستیم آدرس اولین خانه
Pee ay
ye Weay) tae Snes Be BES Ep] Ere
بتابراین با این دو مقدار, تابع میتواند به آرابه دسترسی
داشته باشد.
صفحه 263:
1 eM Oe LE ond E>)
1 owe a ern Se Sco Mp SNES oI Oe
میکند:
{ int al] = { 22, 44, 66, 88 };
cout << "a =" <<a <<endl; // the address of
2]0[
cout << "a[0] =" <<a[0]; // the value of a[0]
صفحه 264:
۶- الگورینم جستجوی خطی
آرایهها بیشتر برای پردازش یک زنجیره از دادهها به
لاد 2
اغلب لازم است كه بررسى شود آيا يك مقدار خاص
mee uey yn) ا 2 0 0220000 32
ا ل ا ا 6
همة عناصر آرايه را جستجو نماييم تا بفهميم كه مقدار
مورد نظر در كدام عنصر قرار كرفته. به اين روش
ا ا میگویند.
صفحه 265:
سل امس
برنامةٌ زير تابعی را آزمایش میکند که در این تابع از روش جستجوی خطی برای
یافتن یک مقدار خاص استفاده شده:
int index(int,int[], int);
int main()
{ int al] = { 22, 44, 66, 88, 44, 66, 55};
cout << "index(44,a,7)
endl;
cout << "index(50,a,7)
endl;
"<< index(44,a,7) <<
"<< index(50,a,7) <<
KS)
صفحه 266:
تابع سه يارامتر دارد:
0 ل ا ل By
ا ا ل تن
برابر باشد ایندکس آن عنصر باز گردانده شده و تابع خاتمه "
مییابد.
صفحه 267:
1 ا eed
مقدارى خارج از ايندكس آرايه بازكردانده مىشود كه به
این معناست که مقدار در آرابةً ۱
PN eae SCC De 2 eS Te Se
واقع است و در اجرای آزمایشی دوم مشخص شده
ا ا ا ۱
ا ل ه فقط تا 0000
عنصر داردء مقدار /ا نشان میدهد كه ٠ در ارايه موجود
نیست).
صفحه 268:
حونبسازمیهبلبی- 7
۱
است.
ses Steel by ا ل |
در هر مرتبه بزرگترین عنصر موجود به سمت بالا
Bey ا ا ا ۱
مرتبة بعدى يكى كاسته مى شود.
در يايان همة يويشهاء آرايه مر تب شده است.
صفحه 269:
1
.١ اولین عنصر آرایه با عنصر دوم مقایسه میشود.
۲ اگر عنصر اول بزرگتر بود. جای این دو با هم عوض میشود.
۳ سپس عنصر دوم با عنصر سوم مقایسه میشود.
۴ اگر عنصر دوم بزرگتر بود. جای این دو با هم عوض میشود
۱
۳ Leer Ee nee Tees nee pI
05 ان تااات محدوده جستجو یکی کاسته میشود
1 ۱
ey ا ال اا ا ا ل 000 اذام مى يابد تا اين كه
الا ا |
صفحه 270:
ات
int main()
{float a[]={55.5,22.2,99.9,66.6,44.4,88.8,33.3, 77.7};
print(a,8);
sort(a,8);
print(a,8);
صفحه 271:
void sort(float af], int n)
{ // bubble sort:
for (int i=1; i<n; i++)
// bubble up max{a[0..n-i]}:
for (int j=0; j<n-i; j++)
if (a[j] > alj+1]) swap (alj],alj+1]);
/ANVARIANT: a[n-1-i..n-1] is sorted
صفحه 272:
تابع :5011() از دو حلقة تودرتو استفاده میکند.
-١ حلقه 101 داخلى زوجهاى همسايه را با هم مقايسه
میکند و اگر آنها خارج از ترتیب باشند. جای آن دو را
ped) کون میکند:
وقتی ۲0۲ داخلی به پایان رسید. بزرگترین عنصر
موجود در محدودهٌ فعلی به انتهای آن هدایت شده است.
۲-سپس حلقةً ۲ بیرونی محدودهٌ جستجو را یکی کم
"میکند و دوباره ۲0۲ داخلی را راه میاندازد تا
بزرگترین عنصر بعدی به سمت بالای آرایه هدایت
شود.
صفحه 273:
۸- الگور بتم جستجوی دودویی
nL م ا
ا 2 ااا لل 2
تقسیم میشود.
”مقدار مورد جستجو با . . . . . بخش پایینی
۳
oe ee SLs ie ae EE reece
بالايى به دنبال آن كشت.
صفحه 274:
دو بخش تقسیم میگردد و
سرانجام محدودةٌ جستجو به یک عنصر محدود
میشود که پا آن عنصر با مورد جستجو برابر است
و عنصر مذكور يافت شده و يااين كه آن عنصر با
ame a ل ا
صفحه 275:
مثال ۶-۱۴
Pee Cee ae roe ee onl ل Oley Pep yee ee)
زير آمدهاز روش جستجوى دودويى براى يافتن مقدار درون آرايه
استفاده مى كند:
int index(int, int[],int);
int main()
{ int a[] = { 22, 33, 44, 55, 66, 77, 88 };
cout << "index(44,a,7) = " << index(44,a,7) <<
endl;
cout << "“index(60,a,7) = " << index(60,a,7) <<
endl;
p
صفحه 276:
int index(int x, int a[], int n)
{_ // PRECONDITION: a[0] <= a[1] <= ... <= a[n-
1];
// ۵۱۳۵۲۷ 6۵۲1
int lo=0, hi=n-1, i;
while (lo <= hi)
5 1 < )۱0 + (2۶ /{ the average of lo and |
if (a{i] == x) return i;
if (ali] < x) lo = i+1; // contint و
else hi = i-1; // continue searct ۳۵
a
3 Be
صفحه 277:
Fenn es pee CBT ا organ Pp
yes 2 cles) index(44,a,7
وقتی حلقه شروع میشود. ۰ ۰ رو ۱۱2و ۱050 I
است.
ابتدا مقدار .. . . رامیگیرد.پس عنصر . عنصر
DNS cul Lyle lao cael UIT aang
مقدار بزرگتر است. پس در نيمه بالایی نیست و جستجو
FPO eee ee) ۱۳
مى شود و حلقة تكرار مى كردد.
صفحه 278:
Ve 9 است و دوباره عنصر وسط آرايةٌ
oh) ep) ۱
با است که کوچکتر از میباشد. پس این دفعه .
٠ we bal میشود.
در سومین ec aed akontres 952 است. پس عنصر
ay ees که همان ۱۰ است با . مقانسه
میشود. . برابریا . است کهبا برابر است. پس
مقدار باز گشت داده میشود؛ یعنی ۰ مورد نظر در
5۳21 وجود دارد.
صفحه 279:
144
44
44
ues
aie
55
33
44
fix
cng
to
صفحه 280:
ص 1
2 2 ا ل 0 00
2 و اشلت al0..6) Col a es 520
۰ است که از . کوچکتر است. پس ۰ برابر
oe ey oe ۳
بت وع۱ا۳ر ors eS lO=4 رر ۰۳۰
al 4..6] ی ٩151277 رست کر رتر از X
میباشد. Pr ot اا تغییر مییابد و دوباره حلقه
س 010 ohl=4 10-4 ست ودر
5-7 رگ ۰-۵۱4 ۱8۱4[2660 " 1
بزرگتر از ۲ میباشد. لذا به کاهش
5-0
صفحه 281:
0 6 3 55 < 60
4 5 77 > 600
ار 66 4 4
اكنون شرط حلقه غلط مىشود زيرا
ay eee cee | م ل ۳
يعنى عنصر مورد نظر در آرايه موجود نيست.
صفحه 282:
در تابع فوق هر بار که حلقه تکرار میشود. محدودةٌ
جستجو /05١٠ كوجكتر مى شود. در آراية عنصری.
روش جستجوى دودويى حداكثر به تت
تت ل ا Be
۱ [eo
است.
صفحه 283:
تفاوتهاى جستجوى و فظی
Sg © ازجستجوی است.
gees Ber ال ا ا ا ۱0|
مقادیر یکسانی باشند. آنگاه جستجوی خطی هميشه
7 ا ان ل ee 0 لك
جستجوى دودویی را گفت 4s کدام ایندکس
0 4
صفحه 284:
| Cee eS SONG ee on INE
و
7 220
bool isNondecreasing(int a[], int n);
int main()
int a[] = { 22, 44, 66, 88, 44, 66, 55 }; {
بلس ک>( )مهس >> ۲ ع ( )وله > لو
DOUE<"sOouderreustr((a,?) =" << eQ@paderreusty(a,?) << ral:
1
صفحه 285:
bool isNondecreasing(int a[], int n)
1 // returns true iff a[0] <= a[1] <=... <=
a[n-1]:
for (int i=1; i<n; i++)
if (ali]<a[i-1]) return false;
return true;
}
صفحه 286:
این تابع یک بار کل آرایه را پیمایش کرده و زوجهای
۵11-11 و [3]1 را مقايسه م ىكند.
اگر زوجی یافت شود که در آن [211[>]1-1 باشد.
مر تب نیست.
ببینید که مقادیر ۲۱16و ۲۵156 به شکل اعداد )9 +
در خروجی چاپ میشوند زیرا مقادیر بولی در حقیقت به
شکل اعداد صحیح در حافظه ذخیره میشوند.
صفحه 287:
ree eae oe پر نت نون رنه
ار ]
بل یر اب رت تشر برس رت
ركشت . . میتوان اجرای یک
برنامه را به يى شرط وابسته كرد.
PES Se ا ل ا ee
و teat باشد. برنامه را خاتمه داده و موضوع ۳
به سیستم عامل گزارش میکند. اگر مقدار آر گومان
باشدء برنامه بدون تغيير ادامه مى يابد.
eave) <Cassert> 15-5 08551 4!
شاد است.
صفحه 288:
ات۱ :1ك رات
کردن یک پیششرط
برنامة زير نسخة بهبوديافتهاى از تابع ١ مثال
1١-ء را آزمايش مىكند. در اين نسخه.ء از تابع
۲۵۵ 1ف ذا ]|0 نثال 16كء استفاده كوه
7 00
نتيجه اين تابع به تابع ١ ارسال مىكرددتا
ا ا 0
صفحه 289:
#include <cassert> // defines the assert()
function
#include <iostream> // defines the cout object
using namespace std;
int index(int x, int af], int n);
iat Tl)
{ int a[] = { 22, 33, 44, 55, 66, 77, 88, 60 };
cout<<"index(44,a,7) = " << index(44,a,7) <<
endl;
cout<<"index(44,a,8) = " << index(44,a,8) <<
endl;
cout<<"index(60,a,8) = " << index(60,a,8) <<
صفحه 290:
bool isNondecreasing(int a[], int n);
int index(int x, int a[], int n)
{ assert(isNondecreasing(a,n));
int lo=0, hi=n-1, i;
while (lo <= hi)
{ i= (lo + hi)/2;
۱۱) فا
if (a[i] < x) lo = i+1;
2) آط - 1-1: ١
return n;
ااا 000 1
صفحه 291:
لك لك ل ا 990000
| ل 00 ا 000
فراخوانی(۱۱۵6)44,3,7 تب ان در ev
232-20 ارسال مىكند و برنامه ادمه مىيابد.
اما در دوس فراجواتى 22 41-40 ch مر شود
ا مقدار رابه تابع
Qassert ارسال کند که DP) این تت برنامه 20
میشود tT) CUD) Arey hen a ye eT Bere) |
صفحه 292:
ملستفاشت ازبافولع شسمایشوور آرلیه -9
صفحه 293:
به خاطر بیاورید که انواع شمارشی به شکل مقادیر عددی ذخیره
میشوند.
اندازة آرايه. 581-21 است زيرا 58:7 مقدار صحيح ع را
پا FS)
ترا 19
استفاده از انواع شمارشى در برخى از برنامهها باعث مى شود كه
Jlio yo Vio ogc Mol oS ۶-۱۷ کنترل حلقه به
JESS
باعث میشود که هر بینندهای حلقةٌ ۴0۲ بالا را به خوبی
صفحه 294:
| ا
pe een OC pecs
یک نوع جدید به نام تعریف میکند که متفیرهایی از این نوع میتوانند
UBLUE UGREEN LYELLOW LORANGEL sp. wl
A al eee Oe oni ee ere Clete Bay
مر و ای Poa per
BEDE; BLUE ,RED ,GREEN os 54 زر ۱
BL Sh cote ba یدای etl ts
pais VIOLET+1
OER RT TTI aah pe (10102
01
صفحه 295:
1 EY) eon ree) re
يك نام مستعار براى يك نوع 0
استاندارد موجود تعريف مى كند.
نحو استفاده از آن به شكل زير است:
تحت typedef
كه یک نوع استاندارد و 21135 نام مستعار برای
wl Ol
صفحه 296:
jllon~ "اس
عبار اكر دستور رابه شكل زير بكار بارت
ل ا 00
لقع تعريف كنيم:
لومي اد
]لا
4 بود
Inte
soe) frequency[64]
صفحه 297:
دستور ۱
به یک نوع موجود نام مستعاری را بت میدهد.
1
00 ا
FAC] Re] poy ee Se بكار اك
Eran) hp ee Se) ee 0
erro) PRE Seep OU pTS DEN Tee] ever ne yc)
در تابع +20 به كار رفته است:
صفحه 298:
typedef float Sequence[];
void sort(Sequence, int);
void print(Sequence, int);
int main()
{ Sequence a = {55.5, 22.2, 99.9, 66.6, 44.4,
88.8, 33.3, 77.711
print(a,8);
sort(a,8);
print(a,8);
I
صفحه 299:
void sort(Sequence a, int n)
{ for (int i=n-1; i>0; i--)
for (int j=0; j<i; j++)
if (alj] > alj+1])
swap(alj],alj+1]);
صفحه 300:
آملیههایچند بسعدی-1 1
ل ا ۱
Ap Cap evowr) ا ا
ie تعريف كنيم كهاز نوع آرايه باشد.
يعنى هر خانه از آن آرايه. خود يك آرايه باشد.
t—t«éi wT eS pl 0
يك آراية دو بعدی آرایهای است که هر خانه از آن» خود
یک آراية يك بعدى باشد.
يك آراية سه بعدى آرايهاى است كه هر خانه از آن يك
ارابة دو بعدی باشد.
صفحه 301:
صفحه 302:
[۱ ee torte el 7)
Bye Ie SS TOT Ren ee Sete ens
void print(int a[][5]);
int main()
{ int a[3][5];
read(a);
print(a);
صفحه 303:
void read(int a[][5])
{ cout << "Enter 15 integers, 5 per row:\
nt
for (int i=0; i<3; i++)
{ cout << "ROW" <<i<<":";
for (int j=0; j<5; j++)
صفحه 304:
void print(const int a[][5])
{ for (int i=0; i<3; i++)
{ for (int j=0; j<5; j++)
cout <<" " << alil[j];
cout << endl;
}
1
صفحه 305:
صفحه 306:
1۳ On Pome nge s oNN) Ee ا ا s)
pee] gee eee BCBS)
مثال ١٠٠-ع يردازش يك آراية دوبعدى از نمرات امتحانى
const NUM_STUDENTS = 3;
const NUM_QUIZZES = 5;
typedef int Score[NUM_STUDENTS]
[NUM_QUIZZES];
void printQuizAverages(Score);
rintClassAv
صفحه 307:
int main()
{ Score score;
cout << "Enter " << NUM_QUIZZES
<< _" quiz scores for each student:\
3
read(score);
صفحه 308:
)
{ for (int s=0; s<NUM_ STUDENTS;
5++(
{ cout << "Student "<<s <<":
1
1
for(int q=0; q<NUM_ QUIZZES;
(++و
cin >> score[s][q];
صفحه 309:
void printQuizAverages(Score score)
{ for (int s=0; s<NUM_STUDENTS; s++)
{ float sum = 0.0;
for (int q=0; q<NUM_QUIZZES; q++)
sum += score[s][q];
cout << "\tStudent "<< s << '";"
<< sum/NUM_QUIZZES
<< endl;
3
صفحه 310:
{ for (int ۱00۱۳۵۵20 عن +(
{ float sum = 0.0;
for (int s=0; s<NUM_STUDENTS; s++)
sum += score[s][q];
cout << "\tQuiz "<< q << '":" <<
sum/NUM_STUDENTS << endl;
/
صفحه 311:
7 eae)
ات۱۱۱۱ ۱۳ دوبعدى 0*7 نام
انتخاب شده. این باعث 6 ace
د که توابع خواناتر باشند. هر تابع از دو
تودرتو استفاده كرده كه حلقة 07 ۳۹
بيرونىء بعد اول را ييمايش مىكند و حلقة
SO Eee ey SPC ELE
printQuizAverages تلبع
هر سطر از نمرات را محاسبه و چاپ مینماید و
printClassAverages =
میانگین هر ستون از نمرهها را چاپ میکند.
صفحه 312:
|
اين برنامه تعداد صفرها را در يك آراية سه بعدى مى شمارد:
1۳ (int afJ[4][3], int n1, int n2, int
n3);
int main()
i tle شاك St {5,02}, {0,0,9},{4,1,0},
1 1 £3,0,0}, 85,0},
10/00, 12,0,9( ۳
cout << "This array has " <<
numZeros(a,2,4,3)
<<" zeros:\n";
صفحه 313:
۱18۱771۱ int
n3)
{ int count = 0;
for (int i = 0; i < n1; i++)
for (int j = 0; j < n2; j++)
for (int k = 0; k < n3; k++)
oe ۳ 5-55
صفحه 314:
توجه كنيد كه آرايه چگونه مقداردهی شده است. این
قالب مقداردهى به خوبى نمايان مى كند كه آراية مذكور
يى آرايه دو عنصرى است كه هر عنصرء خود يى آراية
میباشد. پس این آرایه در مجموع ۲۴ عنصر دارد. لك
۱-۱ ۱19۳-۳4
و یا مانند این
int 2004131 = {{5,0,2,0,0,9,4,1,0,7,7,7},
{3,0,0,8,5,0,0,0,0,2,0,9}};
هر سة اين قالبها براى كاميايلر یک مفهوم را دارند اما با
نگاه کردن به دو قالب اخیر به سختی میتوان فهمید که
کدام عنصر از آرابه. کدام مقدار را خواهد داشت.
صفحه 315:
یار خلسة سسم
صفحه 316:
9 ۰
رز
«اسساه ام
ارب
555
,اشارهكرها و ارجاعها ؛
صفحه 317:
آنجه در این جلسه می خوانید
۱-عملگر ارجاع
7
۳
- مقداريابى
ا 0
- بازكشت از نوع ارجاع
es Fp) lea ۱۳ >>>
صفحه 318:
7- عملگر New
delete jstc__
- - آرایههای پویا
- اشارهگر ثابت
ا ا
-اشارهكرى به اشارهكر ديكر
-اشارهكر به توابع
. ۱
صفحه 319:
هدف کلی:
آشنایی با اشاره گرها و نحوةٌ کار با آدرسهای حافظه
هدفهای رفتاری:
انتظار میرود پس از پایان این جلسه بتوانید:
1 ee En om eee ne vee res
- «اشاره گر» 7 1ك
مختلف ايجاد كرده و آنها را مقداريابى كنيد.
>> >»
صفحه 320:
- «چپمقدارها» و «راستمقدارها» را تعر یف كرده و آنها را
از یکدیگر تمیز دهید.
- باز گشتهایی از نوع ارجاع ایجاد نمایید.
- طريقة استفاده از عملكرهاى الا © و ©]0)©|©1 و وظيفة
هر يك را بدانيد.
|
آرایههای ایستا ذکر کنید.
- آرایههای پوبا را در برنامههایتان ایجاد کرده و مدیریت
۳
-ثفاهت ب- الالا هه إن ا دهد
صفحه 321:
2
حافظة رايانه را مىتوان به صورت يى آراية بزرك
»bs yo 23,5 ا ا 9500007
60 در حقيقت حاوى آرايهاى بهاندازة
a ل ا 2 رك 1۱7
خانه یک بایت است.
این خانهها دارای ایندکس صفر تا ۲۶۸۰۴۳۵۰۴۵۵
هط
صفحه 322:
آدرس-های حافظه را با اعداد شانزدهدهی نشان
0 اكه مذکور دارای محدوده آدرس
4[ تا 000۲۲۲۲۲۲ میباشد.
هر وقت كه متغيرى را اعلان مىكنيم, سه ويزكى
اساسی به آن متفیر نسبت داده میشود: : «نوع 0
دنام متغیر» و «آدرس حافظه» آن.
ل ال ا لل ات
صفحه 323:
n
Oe) ااا ل
10
الا ات ل |
۱ در بالاى جعبه است و ادرس متغير در سمت جب
crag 0 و PROS heel eee
در بيشتر رايانهها نوع :]11 جهار بايت از حافظه را اشغال
ا ل ا 1 ان
داده شده است. متفیر ۲۱ یک بلوک چهاربایتی از حافظه
را اشغال میکند که شامل بایتهای 000506060
تا 000506063 است. توجه کنید که آدرس شی.
آدرس اولین بایت از بلوکی است که شی در آلن جا
ذخيره شده.
صفحه 324:
A esto PN CoP Ete See 01[ مقداردهى اوليه
شود. آنگاه Sy eel ee ae Deedee Sa
میشود.
0x0050cdb8
0x0050cdb9 ا |
int
clita: (on
0x0050cdc2
0x0050cdc3
000506064
0x0050cdc5
صفحه 325:
ل ا ا Be
عملگر ارجاع ۱ 4 استفاده نمود. به این عملگر «علمگر
آدرس» نیز میگویند. عبارت آدرس متغفیر ۳۳9
دست مى ذهد. int main()
{ int n=44;
صفحه 326:
خروجی نشان میدهد که آدرس- 1۱ در این اجرا برابر با
3 است. مى توان فهميد كه اين مقدار
ا ل Been SSS Se Ce pee
داده شده. اعداد شانزدهدهى را از روی علامت *0
مىتوان تشخيص داد. معادل دهدهى عدد بالا مقدار
۹ میباشد.
صفحه 327:
لرجاعها -3
|
نحو اعلان یک ارجاع به شکل زیر است:
type& ref_name = var_name;
022 6
ا د الل ل
ار 0 كت 1 Orne Cree Yeu] Capua
int& rn=n; // ۱5 asynonym for n
7 ey may leer ane
۱
صفحه 328:
هميشه مقدار بکسانيدارند اگر کاسته شود.
So ee ee eee poe] 1
نيزلفزليشيافته لست
صفحه 329:
a teed ieeerlcey ۳ باید هنگام اعلان مقداردهی
اوليه شوند با اين تفاوت كه مقدار اولية يى ارجاع. يىك
متغير است نه يك ليترال. اشتباه
/۱ ۲۴۵۴: 44 ۱6 ۱0۵۲ 2 ۷۲۵0۱
۱
بدانند ولی با نشان دادن یک هشدار اعلام میکنند که یک
متفیر موقتی ایجاد شده تا ۰ . به حافظةٌ آن متغیر. ارجاع
داشته باشد.
صفحه 330:
زد متغیر نیست.
یک متفیر. فضای ذخیرهسازی و نشانی مستقل دارد.
AE COSCON PCO Cmaa hy eo 1
Soe ee ate es
صفحه 331:
مشلل!-۷ ارجاعها متفیر های» ستقل:یستند *
int main()
{ int n=44;
int& rn=n; // rn is a synonym for n
cout <<" &n="<< &n <<", &n=" << &n <<
endl;
alka dada // rn2 is another synonym
= ین
0x0064fde4, روت
صفحه 332:
n Pe TOME ES PES CS ا STE On eeae
.دنتسها١ است. (1او 102و 13 ارجاعهايى به
۲03 خروجی نیز تایید میکند که آدرس ۲ و ۲02و
با آدرس ۲۱ یکی است.
ارجاعها pew) برای ساختن پارامترهای ارجاع در توابع
به ۷1 میروند. تابع میتواند حون 57 0 را كه
tin ee ند اواك ar را
تنها فرق اين است كه دامنة 7 fel ee.)
Bear oie لت
۳
صفحه 333:
7 ee eo
مىدانيم كه اعداد صحيح را بايد در متغيرى از نوع int
نكهدارى كنيم و اعداد اعشارى را در متغيرهايى از نوع
float
| DNC Ser Pel Meh D1 eee ean de]
Fee وف ا ا
bool - |
صفحه 334:
عملگر ارجاع 6 آدرس حافظة یک متغیر موجود را به
OMA Ke) ee Ee Rene) آدرس 00
Byer oe
متغفیری که یک آدرس در آن ذخیره میشود
ناميده مى شود
براى اين كه يك اشارهكر اعلان كنيم., ابتدا بايد
مشخص کنیم كه آدرس Ep te دادهای قرار است در
آن ذخیره شود. سپس از عملگر اشاره * استفاده
م ىكنيم تا اشارهكر را اعلان كنيم.
صفحه 335:
برای مثال دستور :
- آدرس يك شى از نوع BESS epee SAL
اشارهكرى از نوع * ذخيره كرد و آدرس
يك شوازنوع 93]6]رافقط مىتوان در
اشارهكرى از نوع yee no ل ل ام
CIETY ل RON
اده
4S نوع متغيرهايى است كه اين اشاره كر آدرس
ا ا ۳
اشارة كر owe
صفحه 336:
۱۳ Cee a EE
برنامة زير يك متغير از نوع 1118 به نام 19 و يك اشاردكر از نوع 1131*
به نام 013 را اعلان مىكند:
n= 44, &n = 0x0064fddc
pn = 0x0064fddc
۱۳ الا ® con = ox0064fdeo
int main()
Couey SY Sa) ee sa کی ۲ ح
&n << endl;
int* pn=&n; // pn holds the address
of n
cout <<" pn =" << pn << endl;
RS Le epee BAN | رم er eR) | سر رد ی ere د 3 ل و fl
صفحه 337:
متغیر ۲۱بامقدار ۴۴ مقداردهى
ree) آدرس ۱ 3
db ,0 Ox0064fddc
درس ]١ مقداردهى شده. يس
ا وه ۱۳
020064100 است (خط دوم
خروجى اين موضوع را تاييد
00064100
صفحه 338:
اما یک متفیر مستقل است و آدرس مستقلی دارد.
كلدل SN ۳ ناك سك دده كما سوم
وقتی میگوییم.. ۱۳۳5 .
به اشاره میکند»
g pn یعنی درون
5 دارد. eC oP
صفحه 339:
قدلیبلبید
فرض كنيد ١ دارای مقدار ۲۲ باشد و 0۲۱ اشاره گری به ۲۱
باشد. با این حساب باید بتوان از طریق 0۲۱ به مقدار ۲۲
رسید. با استفاده از * میتوان مقداری که اشارهگر به آن
اشاره دارد را به دست آورد.
صفحه 340:
|
این برنامه همان برنامهة مثال ۷-۴ است. فقط یک خط کد بیشتر دارد:
int main() |
ا اك
cout << "n="<<n <<", &n =" << &n<<
endl;
int® nn—f.n- Inn halide tha addracs
۳ ا ل است زيرا
هر دو یک مقدار دارند.
صفحه 341:
{ int n=44;
cout<<" n="<<n <<endl;
cout<<" &n=" << &n << endl;
int* pn=&n; _—// pn holds the address of n
cout <<" pn =" << pn << endl;
cout <<" &pn =" << &pn << endl;
cout <<" *pn =" << *pn << endl;
int** ppn=&pn; // ppn holds the address of pn
cout <<" ppn =" << ppn << endl;
cout << " &ppn = " << &ppn << endl;
cout << "*ppn =" << *ppn << endl;
cout << "**ppn = " << **ppn << endl;
صفحه 342:
فا iy
در برنامهٌ بالا متغیر ۱ از نوع ]1۲ تعریف
شده. 0۲۱ اشاره گری است که به ۲ اشاره
دارد. پس نوع 0۲ باید ]0]* باشد. 001۱
اشارهگری است که به ۵۲۱ اشاره میکند.
پس نوع 00۲ باید ]0]/:* باشد. همچنین
چون 00۲ به 0۲۱ اشاره ye dul
0 مقدار 0۲۱ را نشان میدهد و چون
7 به ۱ اشاره دارد. پس *0۲۱ مقدار 10
- لا
&n
0x0064fd78
pn
0x0064fd78
&pn
0x0064fd7c
*۵0 < 4
ppn
۱ ۹۹
&ppn
0x0064fd80
صفحه 343:
عملگر مقداریابی * و عملگر ارجاع 6۷ معکوس یکدیگر
رفتار م ىكنند. اكر اين دو رابا هم تر كيب كنيم: يكديكر
sep) ا ل ا 2 ا
esa ا ا 0
مقداری که در آدرس n& قرار كرفته رابه دست آورد.
Sey ee ea eyed ee pei come pees ۱
0 یک اشاره گر باشد. *0 مقداری که 0 به آلن اشاره
دارد را مىدهد. از طرفى بااستفاده از عملكر نب
Ste ae SEN ee Te) ا 0
آوریم. پس ABIlg> P 99> L ply Px& )139 5
قرار گرفتن اپن عملگرها مهم است. یعنی */۷6 با
owl ile Cad pl nx& ۱
صفحه 344:
عملكر * دو كاربرد دارد. اكر يسوند يى نوع
pers ا ل ل ل
تعريف مىكند و اكر ييشوند يك اشارهكر
باشد (مثل *0]) آنگاه مقداری که 0 به آتن
دو كاربرد دارد. اكر يسوند يك نوع باشد
(مثل 6»1108) یک نام مستعار تعریف میکند
و اگر پیشوند یک متفیر باشد (مشل 06۲)
Petre ne orl) تا
صفحه 345:
يى دستور جايكزينى دو بخش دارد: بخشى كه در سمت
جب علامت جايكزينى قرار مى كيرد و بخشى كه در سمت
راست علامت جایگزینی قرار میگیرد. مثلا دستور < n
Heys) متفیر ٩ در سمت چپ قرار گرفته و مقدار ۵۵ در
سمت راست. این دستور را نمیتوان به شکل ۵۵ - 7۲۱
7 ثابت است و نمى تواند مقدار
بكيرد. يس هنكام استفاده از عملكر جايكزينى بايد دقت
كنيم كه جه جيزى رادر سمت جب قرار بدهيم وجه
حيزى رادر سمت راست.
صفحه 346:
۱۳ re ie eee aad
۳ ۰ Ce) Ee rte) قرار بگیرند
چیزهایی که میتوانند در سمت راست جایگزینی
۱ قرار بكيرند
(و به طور کلی اشیا) چپمقدار هستند و لیترالها
7 ("ABC" ۱۱۰۳۵
صفحه 347:
یک ثابت در ابتدا به شکل یک چپمقدار نمایان میشود:
const int MAX = 65535; // MAX is an
value
1 are) eee ae) epee eee pe ved] |
استفاده کرد:
MAX = 21024; // ERROR: MAX is
constant
به این گونه چپمقدارهاء چپمقدارهای «تغیبر ناپذیر» گفته
میشود. مثل آرایهها:
int a[] = {1,2,3}; //O.K
صفحه 348:
1 7 fel fre) Pe OMe See ee
پذیر نامیده میشوند. هنگام اعلان یک ارجاع به یک چپمقدار نیاز
داریم:
int& r =n; //O.K. nis an ۱۷۵۱6
eer be lend Mo eB ا anc
int& r = 44; // ERROR: 44 is not an Ivalue
int& r = n++4; // ERROR: n++ is not an
lvalue
int& r = cube(n); // ERROR: cube(n) is not
an lvaluel-—L_values 2- R_values
ا eer ۱
میتوان تابع را به یک چپمقدار تبدیل کرد.
صفحه 349:
بایکشاز نوعلیجاع -7
۱
رد ۳ دیدیم. این دو شیوةٌ تبادل در مورد باز گشت از
ا
توابعى كه تاكنون ديديم بازكشت به طريق مقدار داشتند.
ee 2) ات الم ا ل ا 00
مى توانيم تابع را طورى تعريف كنيم كه به جاى مقدار,
pees re ا ل را
را بازكشت دهد., يك ارجاع به 117 را بازكشت دهد.
صفحه 350:
خواهد بود زیرا مقدارهالیترال هستند و لیترالها
راست مقدارند. به اين ترتيب تابع رافقط در سمت راست
یک جایگزینی میتوان به کار برد مثل:
m = f();
وقتی باز گشت به طریق ارجاع باشد. تابع یک چپمقدار
py ee ارجاعها جب مقدار eel DP ye ecene.) حالت
تابع ۳ میتوان در سمت چپ یک جایگزینی قرار داد مثل.
f() = m;
صفحه 351:
7 Pen oes ae ae nb) ere Meco
ارجاع را به عنوان يسوند نوع باز كشتى درج كنيم.
Fee ل
int& max(int& m, int& n)
{ return (m>n?m:n);}
int main()
{ intm = 44, n = 22;
max(m, ,۱( >> عع" معدم عع » <a Mas بل
صفحه 352:
تابع 1 از بين و !! ۱۳7۳50 بيدا کرده
و سيس ارجاعى به آن را باز مى كرداند.
(11376)133,10 آدرس 1179 را برمى كرداند.
يس وقتى مىنويسيم 55 > (1113))118,11: مقدار
0 در حقيقت درون متغير !11 قرار مى كيرد (اكر
۱ < باشد).
7۳۱۳۱ کر Repel re car en Ore
Ayre) eee ee eae
صفحه 353:
اخطار:
وقتی یک تابع پایان میبابد. متغيرهاى محلى آنن نابود
ee cede Rear het eed oc ae Reed ald
بازذكشت ندهيد زيرا وقتى كار ۱
متغيرهاى محلىاش غير معتبر مى شود و ارجاع بازذكشت
داده شده ممكن است به يك مقدار غير معتبر اشاره
داشته باشد. تابع 11937() در مثال بالا یک ارجاع به ۲
یا 0 را بر میگرداند. چون ۲ و 9 خودشان به طریق
ارجاع ارسال شدهاند. يس محلى نيستند و بازكرداندن
tulir Fapae S| ل 1
صفحه 354:
e ات۳
۱ beeen kee ee Bl Eee
یک ارجاع درآمده است.
صفحه 355:
float& component(float* v, int k)
و۱2
int main()
{ float v[4];
for (int k = 1; k <= 4; k++)
component(v,k) = 1.0/k;
for (int i = 0; i < 4; i++)
(fella <q AV ee عت ۱۱ کر < اب یت
endl;
7
صفحه 356:
تابع و ۳
۱
يكى» تغيير كند. بنابراين (0111201111)1/,3©
الل ا ا
eS] 0
صفحه 357:
آيليدها ولشليدكرها -8
027 ا eB LC SCE ee SCs
از اعمال حسابى را مىتوان روى اشاره كرها انجام داد.
حاصل این میشود ا دیگری از حافظه
FN oe Pee Sea cP SL
افزايش و يا كاهش داد و مىتوان يك عدد صحيح را به
0 ten vy)|
کاهش اشاره كر بستكى به نوع دادهاى دارد كه اشاره كر
به آن اشاره شابن
tis lon ۷-۱۰ مثال
صفحه 358:
int main()
{ const int SIZE = 3;
short a[SIZE] = {22, 33, 44};
cout << "a =" <<a << endl;
cout << "sizeof(short) = " << sizeof(short) << endl;
short* end = + SIZE; converts SIZE to
1ه is e ot 7
wry
*p = 33
۲۳
۶ < او 5۳0۲
for (short* p = a; p < end; p++)
{ sum += *p;
8 ۳ ۰۱۴ >> دم
cout << "\t *p
sizeof(short) = 2
۱۳ نگ He)
Wines
p = Ox3fffdic
sum = 55
oT ee ی ها
صفحه 359:
0 ا ل eae Conga
ا 1 رت PCa SBC Prue ip) RCo see
ا اشاره گری به
cute L pl» Sizeof(double) ت۰۵
بايت باشدء. هر كاه كه 0 يك واحد افزايش يابد,
ا اه ات ا ل ا ات
صفحه 360:
: مثلا كد زير
float a[8];
float* p =a; //p points to a[0]
++); // increases the value of p by sizeof(float)
صفحه 361:
PRC 1 prtoe Fa al a (oy~ | ey
درون 0 را“ بايت افزايش مىدهد و 5 -+ م
بايت افزايش میدهد. با استفاده ٠١ مقدار درون (] را
از خاصيت مذكور مىتوان آرايه را ييمايش نمود: يك
اشارهكر را با آدرس اولين عنصر آرايه مقداردهى
کنید. سپس اشاره گر رايى در يى افزايش دهيد. هر
افزایش سبب میشود که اشاره گر به عنصر بعدی
0 ere ear gc hee reece wha PBT |
CCN beep pee oY Tce Bc
صفحه 362:
Pre اا
float* p = a; // p points to a[0]
و ن // now p points to
a[5]
یک نكتهةّ ظریف در ارتباط با آرایهها و اشاره گرها وجود
دارد: اكر اشاره كر را بيش از ايندكس آرايه افزايش
دهيم: ممكن است به بخشهايى از حافظه برويم كه
هنوز تخصيص داده نشدهاند يابراى كارهاى ديكر
تخصیص ا دادن مقدار این بخشها باعث
پروز خطا در برنامه و کل سیستم میشود. هميشه باید
و و و
صفحه 363:
SCS تن ne eho at Se Ree eee
float a[8];
float* -ام al7]; // points to last element in the
الريك
last ۱۰ 0 ره رید
إغمع دمعاء
ا ل ا Si
مثال بعدی نشان میدهد که ارتباط تنگاتنگی بین آرایهها
واشارهدكرها وجود دارد. نام آرايه در حقيقت يك
لل ل ا ا pee
همجنين خواهيم ديد كه اشارهكرها را مانند هر متغير
|
صفحه 364:
[0 Be ieee elem a
int main()
{ short a[] = {22, 33, 44, 55, 66};
عب هو کب ۲ < ۰:2۵ ۲ که و کب ۰ < ۱2۵ کع> الا60
endl;
for (short* p = a; p <a +5; p++)
a = Ox3fffd08, *a = 22 Fa #p <<
PROS TiCc(1s ar awed cS
p = Ox3fffd0a, *p = 33 0
p = Ox3fffdOc, *p = 44
p = Ox3fffd0e, *p = 55
p = Ox3fffd10, *p = 66
p = Ox3fffd12, *p = 77
صفحه 365:
۳ |
:302 اشاره مى كنند و هر دو داراى مقدار
8 سستند. اما 2 یک اشاره گر ثابت است و
ee ere LA CEC NEM CC Be ere 1
ل FLOP 1
at5) > 0) حلقه را خاتمه مىدهد. 2+5 به شكل
زير ارزيابى مى شود:
Ox3fffd08 + 5*sizeof(short) = Ox3fffd08
Ox3fffd08 + Oxa = Ox3fffd12 = 5*2 +
پس حلقه تا زمانی که 03۲۴۴012 > 0۵ باشد ادامه
مییابد.
صفحه 366:
عملگر زیرنویس [] مثل عملگر مقداریابی * رفتار میکند. هر دوی
Bead os ee ep EE pI ae eel Cea gel
alO] == *a
a[1] == *(a + 1)
a[2] == *(a + 2)
صفحه 367:
Fae a a Oy
22 در این مثال, تابع 0106 در میان 91 عنصر اول آراية 81 به دنبال 92 عنصر اول آراية
CREE eS eee VC CRC See Mere ا ا SCI
۳ 6 Batre)
short* loc(short* al, short* a2, int n1, int n2)
{ short* endl = al +n1;
for (short* p1 = al; pl <end1; p1++)
if (*pl == *a2)
{ for (int j = 0; j < n2; j++)
if (p1[j] != a2[j]) break;
if (j == n2) return pl;
}
return 0;
صفحه 368:
int main()
{ short al1[9] = {11, 11, 11, 11, 11, 22, 33, 44, 55};
short 22]5[ - 11, 11 11,22, رو
cout << "Array al begins at location\t" << al << endl;
cout << "Array a2 begins at location\t" << a2 << endl;
short* p = loc(al, a2, 9, 5);
if (p)
{ cout << "Array a2 found at location\t" << p << endl;
for (int i ناد عن
صفحه 369:
Ox3fffd12 مماغوعها غة را رواد
Array a2 begins at location Ox3fffdos
Array a2 found at location Ox3fffd16
Ox3fffd16: 11 Ox3fffd08: 11
Ox3fffd18: 11 Ox3fffd0a: 11
Ox3fffdla: 11 Ox3fffdOc: 11
Ox3fffdic: 22 Ox3fffd0e: 22
Ox3fffdle: 33 Ox3fffd10: 33
صفحه 370:
kg و
وقتی یک اشاره گر شبیه این اعلان شود:
0 (۱17
AT ١
ee 57 جهاربايتى به ]| تخصيص داده مىشود (معمولا
۱ ا ل ۱
اما به هيج جايى اشاره نمى كند زيرا هنوز آدرسى 3917 تن
قرار نگرفته. به چنین اشاره گری اشارهگگر س رگردان
مى كويند. اكر سعى كنيم يك اشارهكر سركردان را
مقداریابی یا رجاع کنیم با خطا مواجه میشویم.
صفحه 371:
۱7 ار
*0 < 3.14159: // ERROR: no storage
has been allocated for *P
A caer we Hen S) MSP ICN Des Beaices
را كجا ذخيره كند. براى رفع اين ta Cee ether
111111111111119
11081 7۷ < 0 ۱۱۷ cintains the value 0
float* p = & // now p p
0-00 415 WE
صفحه 372:
در اين حالت مىتوان به «0] دستيابى داشت زيرا حالا 2] به كا اشاره
م ىكند و آدرس آنن را دارد. راه حل ديكر اين است كه يك آدرس
eed ا ل 0
خارج مىشود. اين كار با استفاده از عملكر /الا©19 صورت مى يذيرد:
float* p;
p = new float; // allocates storage for 1
float
*p = 3.14159; // O.K. assigns this value to that
صفحه 373:
با این دستور, اشاره گر 0 از نوع :7103+ تعریف میشود
و سپس یک بلوک خالی از نوع 1031] منظور شده و
ل او rere ل PE eee
89 ."در آن آدرس قرار مى كيرد. اكر عملكر
لالا١! نتواند خانة خالى در حافظه بيدا كند. مقدار صفر را
برمى كرداند. اشارهكرى كه اين جنين باشد. «اشاره كر
تهىء يا |-الالاا مینامند.
صفحه 374:
با استفاده از کد هوشمند زیر میتوانیم مراقب باشیم که
اشارهكر تهى ايجاد ل
double* p = new double;
if (p == 0) abort(); // allocator
failed: insufficent memory
else *p = 3.141592658979324;
در اين قطعه كد. هر كاه اشارهكرى تهى ايجاد شد.ء تابع
الل ا Bye
صفحه 375:
تاكنون دانستيم كه به دو طريق مىتوان يك متغير را ايجاد و
مقداردهى كرد. روش اول:
allocates // ؛
named memory
و روش دوم:
/ (9
allocates unnamed memory
صفحه 376:
0616186 عملكر Do
عملكر -. . . ..عملى برخلاف عملكر ١... دارد. كارش اين است
كه حافظة اشغال شده را آزاد كند. وقتى حافظهاى آزاد شود. سيستم
Tee oc ا ا ا 000
CCE Fae ا | لل ل 3
كار برد كه با دستور الا ©19 ايجاد شدداند. وقتى حافظة يك اشاره كر
ال ا ا ل ا ا دوباره اين
حافظه تخصیص یابد:
float* p = new float(3.14159);
delete p; // deallocates q
Be) oer M18) Femi cele ar
deallocated
صفحه 377:
وقتى اشاره كر (] در كد بالا آزاد شود. حافظهاى كه توسط
۷ به آن تخصیص يافته بود. آزاد شده و به میزان
(512601)103 به حافظة آزاد اضافه مىشود. وقتتى
|
که مقداردهی نشده. ا اشاره گر سر گردان
میگویند.
اشاره كر به يكد شىء ثابت را نمىتوان آزاد كرد:
const int* p = new int;
delete p; // ERROR: cannot delete pointer to const
objects
علت اين است كه «ثابتها نمى توانند تغيير كنند».
صفحه 378:
per ats ead ات
bey ese] |S) Rover 3017
اشتباه غير عمدى زير مى شود:
// x contains the value
3.14159
// p contains the address of x
// WARNING: this will make x
صفحه 379:
آيليمهاوبويا -11
خر Pe iv
تخصيص داده مى شود:
نام آرایه در
//a is a const pointer to a block of 20
floats
م5 50//
ل ل ا So nee eee
ل |
iyo Teor ا ا ل ۱
Bey ed ل ا ا ا ا كه
یافت حتی اگر از آن هیچ استفادهای نشود.
صفحه 380:
۹ Leonie re)
ever ea pes te eRe P Ee Tony RESTO eter Rarency
يابد:
700 ا ل العلل cor elena Eeyore)
02000 2 0 ا ا ل BCs
م Bp ree heer Se rin ل Lie
بستهیندی پویا۳ یا «بستهبندی زمان جرا» می گویند.
صفحه 381:
0
۱
پایان اجرای برنامه, حافظةً تخصیصی به آسن مشغول
آراية يوياى (] در زمان اجرا و هر جا كه
ا ا 0 ا 57
عملكر 1616© حافظة تخصيصى به آن را آزاد كرد:
delete [] p;
برای آزاد کردن آرايةٌ پویای 0 براکتها [] قبل از نام 0
باید حتما قید شوند زیرا 0 به یک آرایه اشاره دارد.
صفحه 382:
مثلل 8 /-١ استفاده از آرايههلى يويا
ا 2 0
void get(double*& a, int& n)
cout << "Enter number of items: "; cin >> n; {
a = new double[n];
cout << "Enter " << n << " items, one per line:\n";
for (int i = 0; i < n; i++)
cout << "\t" <<i+1 <<": "; {
cin >> ali];
1
void print(double* a, int n)
ee ee oe) ۰
cout << a[i] <<"";
cout << endl;
1
صفحه 383:
int main()
0 اا Mer MMe ame MTT] Le 1 3-1 |
وت رازه۱
int n;
get(a,n); 1 now a is an array of n doubles
print(a,n);
Geleten ay Arias eeu orien ui
again
get(a,n); // now a is an array of n doubles
print(a,n);
}
صفحه 384:
Enter number of items: 4
Enter 4 items, one per line:
1: 4
2:77.7
» نمه عدم
ل
44.4 77.7 22.2 88.8
Enter number of items: 2
Enter 2 items, one per line:
1: 3.33
2: 9.99
9 ع ع
ارو حا QQ
صفحه 385:
۷ ۳ ya Fogle
«اشاره كر به يى ثتابت» با 7 ثابت» تفاوت زر
7 ات ا erie
ثابتها
ا 7۳ اشاره كر اعلان شده. اشاره كر ,
اشاره كر ثابت (2. اشاره به يى ثابت ©0]. اشاره كر
ثابت به يى ثابت 066 :
صفحه 386:
ms رو
غصاا مج مغ عمعغمامم د // int* p = &n;
++(*p); // OK: increments int *p
++p; // OK: increments pointer p
int* const cp = &n; Mie Seelam oe
++(*cp); // OK: increments int *cp
++cp; // illegal: pointer cp is const
const int k = 88; ۱۱ < 2 ۲
const int * pc = &k; // a pointer to a const int
++(*pc); // illegal: int *pc is const
++pc; // OK: increments pointer pc
ola int* const cpc = &k; // a const pointer to a const
++(*cpc); // illegal: int *pc is const
صفحه 387:
اشاره كر ( اشاره كرى به IG P 995 em cul patito
افزايش است (++0) و هم مقدارى كه ( به لن اشاره مى كند
قابل افزايش است (++(*2)). اشاره كر 0© يك اشاره كر
ثابت است. یعنی آدرسی که در 00 است قابل تغییر نیست
ب ee OP 0007
کرد. اشاره گر 0 اشاره گری است که به آدرس یک ثابت
اشاره دارد. خود 0©(] را مىتوان تغيير داد ولى مقدارى كه
O16 ل 0 (ol
يك اشارهكر ثابت به يى شىء ثابت است. نه مقدار 6ع م0 ©
قابل تغيير است و نه مقدارى كه آدرس آن در ©6 © است.
صفحه 388:
آیلیهاواز-اشایهگرها -13
میتوانیم آرایهای تعریف کنیم که اعضای آن از نوع
اشاره گر باشند. مثلا دستور:
float* p[4];
EL CLL eres] pew Uy ele اشارهكرى
به 11938])اعلان مىكند. عناصر اين آرايهرامثئل
اشاره كرهاى معمولى مى توان مقداردهى كرد:
new float(3.14159); = [0]م
p[1] = new float(1.19);
صفحه 389:
اين آرايه را مى توانيم شبيه شكل مقابل مجسم كنيم:
مثال بعد نشان میدهد که آرایهای از اشارهگرها به چه
دردی میخورد. از این آرایه میتوان برای مر تبکردن
یک فهرست نامرتب به روش حبابی استفاده کرد. به جای
0
میشوند. Pp
8
oe |
صفحه 390:
PeaD ool Ld را
void sort(float* p[], int n)
float* temp; {
for (int i = 1; i < n; i++)
for (int j = 0; j < n-i; j++)
([1+زام* < [زام*) ؟1
زرا - موعة )
:1+ نزام < [ز]0
p[j+1] = temp;
}
صفحه 391:
۱ ae
حلقههای تودرتوی ۴0 بررسی میکند که آیا مقادیری که
اشاره گرهای مجاور به آنها اشاره دارند. مرتب هستند یا نه.
اگر مرتب نبودند. جای اشاره گرهای آنها را با هم عوض
مى كند. در يايان به جاى اين كه يى فهرست مرتب داشته
باشیم. آرایهای داریم که اشاره گرهای درون آتن به تر تیب
قرار كرفته اند.
صفحه 392:
A aS le meee Sl eel
یک اشاره گر میتواند به اشاره گر دیگری اشاره کند. مثلا:
char c = 't';
char* pc = &c;
char** ppc = &pc;
char*** pppc = &ppc;
**oppc = 'w'; // changes value of 6
30
حالا 0 اشاره گری به متغیر کاراکتری » است. 0۳ اشاره گری به
So Lil 7 0 ا 1۱
صفحه 393:
صفحه 394:
لشایدگر به تولبع -15
این بخش ممکن است کمی عجیب به نظر برسد. حقیقت
این است که نام یک تابع مثل نام یک آرایه. یک
ار
مىدهد كه كدهاى درون تابع را
كرفتهاند. يس بنابر قسمت قبل اكر اشارهكرى به تابع
اعلان کنیم. در اصل اشارهگری به اشاره گر دیگر
تعريف كرددايم. اما اين تعريف. نحو متفاوتى دارد:
function f 06601۵۲65 / :(غصأ)؟ غصا
int’ (*pf)(int); // declares function
pointer pf
صفحه 395:
ee ES Dep ne EME eee MeL Se
اين كه 5(] اشارهكرى به يك تابع است. بعد از كن يى
210 ا ا SEPA LY
ل و OL cy
CBT Ie ON Coca ا
صفحه 396:
فايدهٌ اشاره گر به توابع این است که به این طریق
میتوانیم توابع مرکب بسازیم. یعنی میتوانیم یک تابع را
ا ا ل ۳
a petioles Polar eecr yes Benet] .|
صفحه 397:
مثال ١-١8 تابع مركب جمع
تابع 514130() در اين مثال دو يارامتر دارد: اشارهكر تابع 05] و عدد صحيح 19:
int sum(int (*)(int), int);
int square(int);
int cube(int);
int main()
{ cout << sum(square,4) << endl;
cout << sum(cube,4) << endl;
صفحه 398:
تابع 7 يك بيارامتر غير معمول دارد. نام rai
دیگری به ا ل شده. هنگامی که
ور مقدار
square(1)+square(2)+square(3)
(50013:)4+ بازكشئست ذاده مىشود.
جون(©12) 50101316 مقدار oS onl K*K
SUM (Square,4) 19515 مقدار
(ejb 9 09905 4 _wloce Ly Me =1 F494 F 4) 95 513
تعریف توابع و خروجی آزمایشی به شکل زیر است:
صفحه 399:
int sum(int (*pf)(int k), int n)
{ // returns the sum f(0) + f(1) + f(2) + ... + f(n-1):
1552:
for (int i = 1; i <= n; i++)
s += (*pfi);
تاناعم 5
1
نيلات نت فليا
صفحه 400:
5 در فهرستهارلمترهائتابع 0051017) يى
اشايدكر به تابع لسستلشاره كر به تابعىكه لن
تابع پارلمترءاز نوع 80۴ دارد و مقدارعاز نوع Int
رابرميكردلند »ادر تابع 510117 لصلالستفادهم
0201 001 00 0 1 0 vod
4s ۴ ب به تابعیاشاید دارد که سس نوع
صفحه 401:
Se CirE ل ا 026 الل نك
آدرس شروع تابع ©5010131() را دارد. بنابراين وقتى
تابع 0514117 به شكل sum(square,4)
pee be ال ا و
اشاره كر 65] فرستاده مىشود. با استفاده از عبارت
DI LED) ا ا 0 ا
oi 0 ا
صفحه 402:
NULL , NUL-1¥
ثابت صفر (۰) از نوع 1108 است اما این مقدار را به هر نوع بنیادی دیگر
میتوان تخصیص داد:
char c = 0; // initializes c to the char '\O'
short d = 0; // initializes d to the short int
0
int n = 0; // initializes n to the int 0
unsigned u = 0; // initializes u to the unsigned
int 0
float x = 0; // initializes x to the float 0.0
dnithle 7 — nN: | مود روز 7 tr the doiihla
صفحه 403:
مقدار صفر معناهاى كوناكونى دارد. وقتى براى اشياى
عددی به کار رود. به معنای عدد صفر است. وقتی برای
ل ا ا ل Oe RC
الالاا است. الالاا معادل كاراكتر ٠٠" نيز هست. وقتى
مقدار صفر برای اشاره گرها به کار رود. به معنای «هیچ
جيزءيا ا الالاا است. | الالاا يى كلمة كليدى است و
کامپایلر آتن را میشناسد. هنگامی که مقدار أالالا با
ا ا 0
0 در حافظه اشاره دارد. اين خانة حافظه. يى خانة
استثنایی است که قابل پردازش نیست. نه میتوان آتن
خانه را مقداريابى كرد و نه مىتوان مقدارى را درون آن
ا ا میگویند.
صفحه 404:
Key ed TBS) esl ed) ان
Ba pret i bes cy 6 ل ا Bul Ree Uh eye Rete ree i ep
Pree Cer ep Revel) LU) 8 Biscay) boi Cave eco] DT care
int*p = 0; //p points to NULL
*p = aes // ERROR: cannot dereference the NULL
foeyial ee
يس خوب است هنكام مقداريابى اشارهكرهاء احتياط كرده و بررسى كنيم
که آن اشارهگر االالا نباشد:
if کر
ere w le 0 ل ا ا ا ان
fond eB Seen ee pen)
if (p != NULL) *p = 22;
صفحه 405:
اشارهكرها را نمىتوان ناديده كرفت.
آنها سرعت يردازش را زياد مىكنند و كدنويسى را
با استفاده از اشارهگرها میتوان به بهترین شکل از
حافظه استفاده كرد.
۱ ا ede)
ساخت. 20000
صفحه 406:
صفحه 407:
صفحه 408:
آچه دراین پلسه می فینید
! مروری بر اشارهگرها
! رشتههای کاراکتری در ()
1
" چند تابع عضو 2 و 2
" توابع کاراکتری () استاندارد
Rp Cp) ae
SES ES ae 0[ )2
صفحه 409:
0
cS دقیقتر به تبادل دادهها
دی قالببند
خی : اشنابي بأ ۷ M P| آنهاء.
آنوع ا
أفايلها
صفحه 410:
معرفی رشتههای کاراکتری به سبک 9 بب+و
نحوةّ ایجاد و دستکاری آنها و همچنین نحوةٌ
استفاده از فايلهاى متنى براى ذخيره سازى و
بازيابى اطلاعات.
صفحه 411:
هدفهای رفتاری: انتظار میرود پس از پایان این جلسه بتوانید:
were IY Brod pC Layee 7 1
- توابع معرفى شده عضو 25 و 7701 را شناخته و وظيفة هر يك را
شرح دهید.
- رشتههاى كاراكترى به سبى (00++ استاندارد را ايجاد نماييد.
- مفهوم «ورودی قالببندی شده» و «ورودی قالببندی نشده را
Emel by ۱
Et Ree PRC aD Mad cae cle
| ل Se Ee ل 26
- اطلاعات كاراكترى و رشتهاى رادر يك فايل متنى نوشته يااز
0
صفحه 412:
:مقدمه
دادههایی که در رایانهها پردازش میشوند هميشه
نيستند. معمولا لازم است که اطلاعات
کاراکتری مثل نام افراد - نشانیها - متون -
توضیحات - کلمات و ... نيز يردازش گردند.
جستجو شوند. مقایسه شوند. به یکدیگر الصاق
شوند يا از ی
در اين حلسه بررسى مى كنيم 4S چطور اطلاعات
تا
شكل دلخواه به -.:2-.. بفرستيم. در همين راستا
توابعى معرفى مى كنيم كه انجام اين كارها را آسان
ام كلند
صفحه 413:
ل ل
| Rents Sake)
حافظه میباشد. نوع این متغیر از نوع مقداری است
که در آن آدرس ذخیره شده. با استفاده از عملگر
ارجاع 6 میتوان آدرس یک شی را پیدا کرد.
همچنین با استفاده از عملگر مقداریابی * میتوانیم
مقداری که در یک آدرس قرار دارد را مشخص
كنيم. به تعاريف زير نكاه كنيد:
6026 د و ور
ا
صفحه 414:
ور(
در ی ۱
کاراکترهاست که این آرایه دارای ویژگی مهم زیر است:
-١ يك بخش اضافى در انتهاى آرايه وجود دارد كه مقدار
اك ب بون ل ل gore oe ول
تا
٠" - رشتة كاراكترى را مىتوان با ليترال رشتهاى به طور
مستقیم ۳ ره
sir[] = "striae"; ان
ا ا ا Pay Riper Wemreor
Wy gt yt p UGS
صفحه 415:
ا- كل يكد رشتة كاراكترى را مىتوان مثل يك متغير معمولى
چاپ کرد. مثل:
در این صورت. همه کاراکترهای درون رشتهة کاراکتری یکی
PTT me pee ae 7
برخورد شود.
- يك رشنة كاراكترى راامىتوان مثل يى متغير مفدولى ال
ورودى دريافت كرد مثل:
صفحه 416:
۵ - توابع تعریف شده در سرفایل <:7> را
wl» | دستکاری رشتههای کاراکتری oe
کار بگیریم. اين توابع عبارتند از:
Oca ا 1
(eee ae SRP
صفحه 417:
۳ LCM FY Seed DCMT LF Con)
۱ CoC oo ep Ce ORE ee RC er Cr Ae
ان(
۷
Por (iat i = O; i < S; i++)
at} << Mel >> ۱ >> y=" << Fall << ۳
۱
صفحه 418:
رشتة کاراکتری < دارای پنج عضو است که
عضو پنجم. کاراکتر ۰ مى باشد. تصوير
خروجى اين مطلب را تاييد مىنمايد.
39 کاراکتر ۱ ۰ به .. فرستاده
enero ne eed mre ee
سا
خط آخر خروجی. عضو پنجم را نشان می
دهد كه ميان دو علامت ايستروف هيج
جيزى جاب نشده.
ههه 1516
OO oOs4 3
صفحه 419:
1
در (0++ به جند روش مى توان رشتههاى كاراكترى
رادريافت كرده يا نمايش داد.
یک راه استفاده از عملگرهای کلاس 27:7 است که
ا ا 0
Pe ere Ree Ea ES SCENE TD)
در ادامه شرح میدهیم.
صفحه 420:
معال ۸۰۱۳ روش ساده دربافت و بمایش رستة فاق كار اكترق”:
در برنامة زير يك رشتة كاراكترى به طول 1 كاراكتر اعلان شده و
كلماتى كه از ورودى خوانده مى شود در آن رشته قرار می گیرد:
|
0
| _
کی
ا ل
i
صفحه 421:
g vin gas QU i> مت
ی ee
شامل توابع زير است:
ات هت
Diu.
70 همه این توابع شامل پی پیشوند 7:7 هستند زیرا آنها طضوی از
میباشند. به 7۷ شیء فرآیند خروجی می
ay mae ESO care ror ect RUAN ees
5 ل لت Papi yo
الما Rye Ow ot an) a Be)
درون 1 خوانده شود و مابقى كاراكترهاى وأزد شده تاديده
0
صفحه 422:
ط ات یت دا ار
:این برنامه ورودی را خط به خط به خروجی میفرستد
20 1
رگا {
7
٩۱ رک
eee رز
ل
i
صفحه 423:
را
مرا
اه
3
ل هرت سرت وا
۱ eal Glico) Borat Me هال"
Ae cd ؟
۱
صفحه 424:
لا كل
این برنامه تعداد حرف "< در جریان ورودی را شمارش
مى كند. قا وقتى (5-):<.: كاراكترها را با موفقيت به درون
میخواند» حلقه ادامه میباید: oe
Ree ale
oe 0 كرك Pe
يكيس 22 = = iP (ck
1
۱
صفحه 425:
ل
S, ل ل ورودی را به حرف بزرگ تبدیل
كرده و آن را مجددا در خروجى جاب مى كند:
ل
char ck, pre = \O }
Pe CC)
Ca dec eC
مت مب مسا
نم تست
۳
{
صفحه 426:
درل اس مسر امسر رت
Pape ICON BSE orc ie Ony even Sine ee eB
:مى كند
Reker dn nd
سسحتي ددنت ony
ene | للب یر نا 0
1
(edn)
۳
نت
1
۱ Ont teed) 3
| be }
زه << وم
صفحه 427:
تابع 00
اين نسخه از تابع 14 () معادل آن است كه در مثال قبلى بودة
0
ae رت
sh
while (ch = vis.perh())
iP (ch >= 'O' && vk <= 'O')
Bo
Rand
0
ا
Ree cc)
۳
صفحه 428:
توابع کاراکتری استاندارد
در مثال 8-8 به تابع:1017() اشاره شد. اين فقط يكى
از توابعى است كه براى دست كارى كاراكترها استفاده
epee cael Uy ope ا ا 2
7 تعریف شده به شرح زیر است:
شرح نام تابع
A int isalnum(int c);
ار > کاراکتر الفبلیی یا عددی باشد مقدار فیرصفر ۱5۵10۳۳۳(
وگرنه صفر را برمیگرداند
۶( 106) 152100۵ 106
لكر > کاراکتر الفبليى باشد مقدار eed ۱
(۵۵
(
صفحه 429:
(eu
int iscntrl(int c);
کر » کاراکتر کنترلی باشد مقدار غیرصفر و در غیر گن.
صفر را برمى كرداند
int isdigit(int c);
اكر © كاراكتر عددى باشد. مقدار غيرصفر و در غير آن.
صفر را برمى كرداند
int isgraph(int c);
0
|
نام تابع
)015 1
Oisdigit
Oisgraph
صفحه 430:
(ese
int ispunct(int c);
اگر 6 کاراکتر چلپی به غیر از حروف و اعداد و فضای خللی باشد. مقدار غیرصفر
SS TOS seed cine Rel oleae
10 isspace(int os
ی ی لش نت ی مت ها نس SINE ام
(۱ ae الل we لمر ل
lar an en eS aad nee a
int isupper(int c);
اگر 6 حرف بزرگ باشد. مقدار غیرصفر برمی گرداند وگرنه صفر را برمی گرداند
int isxdigit(int c);
اكر © يكى از ده كاراكتر عددى يا يكى از دوازده حرف عدد شائزدهدهى شامل
را و ا ا و رد
و '2' و '5' باشد. مقدار غيرصفر برمى كرداند وكرنه مقدار صفر را برمى كرداند
int tolower(int c);
Drea ee seed arian eee cere gene ata ae ead
برمی گرداند
int toupper(int c);
اگر 6 حرف کوچک باشد. کاراکتر بزرگ معادل آن را برمی گردلند وگرنه خود 6 را
برمى كرد اند
نام تابع
Qispunct
Qisspace
Qisupper
Qisxdigit
Qtolower
Qtoupper
صفحه 431:
ee ea Lo ee eres
دريافت مى كنند و يك مقدار اودارا برمى كردانند. علت
این است که نوع 77 در اصل یک نوع صحیح است.
در عمل وقتى توابع فوق رابه كار مىبرند. يك مقدار
صفحه 432:
به خاطر دارید که گفتیم یک آرايةٌ دوبعدی در حقیقت
آرايهاى يكه بعدى است كه هر كدام از اعضاى لن يك آراية
se gee 1
peed Reo) al]
wher unve[S][CO]
ا هد تس مس مت سب
Creare 1 1
SSSI a ie aa es a cae
۳ سس 2
ere Sees 1 0
تصور كنيم.
صفحه 433:
از طويق
reper bd ee OC ped BM yee) ees eget ا EC DY ree
ree’ Sona م ل ا CU pe eWepyer eer Rey.
يك بعدى با آن رفتار مى شود.
ين
صفحه 434:
آرابهای از رشتههای کاراکتری
CUE PO Ue eee I ese SES
ذخیره کرده و سپس مقادیر آن آرایه را چاپ میکند:
مت 6۱
م۳
AN RC en Rca eS Rn aca
phi (cic. getioe(cae[pouit++], SO))
حت ول جار
cea ل ا له
Leal ce OS ا
jot << "VW" <<i <<", [" << cacvefi] << "]" << ext
1
صفحه 435:
يى آراية رشتهای پویا
Beye) el ل مىدهد كه چگونه مى توان از كاراكتر
SSE ere OS Sea SL Se)
کرد. متال زیر تقر با معادل متال ٩-٩ است. برنامه زیر
1
يك خط نوشته مىشود و هر اسم با كاراكتر '1' يايان
مى يابد. اين اسامى در آراية 77 ذخيره مىشوند.
سيس نامهاى ذخيره شده در آراية 577 جاب مى شوند:
صفحه 436:
صفحه 437:
مقداردهى يك آراية رشتهای
Te لا
سا
Weert }} ماه سا تا مان مطس۳ ۲ ) حاسمت jobor*
و ۲ << Spout
Por (ict i = 0:۱ DO; i++)
“oot << "\I" <<; <<", ۱ << xeve(i] << اله
je > >
f
1
صفحه 438:
00 5 الله مه
توابع استاندارد رشتههای کاراکتری:
سرفايل <22002> كه به آن «كتابخانة رشتههاى
کاراکتری» هم میگویند. شامل خانوادةٌ توابعی است
كه براى دست كارى رشتههاى كاراكترى خيلى مفيدند.
ene sen | ل ا ا ل ل
9۳ میدهد. این ا طول ae) رشتة pricy
۰1۰۰۰۳ (یعنی تعداد کاراکترهای لن رشته)
را برمى كرداند.
صفحه 439:
Qsiries تابع
Rowe Oe er nC eee ney Ik eee eT ey
CCA Peer SOMES Brel PCM CRY oe Pn es DC ا
ا ا و ال داده میشود:
>> #بمساوص> على اوم
)(5 كعد
[]د عصساه" زر < 00008 1
joo >> sided >> و >> 1" =o Se ae >> المج
0 ل ا
har buPPer [OO]
oot << "Cater stray") ia >> buPPer
want << "0 ("<< buPPer <<") = "<< (buPPer) << endl
صفحه 440:
4 (oir ronr(), srenr(), sire
OS Eats 11 Ee SBE Ire SESE ا ا
BG يي
مها
_ ا ل ایب
Sa ا
)09 و
CO cea MS i اال
0
مط[" >> د - م >> "إء طاطهمم (ه ,5 | " >> بحو"
w= ,')
Ho ل ae Mee
یا
ددم >> "إدص صصمم CRN AW ">> نوم
جح ]۳
۱۳ te ae a
race? Me cn a a Ma td
و
aa اد اناك
صفحه 441:
3()eropy قايع
PRO Pere ee oe rr ere TEn e)
Stoke <pereont
<tock de <potrterg
مس ب()
۶ 2 ۵۵0066 ۱
< ]6و ز
۰( وراه عخه۲ >> له ز
(0)مطمم >> " - ايحا ,[" >> )م >> "] د هنا" >> بجو
<< 4
(م) وه >> ۲ < بمط ,[" >> 6و >> ] < 6" >> وم
jeud >>
jorop{o(l,e@)
Fond << "OPer os (0,28) :ha
pot << "Well = [" << ofl >> "[, (0ج) موی >> ۲ < یبط
jeod >>
(6م) ماه >> ۲ 2 بط ,(" >> هو >> ۲ = pon << "WO
jowd >>
صفحه 442:
تب مرو مورا
۱ ی
كدص ()
| ۲8۵۵۵۵۵ < 0و ات ز
Moher sl] = "XL
joo << "DePore sirap) (ol, 2@,C):\0
ofl << "], leony = "<< stlea(o(l) << "[ = ورا" >> نحص
<< از
irteu(sO) >> ۲ 2 اما [" ک> هو >> ] < هويا" >> يوم
<< از
(0, ور موز
Soma << "Per ما( مرو
pot << 90 = [" << 5 << "], eos =" << stteu(o(l)
joo >>
"J, lexus = " << sirtea(sO) << ۵و >> ۳] > هم" >> يوم
jes >>
1
صفحه 443:
تابع الصاق رشته ؛مسب()
برنامة زیر بررسی میکند که فراخوانی ( 26 ,7)26*< چه تاثیری دارد:
منیا
ل الل ا
rap 2 [] 6د سواه
ت۱۳
الا ene eo SP
<< لمور
ee Se (ce) ال ا ا ا اي
<< از
po eee)
Cee) 0
Bey See SP ae on St)
je >>
Pe RS oe Me Seo Scar Em Sa ice)
jead >>
0
صفحه 444:
لك مه 6
رشتههای کاراکتری در (-++ استاندارد :
MSI CME ey) ا 0
و البته بخش
م ا ا 0 0 30000
سريع داددها
Oe ee ne ee Se ee Se aren)
Abel
CPD eS Sp CBee Yr Caney. pers nes ree NU rae]
عنوان پایان رشته
۱ CT ey ET Te Cy
در اين رشتههاء طول رشته نيز درون رشته ذخيره مىشود و لذا فقط به
0
برای مشخص نمودن انتهای رشته اکتفا نمیشود.
صفحه 445:
نكاهى دقيقتر به تبادل دادهها
LEN) RAE eer BN YS Pe eT
را در فالب مجموعهای از کاراکترها تایسپ میکنیم.
1 ا ل ete ea
برنامه بفرستیم» این نتایج در قالب محموعهای از
کاراکتر ها نملیش داده میشوند. لازم است که لین
کاراکترها بسه نحوی برای برناصه تفسیر شوند. مثلا
وقتی قصد داریمیک عدد صحیح را وارد کنيم» جند
كاراكتر عددى تايب مى كنيم
صفحه 446:
ee Bieter SPIN Be) bed
سیک مقدار صحیح بسازد وبه برنلمه تحویل دهد.
همجنين وقتى قصد داييميك عدد اعشارى رلبه
خروجى بفرستيم, بليدجا استفاده از راهكارى»
Re ener Sap Pees ane nee |
eT egy) لت
صفحه 447:
۱
ee ا ey Leeann Wed pre
کاراکترها را بسه دادههایسی از یسک نوع بنیادی تبدیل
۱3 cae LOSS ie By ee ie
۱ Tee eee ee) oad
زیر کلاسهایی تقسیم میشود:
صفحه 448:
شممء 1 جريلنى است كه دادههاى مورد
se. كا بل وارد شده از صفحه كترم
(OP AY رلبه کار st هاى - خروجی تابل
TN Rupe eee) es nee
)_— و fem است که دادههای Coy
نياز را از دادههاى داخل يك فليل» فراهم
میکند. شيمء Ped ASNT جريلنى رم
دادههای حاصل را درون یک فایل ذخبره
VUE ne ee Beamer Le
را در ادامه خواهیم دید.
صفحه 449:
استفاده از عملگر بیرون کشی برای كنترل كردن یک حلقه :
دل
سه
while (via >> a1)
الوح ك>ك اي >> " دي" rea i
{
صفحه 450:
ورودی قالببندی نشده:
۱ eee bE
لین تولبع برای واره کردن کاراکترها و رشتههای کاراکتری
جه کار میرونه که کاراکترهای فضای سفید را نادیده
ذمى كير ند.
TP) ا الل ان
ean ot eee ere ey eam or pee
است.
صفحه 451:
فریافت کاراکترها با استفاده از تایع .ستوز).
صفحه 452:
وارد گردن یک رشتة کاراکتری به وسیلة تابع +۵«(
De ROSIE ae bea Teele) ea) oe Eee ae Shane)
درون یک آراية رشتهای قرار داد:::
00 26 )صا م عمجم
vans eae 00ت جل ر] 801 وا دمت
(pede etre Der MG Oy ec Aor ti OMen aay pre
Oss sects
ener errr ee ae na ct (rol
jet =D
whie(cie.qwitoe(coomprfert+], LEO) && «OL )
in
Por (it HO; کر ++)
wan << ۳ >> ۲ <<" " << oneirfi] << لمم
صفحه 453:
BS) ee Ore me ey mira)
در ():+ استاندارد نوع دادهای خاصی به نام :7:77 وجود دارد که مشخصات این نوع
ا Bp eects ee ee dee pore eRe eee a aan
a te Me Tee Dene See Ret 0
میتوانند اعلان و مقداردهی شوند:
0 as ae
ace مس ت۱۳
eave ene
۱۳ ا
۱/۳ es SRS iam asc anata
صفحه 454:
استفاده از ره اروت
کد زیر یک مجموعه کاراکتر را از ورودی میگیرد و سپس بعد از هر کاراکتر
ne Ao 1
مثلا اگر عبارت ۳
"COPTOORE DOOCOEOT 6 begat
ON eee eM ee SCS ee)
The رگ DOOCG, OE, OT & begac
متن برنامه این چنین است: امس سس
ide Cae}
صفحه 455:
خابلها
يكى از مزيتهاى رايافه» قدرت نكهدارى اطلاعات
حجیم است. فابلها لین قدرت رلبه رابلنه میدهند.
Ce her ety Se es ad
SS tt Tee rd
نمی کردند.
چون اغلب برنامههای امروزیبا فایلها سر و کار
دایند»یک برنامهنییس لازم است کمبا فلیل آشنا
eee ا pes
eB کارابی ۳ را eddO LR)
صفحه 456:
۱۳ eB) ee Te Lae 3S)
ا ا ل ال
eee) Boat ا ل oar |
ل ل eros,
دو زير شاخة مرس و رو وت dot ped ومحوجدا
تقسيم مى شود.
جريان مرو براى خواندن اطلاعات ei) فلیل
اه کار میرود و جريان موص وناو براى نونتن
اطلاعات درون يك فايل استفاده مى شود.
صفحه 457:
ae a Som Serer een
شدهاند.
1 nee
ی
سا سا
۱ اک و
|
طبق کدهای فوق» ا ی
صفحه 458:
یک دفتر تلفن
برنامة زيرء جند نام و تلفن مربوط به هر يك را به ترتيب از كاربر دريافت كرده
و ذر قايلي به نام ۱۱ 1۱۱۱ 0 دخیره ميکند. کاربر براي بایان دادن
به ورودي بايد عدد (0 را تايب كند. Pree ae eee
ee ee
ee ees RC ROOD Ce
یس و مزا
سس موز
(RS et) وه ۳ RC ۲ >> فد ز
ود
SR SKC
2 بر
۳
۳
0
عدم >> السام << ' أ
aa
صفحه 459:
جستجوي یک شماره در دفثر ثلفن
اين برنامه» فایل تولید شده توسط برنامه قبل را به کار ميگیرد
و درون آن به دنبال یک شماره ثلفن ميگردد: مد رت
el داكا
میا
ee See Fel ch ۳[
aS ee >> لو
وم سر
0
اس ل 110
pe ee a oe
{
صفحه 460:
پایان جلسه هشتم
صفحه 461:
صفحه 462:
ABLE ی
(- اعلان کلاسها
- سازنددها
"- فهرست مقداردهی در سازندهها
با
0- توابع عضو خصوصى
ee و۳ )»>
صفحه 463:
۷- نابود کننده
Se
Peed Ie Eo Ore |
اعضاى دادهاى ايستا - ٠
توابع عضو ايستا -١١
صفحه 464:
هدف کلی :
آشنايى با كلاسها و اصول اولية
به کار گیری ag!
صفحه 465:
۳۹ رفتاری:
انتظار میرود پس از پایان این جلسه بتوانید:
- نحوةّ اعلان «کلاسهاء را بدانید و اعضای یک کلاس را برشمارید.
a ee BELEN Bed Dred re ed ee Cre Rat cia 0
کدام را بیان کنید.
- «تابع سازنده» را شناخته و وظیفةٌ آن را شرح دهید.
- روشهای گوناگون :
صفحه 466:
مقدمه
2020 رهیافت جدیدی بود که برای
ياره اى از مشكلات برنامه نويسى راه حل
داشت. این مضمون از دنبای فلسفه به جهان
برنامهنویسی آمد وكمى كرد تا معضلات
تولید و پشتیبانی نرمافزار کمتر شود.
اشیا را میتوان با توجه به مشخصات ورفتار
آنها دسته بندی کرد.
صفحه 467:
در بحث شى كرايى به دستهها (eID
میگویند و به نمونههای هر کلاس 00
00
مشخصات هر شى را «صفت؛ مینامند و به
رفتارهاى هر شى «متد؛ 2
صفحه 468:
برنامهنويسى شى كرا بر سه ستون استوار است:
الف. دستهبندى: يعنى اين كه دادههاى
مرتبط. با هم ترکیب شوند و جزییات
پیادهسازی مخفی شود.
Am) وراشت: در دنیای واقعی. ورافت به این
معناست که یک شی وقتی متولد میشود.
خصوصيات و ويزكىهايى را از والد خود به
همراه دارد .
صفحه 469:
امتياز وراثت در اين است كهاز كدهاى
مشترى استفاده مى شود و علاوه بر اين
كه مى توان از كدهاى قبلى استفاده مجدد
Eee رس
استحكام منطقی 0-0 هم 0
ميپابد.
صفحه 470:
ل 2
میگویند به معنای یک چیز بودن و چند
شکل داشتن است. چندریختی بیشتر در
وراثت معنا ييدا مىكند.
صفحه 471:
لدت ۱7۳
كد زير اعلان يك كلاس رأ نشان مى د هذ
موه
:لس )
0 رس(
viod prici();
۳۳۱
ce ۱
اعلان کلاس با chase 5345 aal5 شروع
میشودسیس نام کلاس میاید.
صفحه 472:
35 if
علان اعضا
که کلاس درون نک وی از
بلوى انجام مى شود
ES peer) سمیکولر 71 9 بلوک نشان
مىدهد كه اعلان كلا te 9 بت
ee LO og فته | 2
|
ارت
ریت 2 هر عصوى
5 5 عبارت ۳۲۱/۷ كه
le Ju ت ره ا 1 2
2 0
عمومی»
محسوب میش
Te) 0 عضوى كه 3
ذیل عبارت
2
۱ ۳ 7 DY OD Cl a ANd
> 2 3 ده
خصوصی»
08
شود.
صفحه 473:
سازندهها
وظيفة ee rol است که حافظةً لازم را برای
شىء جديد تخصيص داده و آن را مقداردهى نمايد
و با اجراى وظايفى كه در تابع سازنده منظور شده.
شیء جدید را برای استفاده آماده کند.
هر کلاس Bw PP) چندین سازنده داشته باشد. در
حقیقت تابع سازنده میتواند چندشکلی داشته
۰
صفحه 474:
راز نس را
از یکدیکر تفکیک میشوند. ,رب(
مثال 4-0 افزودن جند تابع سازندةً ديكر به كلاس 47-©)
هت
تاطحم )
casted (PR ل 0ك
(PY ا (RG) كا
cain ال 000 كا
0 0 0
:ادرفم
att 00
7
صفحه 475:
این نسخه از کلاس ۶( ر., سازنده دارد؛
Lee eae ee rau rca
۱ PENS SCTSCUU MI RCTNC)
برد سازنده یک بارامتر از نوع از دارد و
ی اعلان شده را طوری مقداردهی میکند که
حاصل مقدار آن يارامتر برابر باشد.
20 شازتدة نير همان سازندة مثال ۲-۱۶
زر
صفحه 476:
یک کلاس میتواند سازندههای مختلفی داشته
باشد. سادهترین آنهاء سازندهای است که هیچ
بر اسری ندارد + ابر BIS سازئدة يريش فرضص.
38
اكر در يك كلاسء سازندة ييشفرض ذكر
نشود. كاميايلر به طور خودكار كن را براى
كلاس مذكور ايجاد مىكند.
صفحه 477:
فهرست مقداردهی در سازندهها
سازنددها اغلب به غير از مقداردهى دادههاى
ee este ae repos 20
همين دليل در 0++ يك واحد دستورى
مخصوص بيش رببينى شده كه توليد سازنده را
ECP) ee a ROLE RO ced
«قداردهی تن داردد
صفحه 478:
به سومین سازنده در متال ٩-۵ دقت کنید. این سازنده ر
میتوانيم ب) استفاده از فهرست مفداردهی به سكل ركر
خلافه کندم:
o, ct): num(n),den(d) { } ۱02
مثال ٩-۶ استفاده از فهرست مقداردهى در كلاس -1-)
مدا سا
۱
(0(1)-ظ یراس نف
۱ از en sl (OE AY
0 ا ca)
rag aw ot
ach رن با
1
صفحه 479:
توايع دستيابى
دادههای عضو یک کلاس معمولا به صورت
خصوصی (۶,<) اعلان میشوند تا دستیابی به
آنها محدود باشد اما همین اهر باعث میشود
A5 در مواقع لزوه به اين دادهها
دسترسى داشته باشيم. براى حل اين مشكل از
تواتعئ نا عنوان ٠2:0 ٠ب استقادة
میکنيم.
صفحه 480:
تابع دستیابی یک تابع عمومی عضو کلاس است و
به همين دليل اجازةً دسترسى به اعضاى دادهاى
خصوصى را دارد.
با استفاده از توابع دستيابى فقط مى توان اعضاى
دادهای خصوصی را خواند ولی نمیتوان آنها را
دستکاری کر د.
صفحه 481:
مثال ٩-۸ افزودن توابع دستیایی به کلاس ۳؟)
۱
وم
۹ 20, Nap) 9 8
الح
( دصل 99 ۳ 0
صفحه 482:
توابع عضو خصوصی
توابع عضو را گاهی میتوانيم به شکل یک عضو
فصوصى كلاس معرفى كنيم. واضع است كه هنين
تابعى از دافل برنامةً اصلى به هيج عنوان قابل
دستيابى نيست. اين تابع فقط مىتواند توسط ساير
توابع عضو كلاس دستيابى شود. به هنين تابعى يى
اا ل میگوييم.
صفحه 483:
co
در بر
تابع عضو خصوصی به نام ۳۵۱() است.
وظيفة تابع مذكور اين است كه معادل
jroo شناور یک عدد کسری را بر گرداند
مه زير. كلاس 0
a يي
اين تابع فقط درون بدنة تابع عضو
7 )) استفاده شده و به
انجام ol dab كمكدمىنمايد و 1
هیچ نقشی در برنامةً اصلی ندارد. ۱
صفحه 484:
سازندة كبى
۱
در متفیری به نام » از نوع ایجاد میشود.
در هم همین کار انجام میگیرد با این
تفاوت كه يس از ايجاد >< مقدار موجود در متغير >ا كه
از قبل وجود داشته درون *< مىشود. اصطلاحا ><
3 00
صفحه 485:
0۲
كد بالا يك شى به نام باز نوع 0557 ايجاد
Ooo eed كت ا ل SPP
آسن قرار مىدهد. اكر در تعريف كلاس»
سازندةٌ كيى ذكر نشود (مثل همة
etd ل ا ل ات
زره رم دس لت
خواهد شد.
صفحه 486:
مثال ٩-۱۰ افزودن یک سازندهٌ کپی به کلاس ۲
0
اك اك 1
xn), ely xox) اك و0 اق قسن رن
0 ۷ ۶ ۱ ۶
Aan
fot ony, choc
1
در مثال بالاء تابع سازندة کیسی طوری تعریف شده که
سس را رت سر
ل ا
صفحه 487:
سازندة کپی در سه وضعیت فرا خوانده میشود:
See TCI ree eee PCy eal] ل
شود.
1
1 شی به وسیله .:_ ر به یک تابع رال
٠” - وقتى كه يك شى به وسيلة :ار از ز گشت
an شى راز یک تابع .زر <-
صفحه 488:
زابود كننده
{
١ 5
یب نسم ِ رل(
r
وقت که
وقتی 5
یک نابود کننده ۱
.دارد تع |
>
صفحه 489:
مثال ٩-۱۲ افزودن یک نابودکننده به کلاس ۲97)
uss Ratz
رم ۷
.60000 ۱ متسر
0
iy
~Ruto() { cu << "OBJECT O1EG.\a"; }
م۱2
در زر ce
صفحه 490:
اشیای ثابت
اشيا را نيز میتوان با استفاده از
عبارت 772۱ به صورت یک شیء
ثابت اعلان کرد:
vows Ruic PUCS,?);
9.00۴93
۱ of], = wnt GIL);
صفحه 491:
۱
ee eee Te) كر
0 از آنجاکه یک کلاس
ا ا ا ا
داشته باشد.ء اشاره كر به اشيا بسيار
سودمند و مفید است.
7 به ._برای ساختن فهرستهای
ييوندى SEE كار
oy)
صفحه 492:
مثال ٩-۱۳ استفاده از اشاره گر به اشیا
صفحه 493:
pS) ار
pa تسس - ای ز Cleitel (pee) رز مر
آن شى ۳7 Perrone) میکند.
حتماباید هنگام استفاده از آن را درون
py) ((۱
تقدم بالاتری نسبت به عملگر مقداریابی (4)
دارد.
اکر برانتزها قید نشوند و فقط . . ., نوشته
شود کامپایلر این خط رابه صورت ...۰ ا
تفسیر خواهد کرد که اين باعث خطا میشود.
صفحه 494:
تا لس Oe IDE DD EDC ل
نشان میدهد.
مثال ٩-۱۴ فهرستهای پیوندی با استفاده از کلاس اك
Gr اذ
اک
خناتانم 1
data(d), ل 4 200
ا
Reeser
7 20
صفحه 495:
عبارت بالا کلاسی به نام 702() تعریف میکند
که اشیای این کلاس دارای دو عضو دادهای
هستند که یکی متغیری از نوع 1 است و
ديكرى يك اشارهكر از نوع همين كلاس- اين
ل ل ا Papa ACS od
ديكر ييوند دهيم و يك زنجيره بسازيم.
صفحه 496:
اکر اشیای و «و از نوع ع() باشند. میتوانیم
پیوند اين سه شی رابه صورت زير مجسم کنیم:
صفحه 497:
به تابع سازنده نیز دقت کنید که چطور هر دو عضو دادهای شی.-
جدید را مقداردهی میکند.
صفحه 498:
0 ا نامه را نشان میدهد.
شكل زير روند اجراى بر ر دا می | [int data
م
[Node* next]
int data
int data م
لمع | كك
صفحه 499:
اعضای دادهای استا
هر وقت که شیثی از روی یک کلاس ساخته میشود. ن
Oey lr rR EC BL coed
رادارد. كاهى لازم است كه مقدار يك عضو دادهاى در
همة اشيا يكسان باشد. اكر اين عضو مفروض در همة اشيا
ee) ل ا ل FC
pe: Sipe pe agere entrees) 2 ل 0
عنوان يك عضو ايستا اعلان كنيم.
صفحه 500:
۱ meee oe Roe itr ole perry
1۱ Cree ONC ا ل an Papen L etee)
متغیر. میتوانیم آلن متغیر را به صورت ایستا اعلان نماییم. یک متفیر ایستا را فقط
|
یک عضو دادهای ایستا را بیان میکند:
)ا ععواص
) :عناطح
۱ ل eae RR RR Cac cco
صفحه 501:
See a ae eer اه care)
گونه متغیرها 0 tee SS en be mete Te)
Pe ee re ok Mer Be eae ا
داشته باشيد.
eae Re a on PNT
كد زيرء كلاسى به نام اعلرن اعلان مى كند كه اين كلاس يى
عضو دادهای ایستا به نام سس دارد. این عضو تعداد اشیای
اس که موجود هستند را نگه میدارد. هر وقت که یک.
ered ل ا ل ل ل كت
ا ل ا ا لاك
مى شودء از طريق نابود كننده مقدار دحج يكد واحد كاهش
مییابد:
صفحه 502:
۳
) عاطم
OO aa
BO Gee)
تفه بت
1
يي نا
:"ما حاصيلشيد " >> توميب >> " ضبن جمصذا بيه ()" >> انجس
و۲ Oe
| =
4 0 ۳ ۳ LS
صفحه 503:
توجه کنید که چگونه چهار شی-ء اعلب درون بلوک
۱
بلوى خارج مى شودء 7
SOCIO MME aE A ND
يى عضو دادداى ايستا مثل يك متغير معمولى است: فقط
دک نان موه خاس دی دی
صفحه 504:
peer ا
Pe ONS a
9
OO aes
ره
اس { retura cout; }
صفحه 505:
۱۹ fea OD
0ك
0
pout << "Dow there ure" << wn Dideets() << " widgets. la";
0
ا ال ال
}
FNS OE Sa ا لل ا Ae
ما
I OYE wrt he STR ل ل
صفحه 506:
اين برنامه مانند مثال 4-18 كار مىكند با اين تفاوت كه متغير
ایستای سح به شکل یک عضو خصوصی اعلان شده و به
م ا ROU Oa earn كل
بتوانیم درون برنامةٌ اصلی به متغیر #سحسه دسترسی داشته
Steer ed |
مقیل تور کم
QWidget
QWidget~
QnumWidgets
صفحه 507:
WO Cnt atthe
بادقت در مثال قبلى به دو ايراد بر مىخوريم: اول اين كه كرجه
0 متفیر 77:0 یک عضو ایستا ال
1
1
ا ا
ا 00
صفحه 508:
پر
كد زير همان كد مثال قبلى است با اين فرق كه در اين كد. تابع دستيابى كننده نيز به شكل
ايستا اعلان شده است:
يت
public: {
OR etal
یو تساه
ا ما ان
00
اه انز ماد
صفحه 509:
PO teats (De
fat ata)
ات۱ SZ al
Ses
pout >> "Onw there ane" << Didget:taucn() <<" wideets-\0";
SS a i a
0 ل ل
i
NSM a ee RE OO Oc OS ها لس
5 5 5)
Bs -
صفحه 510:
وقتی تابع () به صورت ایستا تعریف شود.
Femi 002
آن نیازی به یک شیء موجود نیست و میتوان با
Ree ER OS Cay م ee
فراخوانی کرد.
صفحه 511:
پایان جلسه نهم
صفحه 512:
9 ۰
رز
دما مود
ارب
جلسه دهم
۷ عملک ها «
صفحه 513:
: آنچه در این جلسه می خوانید
"- توابع دوست
- سربار گذاری عملگر جایگزینی (-)
۷
- سربار گذاری عملگرهای حسابی
Dl aCe Soca PO) Soa 1
- سربارگذاری عملگرهای رابطهای
ا FPS BCI 1 BCe ONT
صفحه 514:
خا ا ل كت
كلاس و نحوة انجام اين كار.
صفحه 515:
هدفهاى رفتارى: انتظار مىرود يس از يايان اين جلسه بتوانيد:
-«سربار گذاری» را تعریف کرده و اهمیت آن را شرح دهید.
با ا
بیان نمایید.
م 15۱۳۱
- نحوةً سربار گذاری عملگر جایگزینی را بیان کنید.
- نحوةّ سربار گذاری عملگرهای حسابی را بیان کنید.
- نحوةٌ سربار كذارى عملكرهاى جايكزينى حسابى را بيان كنيد.
- نحوةٌ سربا ركذارى عملكرهاى رابطهاى را بيان كنيد.
ا 00
صفحه 516:
مش وه
در 0++ مجموعداى از ر»2, .71 مختلف وجود دارد كه براى كارهاى
ee eed Sem nee toe) ا له
ار
هنگامی که کلاسی را تعریف میکنیم. در حقبقت یک نوع جدید را به
۱
۱
اما چون عملگرهای ریاضی زر ۲,۰ -, -) چیزی راجع به اشیای
كلاس جديد نمىدانندء نمى توانند به درستى كار كنند. 0++ براى رفع
اين مشكل جاره انديشيده و امكان سربا ركذارى عملكرها را تدارك ديده
ا ل ا ا ل ل ل ل 4
جدپدی اضافه کنیم تا بتوانند با اشیای کلاس مورد نظر به درستی کار
صفحه 517:
Sa
که (صله) )م سجاصب وا لمحناز
اعضایی از کلاس که به شکل خصوصی . مزر
AO) care Or ee ee eee eae
دستیابیاند و از بیرون کلاس (درون بات
امكان دستر سى به bol نیست. on ۹
اما يك استثنا وجود دارد. 2 ا
که عضو یک كلاس نیست اما اجاژه دارد به اعضاى |
وی ره
>> ۶ >> لز
1
صفحه 518:
۲-سربا رگذاری عملگر جایکزینی(ع):
دربین . . . . . . .عملگر جایگزینی شاید
ل ال ل 211
sea || ل ا ا ا ل 0
مانتدر ازن زر رس زد کر ونر رت ره
عملگر جایگزینی نیز به طور خود کار برای یک
و ابحاد مى شود اما اين تابع 7 میتوانیم كت SS
صربح درون كلاس اعلان نماييم.
صفحه 519:
افزودن عملگر جایگزینی به کلاس:
pres Ce pc eep ety است که شامل سازندةٌ
gee ECR D AS ie Deer) لت
) وه
سس ۲
(Dy 4 420
(Nir (zeacicah Onbeui49
vod operator =(roust Rutin&);
5-5
Ane aace در زر
صفحه 520:
0000 Ce] EEC S OCU) CES
است و فهرست آر گومان 0
آّن ل ل ا ا ا ل منفرد
دارد كه از نوع همان کلاس است که 1 ارجاع ثلبت
Peed ا ل ا الل
Osh a
{ ۳ ae کد فوق اعضای دادهای شی-ء را لل
2 به درون اعضای دادهای شیثی که
مالک فراخوانی این عملگر است. /
GE
صفحه 521:
۲-اساره گر :۲
در . میتوانیم عملگر جایگزینی رابه شکل زنجیرهای مثل
زير به کار ببریم:
07 < « < رر:
اجراى كد بالا از راست به جب صورت مى كيرد.
يعنى ابتدا مقدار (OL PP) 0 مى كيرد و
سيس مقدار درون كيى مىشود و سرانجام
مقدار لا درون 41,5 اا ا 0
جایگزینی که در مثال قبل ذکر شد. نمیتواند به
شکل زنجیرهای به کار رود.
صفحه 522:
od عصاس
اه
tet =); I] teP ok poostrutor اد
aia gt aed اس ماس دا
وم Cee Ta. cme (ek)
vier devloraicas yp here //
سم
نویه
/ ور مت ور
1
Mee RO دا مت a)
ار مار ۳
tan ad
Hae
صفحه 523:
۱۱ ee eee eee ened)
مقداردهى تفاوت داردء هر جند هر دواز عملكر
یکسانی استفاده میکنند. مثلا در كد زير
۵۵ وا وا ۱ :(7 Ratio mes
Ratio y(x); // this is an initialization
8۵0 2 - a // this is an initialization
8316 الا >
۸ < /۱ واعوه طه عا عنط 6۶
پآ
os . جایکزینی عملکر جایگزینی .
ان
صفحه 524:
:سر بل وذليوت سار هاو رعسبو
چهار عملگر حسابی . و - و و ل زبانهای برنامهنویسی وجود دارند و با
kre sre ل ل مل اكت
. « أ آنهاء اشياى ساحت خودمان را در محاسبات
ی و 2 اي
مر
eee ee ARIEL Rees Ae ۱ ی
Tay OTe em] Es nei era a
2 دسر 3
عملگر ضرب براى كلاس 2 به شكل 7
(بر صنه<ا) ,> مها )) “مومه ص2
cyt 1
2 ۳
{
صفحه 525:
|
هب« el کلاس دستيابد. برای رفع این محدودیتها.
تابع سربار گذاری عملگر ضرب را باید به عنوان تابع
دوست كلاس معرفى كنيم. لذا قاالب كلى براى
سربار گذاری عملگر ضرب درون کلاس مفروض آبه
شكل زير است؟
Class T
۱ T operator*(const T&, const
:ء1اطنام
public members //
oleae
Ue ۶ ۹۵
صفحه 526:
| در سرباركذارى عملكرهاى حسابى +و -و /نيزاز
aren | Perc open NFP Cas Fe 1
ae WS EB Dee ele a ی
علامت عملگر مربوطه را قرار دهیم و دستورات بدنة
7
T operator*(cor
T& y)
0
// required operations for z =
st T& x, const
صفحه 527:
مثال ۱۰-۳ سربار گذاری عملگر ضرب برای کلاس :۳؟)
سستات
اس pee eee eer cee re
ee
(0 دس ره د ه)مدمار
)) سمدم )ماه ةر
| eek)
رد
هط
3
Rate opercie” (cost Reto& x, ret Reaio& y)
| ee ee ee
دم
1
لا
لع (مبمار زه )مدر
7
1
صفحه 528:
۵-سربا رگذاری عملگرهای جایگزینی حسابی؛
Oe en eles ا ا eae a
۱ ا ا ا الل
۱
. . حسابی ساده. فقط یک عملوند دارند.. ele Slee GUS yp Le Sloe
سربار گذاری عملگرهای جایگزینی حسابی بر خلاف عملگرهای حسابی. میتواند عضو
۱ eo eee Bl RC Soe tS CB) Sa
CEP ی زر رد
ا 00 5
ee
كه )د D&
فا و۳
31
صفحه 529:
بدنة تابع سربارگذاری به قالب زیر است:
T& Topercia*= (cost T& x)
required 7۳۲ // {
returce “this;
}
استفاده از اشاره گر .. . باعث مىشود كه بتوانيم عملكر2 را
در يك رابطة زنجیرهای به کار ببریم. در چهار عملگر
ا ا ا ال ل 0
بر ا
er amen ya ل
دستورات بدنة تابع را نيز به تناسبء تغيير داد. مثال بعدى نشان
میدهد که ال ا ل OES) Mina 0D) SCD
00
صفحه 530:
کلاس عطلت(1) با عملگر *- سربار گذاری شده
ات
>21 5 774ص
Re ana
ac ane al 2 مجدر
عا محر
صفحه 531:
#-سربار كذارق تملترفاق رابطداقة
شش عملكر رابطهاى در ١ وجود
دارد كه عبار تند از: > وح از ل >=
۳۳
این عملگرها به همان روش عملگرهای
arrce ل سا ۳
ECD) peer میشوند. اما ی
RO Tones”
صفحه 532:
حاصل عبارتی که شامل عملگر رابطهای باشد.
همواره یک مقدار بولین است. یعنی اگر آن عبارت
درست باشد. حاصل 20 است واكر آن عبارت
نادرست wel
جون نوع بولين در حقيقت یک نوع عددى صحيح
است. میتوان به جای 20 مقدار ١ و به جاى
ال Fon nee
بازکشتی را برای توابع سربار گذاری عملگرهای
رابطهای. از نوع . . قرار دادهاند.
صفحه 533:
قالب كلى براى سرباركذارى عملكر رابطهاى -- به شكل زير است:
chase “|
jPriead tot operctor==(cocst T&, coset ۳۵۵ jf
9
مر راز رز
1
صفحه 534:
int operator==(const T& x,const T&
۸
required operations to finding // }
result
۳2۰۱۱24
ee en en ee aa at tear nce)
مى كيرد. ساير عملكرهاى رابطهاى نيز از قالب بالا ييروى
صفحه 535:
ey
5 وسيسب 35 CaO ae) Ci eiey cd
اد SN sel CS ee DD كسر هستند,
7 است که برای Sines
Renee glee بررسى اين تساوى مى توانيم
0 (ى*دا--00) را بررسى كنيم. بدنة
ان = — DPE Nts bp perro
re را بررسی میکند.
a رسمه از
7
0
aD) يي سا مت ی سس
Fee RMA. a Cen) |
i
صفحه 536:
۷-سریارکذااری عملگرهای افزایشی و کاهشی:
عملگر افزایشی ++ و کاهشی -- هر کدام دو شکل
rls
- شکل پیشوندی.
شکل پسوندی.
هر کدام از این حالتها را میتوان سربار گذاری
3S
صفحه 537:
قالب کلی برای سربار گذاری عملگر پیشافزایشی به شکل زیر است
ان جا ع ار اشارة كر "7 (استنادة ره علت هم
eee ad ا ا ۱
باز گشت داده شود. به همین دلیل اشارهگر به
و ۱
۱
صفحه 538:
0 " یک شى از كلاس باشد وعبارت ارزیابی
كرددء مقدار به افزوده مىشوداما جون يك عدد
pee) ا ال ل 2 ل 0 200
دارد. فرض کنید . . . . باشد. حالا داریم:
22 22+7 29
Sa pe 3
صفحه 539:
1
ل 00
اشارهگر . به شیء جاری (مالک فراخوانی) اشاره دارد. کافی است مقدار این اشارهگر
ا ا ل ا ا ل ۷
۱
در عمل جایگزینی, درون قرار میگیرد:
12 arc ed
Par: wee (clo ie) ean
۱9 ACL ie و
۱ سس om eta OME ا
Cae ees ccs ny ld (ec eaL
Fc Rea aS MI Sa
۳ en ane ad
FST ae
1
صفحه 540:
0 0 ل نیز به
ال eee See ay
Te RCD) eae) 0
اينهاء عملگرهای دیگری نیز مثل عملگر
خروجی (<<) , عملگر ورودی (> >).
عملكر انديس (]) و عملكر تبديل نيز وحود
دارند که میتوان آنهارا براى سازكارى
براى كلاسهاى جديد سرباركذارى كرد.
صفحه 541:
پایان جلسه دهم
صفحه 542:
9 ۰
رز
دما مود
ارب
جلسه بازدهم
«تر کیب و ورائت»
صفحه 543:
مقدمه
رس
وراثت
اعضاى حفاظت شد
غلبه كردن بر وراثت
ار
ا ل
peec eye ا
صفحه 544:
کلاسهای پايةٌ انتزاعی
پرسشهای گزینهای
پرسشهای تشریحی
eed شي
5 : ياسخنامة يرسشهاى كزينهاى
استاندارد
استاندارد
صفحه 545:
بيان اهميت تر كيب وورائت در
شى كرايى و جكونكى انجام اين كارها.
انتظار میرود پس از پایان این جلسه بتوانید:
ده( See Peon eke Soe I ۳
صفحه 546:
- «اعضاى حفاظت شدة كلاس» را تعريف كنيد و تفاوت
اين اعضا با اعضاى عمومى و خصوصى كلاس را شرح
5
- نحوةٌ غلبه كردن بر وراثت را شرح دهيد.
- «تابع مجازى» را تعريف كنيد و علت استفاده از توابع
مجازى را بدانيد.
- «چندربختیی را تعریف کنید و ل
چندر بختی بر کلاسها ۳۳
- «کلاس پايةٌ انتزاعی» را تعریف کنید و علت تعریف این
كلاءان افا را ذكز) كنيد:
صفحه 547:
Ree ee Re Were Ret nore رت
كه همه جيز از اول طراحى شود. مى توانيم براى ايجاد
کلاس مورد نظر از ارت TH coy Ge
11211111117
اين باعث صرفهجويى در وقت و استحكام منطق برنامه
د.
صفحه 548:
۱
از یک يا چند کلاس دیگر در داخل تعریف یک
كلاس جديد.
هنكامى كه عضو دادداى كلاس جديد.ء شيئى از
كلاس ديكر باشدء مىكويبم كه اين كلاس جديد
تركين از شاير كلاس هاست.
به تعريف دو كلاس زير نكاه كنيد.
صفحه 549:
کد زیر. کلاس -::() را نشان میدهد که اشياى اين كلاس براى نكهدارى تاريخ استفاده
میشوند.
تایه
W=O, rt S=D) ۱۹
ad a)
Fee Oe ea on)
1: il Sc Cs ie
را ۱0
| ل ل ieee a)
000
et اا ا
privat
۲ Sd
0
صفحه 550:
®ovk pS
Soe) ا ا ا ECS
مشخصات يك كتاب را نكهدارى مى كنند:
chose Book
atc }
:@ovk(cha* a ="") tot i = ©, تمه O)
{} sae(a), (1), poce(r)
vod pricKDawe() { cout << ove; }
void priefld() ) ايلع >> نحم }
rout << pore; } ) ()جوه "ماسم لور
۳۳
دنه سوه موز
proce رل از
صفحه 551:
Cad تا
رام
Oe 0
0S Oma)
Peta One OE Gt eer an
Tad OR OC TE
تعدمم >> نحم On دم صر
(0 يا رج يا ره يب 008 2اميسد لين
00 ل Aa
ane Nel Nets ae eo nora
هه ریت۲
مان
RO و os
۱
صفحه 552:
وراثت روش ديكرى براى ايجاد كلاس جديد از
نيز مى ككويند.
ا ال
صفحه 553:
اعضای حفاظت شده:
۱0 ا Ju Jin p> we Aa ST
خصوصى كلاس والدش دسترسى داشته باشد., اما با استفاده از
توابع عضو عمومى كه از كلاس والد به ارث بردهء مى تواند به
Oe 1 0 ا hoe e ee Cy ol اعضاى خصوصى
كلاس فرزند را براورده نسازندء كلاس فرزند ناكار ا مد مى شود.
اوضاع زمانی وخیمتر میشود که هیچ تابع عمومی برای دسترسی
ا ۱
صفحه 554:
۱ cldlolST th jl wIS aj SI
حفاظت شدهٌ كلاس راارث مىبرند.
مثلا تمامی اشیای تابع دستيابى 00٠١١١ ازكلاس
رابه ارث مىبرند. به تابع ١١١١ يكدهعضوموروثى»
soul
باشیم
يعنى كلاس فرزندء. عضوى هم نام با عضو موروثى داشته باشد كه
مخصوص به خودش باشد و ارثی نباشد. برای مثال فرض كنيد
كلاس يك عضو عمومى به نام داشته باشد و كلاس زير
bb pS
صفحه 555:
در این حالت اشیای کلاس : عضو موروثی 7 را خواهند داشت.
حال اكر يكد عضو به همان نام 7 در زير كلاس ٠“ به شكل
eee) ors Be. ا ا ا RG
مقلوب میکند.
Te IR ele ek Se Rare ee aCe a ane ie
7 شى 801 ا عضو 7 غالب اشاره دارد نه به
0
ا 7
۱۲ به 7 موروثی دستیابی دارد.
صفحه 556:
هم مى توان اعضاى دادهاى موروثى را مغلوب كرد و
يعنى اكر كلاس داراى يك عضو تابعى عمومى به
نام ۴() باشد و در زیرکلاس نیز تابع ۴ را به
Ce eC OB Cord ل 7 TF
اشاره دارد 9 a (001d Ge me تابع موروتى اشاره دارد.
در برخی از مراجع به توابع غالب. . میگویند
۱
كتاب هر دو مفهوم را به عنوان اعضاى غالب به كار
مى بريم. به مثال زير نكاه كنيد.
صفحه 557:
اعضای دادهای و تابعی غالب :
[ تال
۱
ار
تا : ۷۲ عون
[ ارو
) f= Poetic"; }
صفحه 558:
سازندهها و نابودکنندههای والدة
0 :"ا>سحجمت سماصحفصط ()7::02" >> نحط ) 0
Fey
al
۲ ) مه >>
۷ ) وم >>
cee
publ |
BO On ea) eae eee
7 راک مت ۱ ۳ 0
oan
۳
۱
صفحه 559:
اشارهگرها در ورائت :
٠. ©
2 د ود"
در شى كرايى خاصيت جالبى وجود دارد و لن اين است كه اكر « اشارهكرى از نوع كلاس
Ine) ل ا ا ۱
کنید:
که
able
فلت
/
) خان وجواسطد ه IIS? ts عاطم : ث٠ سداد
able |
فلت
0
Od
Ih pte spotter to objets oP base chew X
ua
oP subckes VY ماه او سل موم ار
0
صفحه 560:
5 ۰ شه و Ss
اشارهگری از گلاس والد به شیئی از گلاس فرزند؛
در برنامه زیر کلاس زر کلاسی از است هر دوی این کلاسها
دارای یک عضو تابعی به نام هستند و 7 اشارهگری از نوع :
تعريف شده: نيدت
احج
Pee ean rn eee ca
3
ا
ble |
( 0 ريس
1
1
تخد
Dewi
94
>« <
) عجب ل عم مسا (::۷ لس || ترا
Re
X عرب دكا م «صوجهنا ()*:: لا وجحاهها |/ )8م
{
صفحه 561:
توابع مجازی و چندر یختی :
ا ل ا ا ل
مشخص مىشود. وقتى يى تابع به شكل مجازى
Pes Sg Cs SO CRC ee Pye pee) es
فرزند نيز تابعى با همين نام وجود دارد. توابع
مجازى امكان مىدهند كه هنكام استفاده از
اشارهكرهاء بتوانيم بدون در نظر كرفتن نوع
اشارهكرء به توابع شىء جارى دستيابى كنيم.
مثال زير Pees ss
صفحه 562:
استفاده از توابع مجازى:
ا عصان
pablo: — Orrtud Puarion }
وک ۱۳ سس
ae eG
Cea
0 | ا
صفحه 563:
چندریختی از طریق توابع مجازی ؛
سه کلاس زیر را در نظر بگیرید. بدون استفاده از توابعمجازی, برنامه آن طور
1
اف
۳ eer saree
ناریو ویو
< حجنو إي كوهيم
aces ot tea aa aca بخ"
' 1 ea ‘=
on oe
۳
صفحه 564:
آنابودکنندة مجازی
با توجه به تعريف توابع مجازى. به نظر مىرسد كه نمىتوان توايع
سازنده و نابودكننده رابه شكل مجازى تعريف نمود زيرا سازنددها
BCEY ل ا ا ا 00
CL Deo ا COS BY CES BeBe RSC IN ee
دیگری دارند.
مثال بعدی ایراد مهلکی را نشان میدهد که با مجازی کردن
نابود كر. برطرف مى شود.
صفحه 565:
لح
لي الي
-("ها.0)-" >> ففجم زم [] منطاط ) )0
رو
[7 NER eae
aS
Ohl ie hes dD od
pride
int
000
| ات اس یا
| لسع حم “لاز
از
i
1
1
صفحه 566:
کلاسهای پایة انتزاعی :
در شیگرایی رسم بر این است که ساختار برنامه و کلاسها را طوری طراحی کنند که بتوان.
آنها را به شکل یک نمودار درختی شبیه زیر نشان داد:
بسم الله
الرحمن
الرحيم
دانشگاه
پيام نور
دانشكده فناوري
اطالعات
برنامه سازي پيشرفته
تهيه كننده:
دكتر احمد فراهي
:مقدمه
زبان Cيک زبان همه منظوره است.
دستورالعملهاي اين زبان بسيار شبيه
عبارات جبري و نحو آن شبيه جمالت
انگليسي مي باشد .اين امر سبب
ميشود که Cيک زبان سطح باال
باشد که برنامهنويسي در آن آسان
C++که از نسل Cاست ،تمام ويژگيهاي
Cرا به ارث ب77رده اس77ت .اما برتري ف77ني
ديگري هم دارد ++C :اکن777ون «ش777يگرا»
است .ميت77وان با اس77تفاده از اين خاص77يت،
برنامههاي شيگرا تولي77د نم77ود .برنامههاي
شيگرا منظم و ساختيافتهاند ،قابل روزآمد
کردناند ،به سهولت تغيير و بهبود مييابن77د
و قابليت اطمينان و پايداري بيشتري دارند.
:اهم مطالب اين كتاب
جلسه اول« :مقدمات برنامهنويسي با »++C
جلسه دوم« :انواع اصلي»
»جلسه سوم« :انتخاب
جلسه چهارم‹‹ :تكرار»
»جلسه پنجم« :توابع
جلسه ششم « :آرايهها»
»جلسه هفتم« :اشارهگرها و ارجاعها
جلسه هشتم« :رشتههاي كاراكتري و فايلها در C++استاندارد»
جلسه نهم« :شيئگرايي»
»جلسه دهم« :سربارگذاري عملگرها
جلسه يازدهم« :تركيب و وراثت»
جلسه اول
مقدمات برنامهنويسي با
+
+C
:آنچه در اين جلسه مي خوانيد
-1چرا ++C؟
-2تاريخچۀ ++C
-3آمادهسازي مقدمات
-4شروع کار با ++C
-5عملگر خروجي
-6ليترالها و کاراکترها
-7متغيرها و تعريف آنها
-8مقداردهي اوليه به متغيرها
-9ثابتها
-10عملگر ورودي
هدف کلي:
آشنايي با تاريخچه و مزاياي زبان برنامهنويسي ++Cو
بيان مفاهيم بنيادي شيگرايي و عناصر مهم برنامههاي
++C
:هدفهاي رفتاري
انتظار ميرود پس از پايان اين جلسه بتوانيد:
مزاياي زبان ++Cرا بر زبانهاي مش77777ابه ذکر کرده وتفاوت آن را با زبان Cبيان کنيد.
شرح مختصري از روند پيشرفت زبانهاي برنامهنويسيرا بيان کرده و مش7777کالت هر دوره را ب7777ه اختصار شرح
دهيد.
مزاياي شيگرايي در توليد نرمافزار را برشماريد. اصول سهگانۀ ش 7يگرايي را ن77ام ب77رده و هر ي77ک را ب77هاختصار شرح دهيد.
ق777الب کلي برنامههاي ++Cرا بشناس777يد و بتواني777د برنامههايکوچک را نوشته و آزمايش کنيد.
عملگر ورودي و خروجي را در ++Cش7777777ناخته و از آنها دربرنامهها استفاده کنيد.
نحوۀ اعالن متغيرها و شيوۀ مقداردهي به آنها را بدانيد. سه موجوديت «ليترال»« ،کاراکتر» و «عدد» را شناخته و فرق بينآنها را شرح دهيد.
علت و شيوههاي افزودن توضيح به کد برنامه را شرح دهيد. -علت و شيوۀ معرفي ثابتها در برنامه را شرح دهيد.
مقدمه
در دهه 1970در آزمايشگاههاي بل زباني ب77ه ن77ام Cايجاد
شد .انحصار اين زبان در اختيار شرکت بل بود ت77ا اين ک77ه در
سال 1978توسط Kernighanو Richieشرح کاملي از اين
زبان منتشر شد و به سرعت نظر برنامهنويسان حرفهاي را
جلب نمود.
هنگامي که بحث شيگرايي و مزاياي آن در جهان نرمافزار
رونق يافت ،زبان Cکه قابليت شيگرايي نداش77ت ن77اقص ب77ه
نظر ميرسيد تا اين که در اوايل دهۀ 1980دوباره شرکت
بل دست به ک77ار ش77د و Bjarne Stroustrupزبان ++Cرا
طراحي نمود
++Cترکيبي از دو زبان Cو Simulaب777ود و قابليتهاي
ش77يگرايي ن77يز داش77ت .از آن زمان ب77ه بع77د شرکتهاي
زيادي کامپايلرهايي براي ++Cطراحي کردن7777د .اين امر
سبب شد تفاوتهايي بين نسخههاي مختلف اين زبان ب777ه
وجود بيايد و از قابليت سازگاري و انتقال آن کاسته شود.
به همين دليل در سال 1998زبان ++Cتوس77ط موسس77ۀ
استانداردهاي ملي آمريکا ( )ANSIبه شکل استاندارد و
يکپارچه درآمد.
-1چرا ++C؟
زبان Cيک زبان همه منظوره است
در اين زبان عملگرهايي تعبي77ه ش77ده ک77ه برنامهنويس77ي
سطح پايين و به زبان ماشين را نيز امکانپذير ميسازد
چون Cعملگرهاي فراواني دارد ،ک77د منب77ع برنامهها در
اين زبان بسيار کوتاه است
- زبان Cبراي اجراي بسياري از دسWWتوراتش از توابWWع کتابخWWانهاي
استفاده ميکند و بيشتر خصوصيات وابسته به سWWختافزار را بWWه اين
توابع واگذار مينمايد.
برنامۀ مقصدي که توسط کامپايلرهاي Cساخته ميشود بسيار
فشردهتر و کمحجمتر از برنامههاي مشابه در ساير زبانها است.
++C که از نسل Cاست ،تمام ويژگيهاي جذاب Cرا به ارث
برده است .
و سرانجام آخرين دليل استفاده از ++Cورود به دنياي #Cاست.
-2تاريخچۀ ++C
در دهه 1970در آزمايشگاههاي بل زباني ب777ه ن777ام Cايجاد
شد .انحصار اين زبان در اختيار شرکت بل ب77ود ت77ا اين ک77ه در
سال 1978توسط Kernighanو Richieشرح ک777املي
از اين زبان منتشر ش777777د و ب777777ه سرعت نظر برنامهنويسان
حرفهاي را جلب نمود .هنگامي که بحث ش777يگرايي و مزاياي
آن در جهان نرمافزار رون7777ق يافت ،زبان Cک7777ه ق7777ابليت
شيگرايي نداشت ناقص به نظر ميرسيد ت77ا اين ک77ه در اواي77ل
دهۀ 1980دوباره شرکت بل دست به کار شد و Bjarne
Stroustrupزبان ++Cرا طراحي نمود.
++Cترکيبي از دو زبان Cو Simulaب ود و قابليتهاي
شيگرايي نيز داشت از آن زمان به بعد شرکتهاي زيادي
کامپايلرهايي براي ++Cطراحي کردند .اين امر سبب شد
تفاوتهايي بين نس خههاي مختل ف اين زبان ب ه وج ود
بيايد و از قابليت سازگاري و انتقال آن کاس ته ش ود .ب ه
همين دلي ل در سال 1998زبان ++Cتوس ط موسس ۀ
استانداردهاي ملي آمريکا ( )ANSIبه شکل اس تاندارد
و يکپارچه درآمد .کامپايلرهاي کنوني ب ه اين اس تاندارد
پايبندن د .کت اب حاضر ن يز ب ر مبن اي همين اس تاندارد
نگارش يافته است.
آمادهسازي مقدمات 3-
يک «برنامه» دستورالعملهاي متوالي است ک77ه ميتوان77د
توسط يک رايانه اجرا ش77ود .ب77راي نوش77تن و اج77راي هر
برنامه به يک «ويرايشگر متن» و يک «کامپايلر» احتياج
داريم.
بستۀ ++Visual Cمحصول شرکت ميکروسافت و
بس7777تۀ C++ Builderمحص7777ول شرکت بورلن7777د
نمونههاي جالبي از محيط مجتمع توليد ب777راي زبان ++C
به شمار ميروند.
-4شروع کار با ++C
++C نسبت به حروف «حساس به حالت» است يعني Aو aرا يکي نميداند
مثال :اولين برنامه
اولين برنامهاي که مينويسيم به محض تولد ،به شما سالم ميکند و عبارت " "!Hello, my programmerرا نمايش
ميدهد:
>include <iostream#
)(int main
{ ; "std::cout << "Hello, my programmer!\n
;return 0
}
اولين خط از کد باال يک «راهنماي پيشپردازنده»
است .راهنماي پيشپردازنده شامل اجزاي زير است:
#
که نشان ميدهد اين خ77ط ،ي77ک راهنماي
-1 کاراکتر
پيشپردازن77ده اس77ت .اين ک77اراکتر باي77د در ابت77داي هم77ۀ
خطوط راهنماي پيشپردازنده باشد.
-2 عبارت include
-3 نام يک «فايل کتابخانهاي» که ميان دو عالمت <>
محصور شده است.
خط دوم برنامه نيز بايد در همه برنامههاي ++C
وجود داشته باشد.
اين خط به کامپايلر ميگويد که «بدنۀ اصلي برنامه» از کجا شروع
ميشود .اين خط داراي اجزاي زير است:
– 1عبارت intکه يک نوع عددي در ++Cاست.
– 2عبارت mainکه به آن «تابع اصلي» در ++Cميگويند.
– 3دو پرانتز () که نشان ميدهد عبارت mainيک «تابع» است.
هر برنامه فقط بايد يک تابع )(main
داشته باشد .
.سه خط آخر برنامه« ،بدنۀ اصلي برنامه» را تشکيل ميدهند
دستورات برنامه از خط سوم شروع شده است.
دستور خط سوم با عالمت سميکولن ; پايان يافته است.
توضيح
توضيح ،متني است که به منظور راهنمايي و
درک بهتر به برنامه اضافه ميش ود و ت اثيري
در اجراي برنام ه ن دارد . .کامپايلر توض يحات
برنامه را قبل از اجرا حذف ميکند.
استفاده از توضيح سبب ميش ود ک ه ساير
افراد کد برنامۀ شما را راحتتر درک کنند.
به دو صورت ميتوانيم به برنامههاي ++Cتوضيحات اضافه کنيم:
– 1با استفاده از دو عالمت اسلش : //هر مت ني
که بعد از دو عالمت اسلش بيايد تا پايان همان
سطر يک توضيح تلقي ميشود .
– 2با استفاده از حالت : Cهر مت ني ک ه با
عالمت */شروع شود و با عالمت * /پايان ياب د
يک توضيح تلقي ميشود.
-5عملگر خروجي
عالمت << عملگر خروجي در ++Cن ام دارد (ب ه آن عملگر
درج نيز ميگويند).
يک «عملگر» چيزي است که عملياتي را روي يک يا چند شي
انجام ميدهد .عملگر خروجي ،مقادير موجود در سمت راستش
را به خروجي سمت چپش ميفرستد.
به اين ترتيب دستور
; cout<< 66
مق77دار 66را ب77ه خروجي coutميفرس77تد ک77ه coutمعم77وال ب77ه
صفحهنمايش اشاره دارد .در نتيجه مقدار 66روي صفحه نمايش
درج ميشود.
- 6ليترالها و کاراکترها
يک «ليترال» رشتهاي از حروف ،ارقام يا عاليم چاپي اس ت ک ه
ميان دو عالمت نقل قول " " محصور شده باشد.
يک «کاراکتر» يک حرف ،رقم يا عالمت قابل چاپ اس ت ک ه
ميان دونشانۀ ' ' محصور شده باش د .پس ' 'wو '!' و ' '1هر
کدام يک کاراکتر است.
ب ه تف اوت س ه موج وديت «ع دد» و «ک اراکتر» و «لي ترال
رشتهاي» دقت کنيد 6 :يک عدد است '6' ،يک کاراکتر است و
" "6يک ليترال رشتهاي است.
- 7متغيرها و تعريف آنها:
«متغير» مکاني در حافظه است که چهار مشخص ه دارد:
ن ام ،ن وع ،مق دار ،آدرس .وق تي متغ يري را تعري ف
ميکنيم ،ابتدا با توجه به نوع متغير ،آدرسي از حافظ ه
در نظر گرفت ه ميش ود ،سپس ب ه آن آدرس ي ک ن ام
تعلق ميگيرد.
در ++Cقبل از اين که بتوانيم از متغيري استفاده ک77نيم،
بايد آن را اعالن نماييم.
نحو اعالن يک متغير
type name initializer
عبارت typeن77وع متغ77ير را مش77خص ميکن77د .ن77وع
متغير به کامپايلر اطالع ميده77د ک77ه اين متغ77ير چ77ه
مقاديري ميتواند داشته باشد و چه اعمالي ميت77وان
روي آن انجام داد.
name \ initializer
عبارت nameن ام متغ ير را نش ان ميده د .اين ن ام ح داکثر
ميتواند 31ک اراکتر باش د ،نباي د با ع دد شروع ش ود ،عاليم
رياضي نداشته باشد و همچنين «کلمۀ کليدي» نيز نباشد.
مقداردهي اوليه
عبارت initializerعبارت «مقداردهي اوليه» نام دارد .با استفاده
از اين عبارت ميتوان مقدار اوليهاي در متغير م ورد نظر قرار
داد.
دستور زير تعريف يک متغير صحيح را نشان ميدهد:
;int n = 50
- 8مقداردهي اوليه به متغيرها
در بسياري از م وارد به تر اس ت متغيرها را در همان محلي ک ه اعالن
ميش وند مق داردهي ک نيم .اس تفاده از متغيرهاي مق داردهي نش ده
ممکن است باعث ايجاد دردسرهايي شود.
دردسر متغيرهاي مقداردهي نشده وقتي بزرگتر ميشود که سعي ک نيم
متغير مقداردهي نشده را در يک محاسبه به کار ببريم .مثال اگر xرا ک ه
مقداردهي نشده در عبارت ;y = x + 5ب ه ک ار ب بريم ،حاص ل yغ ير
قابل پيشبيني خواهد بود .براي اجتناب از چنين مشکالتي عاقالنه است
که متغيرها را هميشه هنگام تعريف ،مقداردهي کنيم.
مثال:
;int x=45
;int y=0
-9ثابتها
در بعضي از برنامهها از متغيري استفاده ميکنيم که فقط يک بار الزم اس ت آن را
مقداردهي کنيم و سپس مق دار آن متغ ير در سراسر برنام ه ب دون تغي ير باقي
ميمان د .مثال در ي ک برنام ۀ محاسبات رياض ي ،متغ يري ب ه ن ام PIتعري ف
ميکنيم و آن را با 3.14مقداردهي ميکنيم و ميخواهيم که مقدار اين متغير در
سراسر برنامه ثابت بماند .در چنين حاالتي از «ثابتها» استفاده ميکنيم.
يک ثابت ،يک نوع متغير است که فقط يک بار مقداردهي ميش ود
و سپس تغيير دادن مقدار آن در ادامۀ برنامه ممکن نيست.
تعريف ثابتها مانند تعريف متغيرهاست با اين تفاوت که کلمه
کليدي constبه ابتداي تعريف اضافه ميشود.
:مثال تعريف ثابتها
int main()
{ // defines constants; has no output:
const char BEEP ='\b';
const int MAXINT=2147483647;
const float DEGREE=23.53;
const double
PI=3.14159265358979323846
return 0;
}
برنامه فوق خروجي ندارد:
عملگر ورودي 10 -
براي اين که بتوانيم هنگام اجWWراي برنامWWه مقWWاديري را وارد کWWنيم
از عملگر ورودي >> استفاده ميکنيم.
:استفاده از دستور ورودي به شکل زير است
;cin >> variable
variableنام يک متغير است.
استفاده از عملگر ورودي1 – 10 مثال
دد را دوباره در خروجي777ه و همان ع777اربر گرفت777برنامۀ زير يک عدد از ک
:نمايش ميدهد
int main()
{ // reads an integer from input:
int m;
cout << "Enter a number: ";
cin >> m;
cout << "your number is: " << m << endl;
return 0;
}
Enter a number: 52
your number is: 52
عملگر ورودي نيز مانند عملگر خروجي ب77ه ش77کل جرياني
رفت77ار ميکن77د .يع77ني همان ط77ور ک77ه در عملگر خروجي
ميتوانستيم چند عبارت را با استفاده از چند عملگر <<
به صورت پشت سر هم چاپ کنيم ،در عملگر ورودي ن77يز
ميتوانيم با استفاده از چند عملگر >> چن77د مق77دار را ب77ه
ص77ورت پش77ت سر هم دريافت ک77نيم .مثال با اس77تفاده از
دستور:
;cin >> x >> y >> z
سه مقدار xو yو zبه ترتيب از ورودي دريافت ميش77وند .ب77راي
اين کار بايد بين هر ورودي يک فضاي خالي ( )spaceبگذاري77د و
پس از ت777ايپ کردن هم777ۀ وروديها ،کلي777د enterرا بفش777اريد.
آخرين مثال جلسه ،اين موضوع را بهتر نشان ميدهد.
چند ورودي روي يک خط1 – 11 مثال
دد را77 است با اين تفاوت که سه ع2 – 10 برنامۀ زير مانند مثال
داد را دوباره در خروجي نمايش777777از ورودي گرفته و همان اع
:ميدهد
int main()
{ // reads 3 integers from input:
int q, r, s;
cout << "Enter three numbers: ";
cin >> q >> r >> s;
cout << "your numbers are: << q << ", " << r
<< ", " << s << endl;
return 0; Enter three numbers: 35 70 9
your numbers are: 35, 70, 9
}
پايان جلسه اول
جلسه دوم
«انواع اصلي»
:آنچه در اين جلسه مي خوانيد
-1انواع دادۀ عددي
-2متغير عدد صحيح
-3محاسبات اعداد صحيح
-4عملگرهاي افزايشي و کاهشي
-5عملگرهاي مقدارگذاري مرکب
-6انواع مميز شناور
›››
-7تعريف متغير مميز شناور
- 8شکل علمي مقادير مميز شناور
-9نوع بولين bool
-10نوع کاراکتري char
-11نوع شمارشي enum
-12تبديل نوع ،گسترش نوع
›››
-13برخي از خطاهاي برنامهنويسي
- 14سرريزي عددي
-15خطاي گرد کردن
-16حوزۀ متغيرها
هدف کلي:
هدفهاي رفتاري:
بتوانيد:نها در
کارگيري آ
نحوۀ به
متغييرها و
جلسه
پايان اين
انواع پس از
معرفييرود
انتظار م
هاي C
برنامه ++ص77حيح در ++Cرا ن77ام ببري77د و
ع77ددي
ان77واع
متغيرهايي از اين نوعها را در برنامهها به کار ببريد.
انواع عددي مميز ش77ناور در ++Cرا ن77ام ببري77د ومتغيرهايي از اين نوعها را در برنامهها به کار ببريد.
ن77وع ب77ولين را تعري77ف کرده و متغيرهايي از ايننوع را در برنامهها به کار ببريد.
>>>
نوع شمارشي را شناخته و متغيرهايي از اين ن77وعرا در برنامهها به کار ببريد.
مفاهيم «تبديل نوع» و «گسترش ن77وع» را ش77ناختهو انواع مختلف را به يکديگر تبديل نماييد.
علت خطاهاي «سرريزي ع777ددي» و «گردکردن»را دانسته و بتوانيد محل وقوع آنها را کشف کنيد.
عملگرهاي حسابي و افزايش77777ي و کاهش77777ي ومقدارگذاري مرکب را در برنامهها به کار ببريد.
مقدمه
ما در زندگي روزمره از دادههاي مختلفي اس77تفاده
ميکنيم :اعداد ،تصاوير ،نوشتهها يا حروف الفبا،
ص777777داها ،بوها و . ...با پ777777ردازش اين دادهها
ميتوانيم تصميماتي اتخاذ کنيم ،عکسالعملهايي
نشان دهيم و مسالهاي را ح77ل ک77نيم .رايانهها ن77يز
قرار اس777ت همين ک777ار را انجام دهن777د .يع777ني
دادههايي را بگيرند ،آنها را به شکلي که ما تعيين
ميکنيم پردازش کنند و در نتيجه اطالعات م777ورد
نيازمان را استخراج کنند.
-1انواع دادۀ عددي
در ++Cدو نوع اصلي داده وجود دارد« :ن77وع
صحيح» و «نوع مميز شناور» .همۀ انواع ديگر
از روي اين دو ساخته ميشوند (به شکل زي77ر
دقت کنيد).
انواع اصلي
انواع مميز شناور
انواع صحيح
نوع صحيح
ن77وع ص77حيح ب77راي نگه77داري اع77داد
صحيح (اعداد 0و 1و 2و )...اس77تفاده
ميشود .اين اعداد بيشتر براي شمارش
به کار ميروند و دامنه محدودي دارند.
انواع صحيح
نوع
نوع
boolean
شمارشي
bool
enum
نوع
کاراکتري
نوع
عددي صحيح
short
char
int
long
unsigned
Unsigned
char
short
Unsigned
wchar_t
int
unsigned
نوع مميز شناور ب راي نگه داري اع داد اعش اري اس تفاده ميش ود.
اعداد اعشاري بيشتر ب راي ان دازهگيري دقي ق ب ه ک ار ميرون د و
دامن ۀ بزرگتري دارن د .ي ک ع دد اعش اري مث ل 352/187را
-1
ميت وان ب ه ش کل 7352/18×10يا 87352/1×102يا
52/1873×10يا 2/18735×10-2و يا ...نوشت.
شناور کردن ت7777وان
مميز زياد
انواعکم و
به اين ترتيب با
عدد 10مميز عدد نيز جابهجا ميشود .به
همين دليل اس77ت ک77ه ب77ه اع77داد اعش77اري
float
«اعدادlong
double
doubleگويند.
مميز شناور» مي
متغير عدد صحيح 2-
++Cشش نوع متغير عدد صحيح دارد تف77اوت اين
شش نوع مربوط به ميزان حافظ77ۀ م77ورد اس77تفاده و
مح77دودۀ مق77اديري اس77ت ک77ه هر ک77دام ميتوانن77د
داشته باشند.
اين ميزان حافظۀ مورد استفاده و مح77دودۀ مق77ادير،
بستگي زيادي ب77ه س77ختافزار و همچ77نين سيس77تم
عامل دارد .يعني ممکن است روي يک رايان77ه ،ن77وع
intدو بايت از حافظه را اشغال کند در حالي که روي
رايانهاي از نوع ديگر نوع intبه چهار بايت حافظ7777ه
نياز داشته باشد.
نوع متغيير
حداكثر مقدار قابل حداقل مقدار قابل
پذيرش
پذيرش
short
-32768
32767
unsigned
short
0
65535
وقتي برنامهاي مينويسيد ،توجه داشته باشيد
int
-21474836
21474836
که از نوع صحيح مناسب استفاده کنيد ت77ا هم
48
47
برنامه دچار خطا نشود و هم حافظ77ۀ سيس77تم
unsigned int
0
4294967
295ندهيد.
را هدر
long
-21474836 21474836
48
47
unsigned long
0
4294967
295
- 3محاسبات اعداد صحيح
د اغلب زبانهاي
++Cمانن
برنامهنويس ي ب راي محاسبات از
عملگرهاي جمع ( ، )+تفري ق (، )-
ضرب (*) ،تقسيم ( )/و باقيمانده
( )%استفاده ميکند.
- 4عملگرهاي افزايشي و کاهشي
++Cبراي دستکاري مقدار متغيرهاي صحيح ،دو عملگر
جالب ديگر دارد:
کدام از اين عملگرها دو ش777کل
اما
هر: ++
عملگر
متف77اوت دارن77د :ش77کل «پيش77وندي» و
مقدار يک متغير را يک واحد افزايش ميدهد.
شکل «پسوندي».
عملگر : --
مقدار يک متغير را يک واحد کاهش ميدهد.
در شکل پيشوندي ابتدا متغير ،متناسب
ياب77د دو
ک77اهش مي
افزايش يا
عملگر،
متغير ميآي
عملگر قبل از نام
پيشوندي،
بادر شکل
محاسبات
پس از
برايوندي ،عملگر
متغيرکل پس
مقدار در ش
آنيا . n--
m++
مثل
شود ++m.يا . --n
آيد مثل
ديگر نام متغير
بعد از
استفادهميمي
در شکل پسوندي ابتدا مقدار متغير در
محاسبات ب77ه ک77ار ميرود و پس از آن
مق777دار متغ777ير ي777ک واح777د افزايش يا
کاهش مييابد.
– 5عملگرهاي مقدارگذاري مرکب
++Cعملگرهاي ديگري دارد ک77ه مقدارگ77ذاري در
متغيرها را تسهيل مينمايند .مثال با استفاده از عملگر
=+ميتوانيم هشت واحد به mاضافه ک7777نيم اما با
دستور کوتاهتر;m += 8 :
دستور باال معادل دس777تور ;m = m + 8اس777ت با
اين تفاوت که کوتاهتر است .به عملگر « =+عملگر
مرکب» ميگويند زيرا ترکيبي از عملگرهاي +و =
ميباشد
عملگرهاي مقدارگذاري مرکب 5-
قبال از عملگر = ب راي مقدارگ ذاري در متغيرها
استفاده کرديم ++C .عملگرهاي ديگري دارد که
مقدارگذاري در متغيرها را تسهيل مينمايند.
عملگر مرکب در ++Cعبارتند از:
و *= و =/و =%
=+و =-
نحوۀ عمل اين عملگرها به شکل زير است:
m += 8; → m = m +
;8
;m -= 8; → m = m - 8
;m *= 8; → m = m * 8
;m /= 8; →m = m / 8
;m %= 8; →m = m % 8
– 6انواع مميز شناور
عدد مميز شناور به بيان ساده همان عدد اعشاري است .عددي مثل
123.45يک عدد اعشاري است .براي اين که مق77دار اين ع77دد در
رايانه ذخيره شود ،ابتدا بايد به شکل دودويي تبديل شود:
123.45 = 1111011.01110012
اکنون براي مشخص نمودن محل اعشار در ع777دد ،تمام رقمها را ب777ه
سمت راست مميز منتقل ميکنيم .البته با هر جابجايي مم777يز ،ع777دد
حاصل بايد در تواني از 2ضرب شود:
123.45 = 0.11110110111001× 27
به مقدار « 11110110111001مانتيس ع77دد» و ب77ه 7ک77ه
توان روي دو است« ،نماي عدد» گفته ميشود.
در ++Cسه نوع مميز شناور وجود دارد:
انواع مميز شناور
long double
double
float
داري
نگه
هش راي
بايت ب
هشت
doubleاز
وعdouble
ن نوع
يا
ده
يا
ت
از
long
کند float.از چهار بايت ب راي
استفادهن ميوع
معم وال
عدد
نگه .داري ع دد
راي
ب
بايت
شانزده
يا
دوازده
نگهداري عدد استفاده ميکند
استفاده ميکند.
جدول تخصيص حافظه براي متغيير هاي مميز شناور
تعداد بيت براي ذخيرهسازيِ
عالمت عدد نما
مانتيس
8
11
23
52
1
1
نوع متغير
float 32بيتي
double 64بيتي
– 7تعريف متغير مميز شناور
تعريف متغير مميز شناور مانند تعري77ف متغ77ير
تفاوت ن وع floatبا ن وع doubleدر اين اس ت ک ه
صحيح است .با اين تفاوت ک77ه از کلم77ۀ کلي77دي
ن وع doubleدو براب ر floatاز حافظ ه اس تفاده
floatيا doubleبراي مشخص نمودن نوع متغير
ميکن د .پس ن وع doubleدق تي بس يار بيش تر از
استفاده ميکنيم.
floatدارد .ب ه همين دلي ل محاسبات double
مثال:
وقتگيرتر از محاسبات floatاست.
;float x
;double x,y=0
شکل علمي مقادير مميز شناور 8-
اع77داد مم77يز ش77ناور ب77ه دو ص77ورت در ورودي و خروجي
نشان داده ميشوند :به شکل «ساده» و به شکل «علمي».
ساده 1-
علمي 2-
1.234567×1 12345.67
4
0
مشخص است ک ه ش کل علمي ب راي نش ان
دادن اع داد خيلي کوچ ک و همچ نين اع داد
خيلي بزرگ ،کارآيي بيشتري دارد.
– 9نوع بولين bool
نوع boolيک نوع صحيح اس77ت ک77ه متغيرهاي
اين ن77وع فق77ط ميتوانن77د مق77دار trueيا false
داشته باشند true .به معني درس77ت و falseب77ه
معني نادرست است.
اما اين مقادير در اصل ب77ه ص77ورت 1و 0درون
رايانه ذخيره ميشوند 1 :ب77راي trueو 0ب77راي
.false
-10نوع کاراکتري char
يک کاراکتر يک حرف ،رقم يا نشانه اس77ت ک77ه ي77ک
شمارۀ منحصر به فرد دارد .ب777ه عبارت عاميان777ه ،هر
کلي77دي ک77ه روي ص77فحهکليد خ77ود ميبيني77د ي77ک
کاراکتر را نشان ميدهد.
مثال هر يک از حروف ' 'Aتا ' 'Zو ' 'aت777ا ' 'zو هر
يک از اع77داد ' '0ت77ا ' '9و يا نش77انههاي '~' ت77ا ''+
روي صفحهکليد را يک کاراکتر مينامند.
براي تعريف متغ77يري از ن77وع ک77اراکتر از کلم77ه
کليدي charاستفاده ميکنيم .يک کاراکتر باي77د
درون دو عالمت آپس77تروف (') محص77ور ش77ده
باشد .پس ' 'Aيک کاراکتر اس77ت؛ همچ77نين''8
يک کاراکتر است اما 8يک کاراکتر نيست بلکه
يک عدد صحيح است .
مثال:
;'char c ='A
– 11نوع شمارشي enum
يک نوع شمارشي يک نوع صحيح است ک77ه توس77ط
ک77اربر مش77خص ميش77ود .نح77و تعري77ف ي77ک ن77وع
شمارشي به شکل زير است:
}enum typename{enumerator-list
که enumکلمهاي کليدي است typename ،نام نوع
جدي777د اس777ت ک777ه ک777اربر مش777خص ميکن777د و
enumerator-listمجموعه مقاديري اس77ت ک77ه اين
نوع جديد ميتواند داشته باشد.
به عنوان مثال به تعريف زير دقت کنيد:
}enum Day{SAT,SUN,MON,TUE,WED,THU,FRI
حاال Dayيک نوع جديد است و متغيرهايي که از اين نوع تعريف
MONو
مق SUN7و
SATو
مقادير
جديديکي از
نوعيتوانند
شوند م
مي
7يين
7اديرش را تع7
محدودۀ
Dayو
وقتي
TUEو WEDو THUو FRIرا داشته باشند:
کرديم ،ميت7777وانيم متغيرهايي از اين ن7777وع جدي7777د
;Day day1,day2
بسازيم .در کد باال متغيرهاي day1و day2از ن777وع
;day1 = MON
Dayتعريف شدهاند .آنگاه day1با مقدار MONو
;day2 = THU
day2با مقدار THUمقداردهي شده است.
هر
SUNو
SATو
مق7777ادير
77...گرها
شمارش
دلخ77واهي را ب77ه
7ادير ص77حيح
ميت77وان مق7
چن77دداد:
نسبت
ک77ه ب77ه همين ش77کل ب77ه ک77ار
ميروند اما در رايانه به ش77کل اع77داد
همچنين دو يا چن77د شمارش77گر در ي77ک فهرس77ت
ذخ77777يره
...
و
2
و
1
و
0
ص77777حيح
مقداردهي شوند ،آنگاه
شمارشگرها
بعضي از
اگريفقط
داشته باشند:
مقادير يکساني
توانند
م
enum
Answer
}{NO=0,FALSE=0,YES=1,TRUE=1,OK=1
مق77ادير
استهاند
نش77د
مق77داردهي
شمارش77گرها ک77ه
ساير
ب77ه
ک77ه
همين دليل
شوند .به
مي
متوالي بعدي را خواهند گرفت:
SUN
و
SAT
مق77ادير
از
يک
هر
enum
}Day{SAT=1,SUN,MON,TUE,WED,THU,FRI
و ...يک شمارشگر ميگويند.
enum
=Day{SAT=1,SUN=2,MON=4,TUE=8,WED=16,THU=32,FRI
}64
نح777وۀ انتخ777اب نامشمارش777گرها آزاد اس777ت اما بيش777تر
برنامهنويسان از توافق زير در برنامههايشان استفاده ميکنند:
– 1براي نام ثابتها از حروف ب777زرگ اس777تفاده
شمارشگر بايد معتبر باشد:
نامکنيد
يعني:
اولين حرف از نام نوع شمارشي را با حرف
–2
کلمۀبنويسيد.
-1بزرگ
کليدي نباشد.
حروف کوچک اس77تفاده
ديگر از
عددجاي
در هر
نشود.
شروع
–-23با
کنيد.
-3نشانههاي رياضي نيز نداشته باشد.
آخر اين ک77ه ن77ام شمارش7گرها نباي77د ب7ه عن7وان ن77ام
اس777تفاده
برنام777ه
ديگر
ديگرهمدر
متغيرهاي
هاي مشترک
محدوده
جاهاي در
نام نبايد
شمارشگرهاي
استفادهمثال:
شود.
شوند .براي مثال تعريفهاي زير را در نظر
بگيريد:
}enum Score{A,B,C,D
}enum Score{A,B,C,D
;float B
}enum Group{AB,B,BC
;char c
ن77ام
عن77وان
نباي77د ب77ه
غيرمجازو C
هاي باال B
در تعري
Bدر
شمارش77گر
استرازي77را
ف باال
تعريف
دو
است.در ن77وع
آمده نامها
7را اين
کاروب77رد زي7
ديگر به
متغيرهاي
Group
Score
تعريف
هر دو
شمارشي Scoreبه کار رفته است .
انواع شمارشي براي توليد کد «خود مستند» ب77ه ک77ار
ميروند ،يعني کدي که به راحتي درک ش777ود و نياز
به توضيحات اضافي نداشته باشد.
مثال تعاريف زير خودمستند هستند زيرا ب77ه راح77تي
ن77ام و ن77وع ک77اربرد و مح77دودۀ مقاديرش77ان درک
ميشود:
}enum Color{RED,GREEN,BLUE,BLACK,ORANGE
}enum Time{SECOND,MINUTE,HOUR
}enum Date{DAY,MONTH,YEAR
}enum Language{C,DELPHI,JAVA,PERL
}enum Gender{MALE,FEMALE
– 12تبديل نوع ،گسترش نوع
در محاسباتي که چن77د ن77وع متغ77ير وج77ود دارد،
جواب هميشه به شکل متغ77يري اس77ت ک77ه دقت
باالتري دارد .يعني اگر ي77ک ع77دد ص77حيح را با
يک عدد مم77يز ش77ناور جم77ع ببن77ديم ،پاسخ ب77ه
7ترش
7
گس
7ل
7
عم
اين
7ه
7
ب
7ت
7
اس
شناور
مميز
شکل
براي اين ک77ه مق77دار ي77ک متغ77ير از ن77وع مم77يز
گويند.
ي
م
نوع
شناور را به نوع صحيح تبديل ک777نيم از عبارت
)(intاستفاده ميکنيم به اين عم77ل تب77ديل ن77وع
گفته مي شود
.مثالهاي زير تبديل نوع و گسترش نوع را نشان ميدهند
مثال گسترش نوع
:زيرنوع
تبديل
:يک عدد صحيح را با يک عدد مميز شناور جمع ميکند
مثالبرنامۀ
: تبديل ميکندint را به نوعdouble يک نوع،اين برنامه
int main()
{int //main()
adds an int value with a double value:
{ int
// casts
a double value as an int:
n = 22;
double pv=1234.987;
double
= 3.1415;
n; n;
pint+=
n = int(v);
cout
<< "p = " << p << ", n = " << n << endl;
cout <<0;"v = " << v << ", n = " << n << endl;
return
} return 0;
}
– 13برخي از خطاهاي برنامهنويسي
«خطاي زمان کامپايل»
اين قبيل خطاها ک77ه اغلب خطاهاي نح77وي هس77تند ،
توسط کامپايلر کشف ميشوند و ب77ه راح77تي ميت77وان
آنها را رفع نمود.
«خطاي زمان اجرا»
کش77ف اينگون77ه خطاها ب77ه راح77تي ممکن نيس77ت و
کامپايلر نيز چيزي راج77ع ب77ه آن نميدان77د .ب77رخي از
خطاهاي زمان اجرا سبب ميشوند که برنامه به ط77ور
کامل متوقف شود و از کار بيفتد.
-14سرريزي عددي
ي77ک متغ77ير هر ق77در هم ک77ه گنجايش داش77ته
باشد ،باالخره مق77داري هس77ت ک77ه از گنجايش
آن متغير بيشتر باشد .اگر سعي کنيم در ي77ک
متغير مقداري قرار دهيم ک7777ه از گنجايش آن
متغير فراتر باشد ،متغير «سرريز» ميش777ود،در
چنين حالتي ميگوييم که خط777اي سرريزي رخ
داده است.
مثال 2 – 12سرريزي عدد صحيح
ب ميكند تا سرانجام
ن برنام ه به طور مكرر nرا در 1000ضر
اي
سرريز شود:
)(int main
{
//prints n until
it overflows:
ص77حيح سرريز
ع77دد
وقتي يک
;int n =1000
ي77ک
شود ،عدد سرريز
<< cout
ب77ه = "n
شده<< "
;n << endl
;n *= 1000
// multiplies
منفيn by
مقدار1000
7ده» ميش77ود
«گرداني7
;cout << "n = " << n << endl
7ناور
7
ش
7يز
7
مم
7دد
7
ع
يک
وقتي
اما
;n *= 1000
// multiplies n by 1000
معن77اي
ninfبه
<< cout
<< " = " n
نماد <<
سرريز شودendl; ،
;n *= 1000
multipliesم//يدهد.
1000راbyبه nدست
بينهايت
;cout << " n = " << n << endl
;return 0
}
– 15خطاي گرد کردن
ت ك ه
ي از خطاس 777
ن ن777وع ديگر
ي گرد كرد
خط777ا
ي محاسبه
ي اع777داد حقيق
ي رايانهها رو
ب وق777ت
اغل
ن
ل ع77دد 1/3ممك
ي مث77ا
خ ميدهد .ب77را
ميكنند ،ر
اس7ه7تفاده
ذخير هبراب7
0.333333مقايس77ه
مميز شناور ب77راي
دقيقا
7ري ك
شود
ت
متغير
گاههازصور
تب
«هيچ
اس
نکنيد» زيرا در متغيرهاي مميز شناور خطاي گرد کردن سبب
.
ت
نيس
1/3
ل
معاد
ميشود که پاسخ با آن چه مورد نظر شماست متفاوت باشد.
اين خطا از آنجا ناشي ميش77ود ک77ه اع77دادي مث77ل
1/3مق77دار دقي77ق ندارن77د و رايان77ه نميتوان77د اين
مقدار را پي77دا کن77د ،پس نزديکترين ع77دد قاب77ل
محاسبه را به جاي چنين اعدادي منظور ميکند.
حوزۀ متغيرها – 16
انتخاب نامهاي ن77امفهوم يا ن77اقص سبب ک77اهش
نويس777ي
خطاهاي برنامه
افزايش
برنامه و
خوانايي
مناسبي است
++Cواژه
«بلوک» در
اصطالح
نامناسبراهم
حوزۀ متغ77ير
متغيرهاآندرح77وزۀ
استفاده77هازوس77يلۀ
شود.يت77وان ب
ميکه م
متغ777ير»
«ح777وزه
ش777ود.
خطاهايي مي
سبب
قس77متي از
برنامه،
بلوک
ب777روزنمود .يک
مشخص
عالمتدارد
جفتاجازه
ي77کخاص
متغير
ک77هيک
اس77ت که
اي است
محدوده
درون
برنام77ه
فراخواني شود.
محدود رود
محدوده به کار
در آن
شدهيااست.
کروشه { }
ح77وزۀ ي77ک متغ77ير از مح77ل اعالن آن شروع
ميشود و تا پايان همان بل77وک ادام77ه ميياب77د.
خارج از آن بلوک نميتوان به متغير دسترسي
داشت .همچ77نين قب77ل از اين ک77ه متغ77ير اعالن
شود نميتوان آن را استفاده نمود.
ميتوانيم در يک برنامه ،چند متغير متفاوت با
ي77ک ن77ام داش77ته باش77يم ب77ه شرطي ک77ه در
حوزههاي مشترک نباشند.
پايان جلسه دوم
جلسه سوم
«انتخاب»
:آنچه در اين جلسه مي خوانيد
-1دستور if
-2دستور if..else
-3عملگرهاي مقايسهاي
-4بلوكهاي دستورالعمل
-5شرطهاي مركب
-6ارزيابي ميانبري
›››
-7عبارات منطقي
- 8دستورهاي انتخاب تودرتو
-9ساختار else if
-10دستورالعمل switch
-11عملگر عبارت شرطي
-12كلمات كليدي
رفتاري:
هاي
ف
هد
هدف کلي:
انتظار ميرود پس از پايان اين جلسه بتوانيد:
به7کار
هايهها
ل برنام
7تورالعمدر
شناخته و آن را
دستوران if7را
نحو
ببريد77.يوۀ
7اب و ش
انتخ
7واع دس7
7ناخت
ش7يکرا ش77ناخته و آن را در برنامهها ب77ه ک77ار
if..else
دس77تور
نح77و
بهکارگيري هر
ببريد.
از ساختار else..ifدر تصميمگيريهاي پيچيده استفاده کنيد. نحو دستور switchرا شناخته و خطاي «تلۀ سقوط» را تش77خيصدهيد.
بلوک دستورالعمل را تعريف کنيد. عملگرهاي مقايسهاي و عملگر عبارت شرطي را در دس777توراتشرطي به کار ببريد.
-از شرطهاي مرکب استفاده کرده و ارزيابي ميانبري را شرح دهيد.
« -کلمۀ کليدي» را تعريف کنيد.
>>>
مقدمه
همۀ برنامههايي ک77ه در دو جلس77ه اول بيان ش77د ،ب77ه
شکل ترتيبياجرا ميشوند ،يعني دستورات برنامه به
ترتيب از باال به پايين و هر کدام دقيقا يک بار اج777را
ن جلسه نشان داده ميشود چگون77ه از
ميشوند .در اي
دس777تورالعملهاي انتخ777اب 1جهت انعطافپ777ذيري
بيشتر برنامه استفاده ک77نيم .همچ77نين در اين جلس77ه
انواع صحيح كه در ++Cوجود دارد بيش77تر بررس77ي
ميگردد.
دستور if
دستور ifموجب ميشود برنامه به شکل شرطي اج77را
شود .نحو آن به گونۀ زير است:
;If (condition) statement
Conditionک77ه شرط نامي77ده ميش77ود ي77ك عبارت
صحيح است (عبارتي که با يک مقدار صحيح ب77رآورد
ميشود) و statementميتواند هر فرمان قاب77ل اج77را
باش77د Statement .وق77تي اج77را خواه77د ش77د كه
conditionمقدار غير صفر داشته باشد .دقت كنيد كه
شرط بايد درون پرانتز قرار داده شود.
-2دستور if..else
دستور if..elseموجب ميش77ود بس77ته ب77ه اين ک77ه
شرط درست باشد يا خير ،يكي از دو دستورالعمل
فرعي اجرا گردد .نحو اين دس77تور ب77ه ش77کل زي77ر
conditionهمان شرط مساله است که ي777ك عبارت
است:
statement2
و
statement1
و
باش777د
ي
م
ص777حيح
;if (condition) statement1
غير
شرط،
مقدار
اگر
هستند.
اجرا
قابل
هاي
ن
فرما
;else statement2
صفر باشد statement1 ،اج77را خواه77د ش77د وگرن77ه
statement2اجرا ميشود.
مثال يک آزمون قابليت تقسيم
int main()
{ int n, d;
cout << " Enter two positive integers: ";
cin >> n >> d;
if (n%d) cout << n << " is not divisible by " << d << endl;
else cout << n << " is divisible by " << d << endl;
}
-4عملگرهاي مقايسهاي
در ++Cشش عملگر مقايس 7هاي وج77ود دارد < :و
> و <= و >= و == و != .هر ي777777ک از اين
شش عملگر به شکل زير به کار ميروند:
xکوچکتر از yاست x < y //
xبزرگتر از yاست x > y //
xکوچکتر يا مساوي yاست x <= y //
xبزرگتر يا مساوي yاست x >= y //
xمساوي با yاست x == y //
xمساوي با yنيست x != y //
اينها ميتوانند براي مقايسۀ مق7777دار عبارات با
هر نوع ترتيبي استفاده شوند .عبارت حاصل به
عن77وان يك شرط تفس77ير ميش77ود .مق77دار اين
شرط صفر است اگر شرط نادرست باشد و غير
صفر است اگر شرط درست باشد .براي نمون77ه،
عبارت 5*6<8*7براب7777ر با ص7777فر ارزيابي
ميشود ،ب77ه اين مع77ني كه اين شرط نادرس77ت
است.
متغير عدد صحيح 2-
++Cشش نوع متغير عدد صحيح دارد تف77اوت اين
شش نوع مربوط به ميزان حافظ77ۀ م77ورد اس77تفاده و
مح77دودۀ مق77اديري اس77ت ک77ه هر ک77دام ميتوانن77د
داشته باشند.
اين ميزان حافظۀ مورد استفاده و مح77دودۀ مق77ادير،
بستگي زيادي ب77ه س77ختافزار و همچ77نين سيس77تم
عامل دارد .يعني ممکن است روي يک رايان77ه ،ن77وع
intدو بايت از حافظه را اشغال کند در حالي که روي
رايانهاي از نوع ديگر نوع intبه چهار بايت حافظ7777ه
نياز داشته باشد.
دقت کني777د كه در C++عملگر جايگزيني با
عملگر براب77777ري فرق دارد .عملگر جايگزيني
ي77777ک مساوي تکي " = " اس77777ت ولي عملگر
برابري ،دو مساوي " = = " است.
مثال دس77تور ;x = 33مق77دار 33را در xقرار
ميدهد ولي دستور ;x == 33بررسي ميکن77د
که آيا مقدار xبا 33برابر است يا خير .درک اين
تفاوت اهميت زيادي دارد.
-4بلوكهاي دستورالعمل
زنج7777يرهاي از
ي7777ك بل7777وك دس7777تورالعمل
دستورالعملهاست كه درون براكت {} محص77ور
شده ،مانند :
{ ;int temp=x
;x = y
;y = temp
}
در برنامههاي C++يک بلوک دستورالعمل مانند
يک دستورالعمل تکي است.
دستور)(ifint
مثال :يك بلوك دستورالعمل درون يك main
{ ;int x, y
";
<<77ه:cout
ترتيب
7"Enterه و ب
twoرا گرفت7
7integersحيح
اين برنامه دو ع77دد ص7
آنها را چاپ ميكند;cin >> x >> y:
بزرگتري ،
;if (x > y) { int temp = x
;x = y
;y = temp
} //swap x and y
;cout << x << " <= " << y << endl
}
int main()
{ int n=44;
cout << "n = " << n << endl;
{ int n;
cout << "Enter an integer: ";
cin >> n;
cout << "n = " << n << endl; }
{ cout << " n = " << n << endl; }
{ int n;
cout << "n = " << n << endl; }
cout << "n = " << n << endl; }
– 5شرطهاي مركب
شرطهايي مانند n%dو x>=yميتوانند ب77ه ص77ورت ي77ك
شرط مركب با هم تركيب ش7777وند .اين كار با اس7777تفاده
ازعملگرهاي منطقي && ( )andو || ( )orو ! ()not
ص77ورت ميپ77ذيرد .اين عملگرها ب77ه ش77کل زي77ر تعري77ف
ميشوند:
p && qدرست است اگر و تنها اگر هم pو هم qهر دو درست باشند
p || qنادرست است اگر و تنها اگر هم pو هم qهر دو نادرست باشند
!pدرست است اگر و تنها اگر pنادرست باشد
براي مثال( )n%d || x>=yنادرست است اگر و تنها
اگر n%dبرابر صفر و xكوچكتر از yباشد.
!
سه عملگر منطقي && ( )andو || ( )orو ( )notمعم7777وال با
استفاده از جداول درستي به گونۀ زير بيان ميشوند:
p q P&&q p q P||q P !P
T T T
TT T
T F
T F T
TF F
F T
F T T
FT F
طبق ج77دولهاي ف77وق اگر pدرس77ت و qنادرس77ت
F p&&q
F F
F
p||qF
Fعبارت
نادرس77777ت و
باش77777د ،عبارت
درست است.
-6ارزيابي ميانبري
عملگرهاي && و || ب77ه دو عملون77د نياز دارن77دتا
مقايسه را روي آن دو انجام دهند .جداول درس77تي
نش77ان ميده77د ک77ه p&&qنادرس77ت اس77ت اگر p
استفاده
ديگر ||
حالت&& و
اينكه از
مركب
شرطهاي
نادرست
نيست که
نيازي
باشد .در
درستنميكنن7
بررس77ي
همچنين را
عملوند دوم
كنند
qمي
اس777ت7داگر p
p||q
شود.
بررسي
اينباشد.
باشد وكهدرالزم
مگر اين
حالت هم نيازي نيست که q
درست
بررسي شود .در هر دو حالت گفته شده ،با ارزيابي
عملوند اول به سرعت نتيج77ه معل77وم ميش77ود .اين
كار ارزيابي ميانبري ناميده ميشود.
-7عبارات منطقي
يك عبارت منطقي شرطي است كه يا درست است
يا نادرس777ت .قبال دي777ديم ک777ه عبارات منطقي با
مقادير صحيح ارزيابي ميش77وند .مق77دار ص77فر ب77ه
معناي نادرست و هر مقدار غ77ير ص77فر ب77ه معن77اي
درست است .به عبارات منطقي «عبارات بولي» هم
ميگويند.
چ77ون هم77ۀ مق77ادير ص77حيح ناص77فر ب77ه معن77اي
درست تفسير ميش777وند ،عبارات منطقي اغلب
تغيير قيافه ميدهند .براي مثال دستور
;"if (n) cout << "n is not zero
وقتي nغير صفر اس777ت عبارت n is not zeroرا
چاپ ميكن777د زي777را عبارت منطقي ( )nوق777تي
مقدار nغير صفر است به عنوان درست تفسير
ميگردد.
کد زير را نگاه کنيد:
;"if (n%d) cout << "n is not a multiple of d
دستور خروجي فق77ط وق77تي كه n%dناص77فر
اس77ت اج77را ميگردد و n%dوق77تي ناص77فر
اس77ت ک77ه nب77ر dبخشپ77ذير نباش77د .گ77اهي
ممکن است فراموش کنيم که عبارات منطقي
مقادير صحيح دارن77د و اين فراموش77ي باعث
ايجاد نتايج غير منتظره و نامتعارف شود.
يك خطاي منطقي ديگر ،اين برنامه خطادار است:
)(int main
;{ int n1, n2, n3
;" cout << "Enter three integers:
;cin >> n1 >> n2 >> n3
;if (n1 >= n2 >= n3) cout << "max = " << n1
}
منشأ خطا در برنامۀ باال اين اصل است كه عبارات
منطقي مقدارهاي عددي دارند.
دستورهاي انتخاب تودرتو 8-
دس7777تورهاي انتخ7777اب ميتوانن7777د مانن7777د
دستورالعملهاي مركب به كار رون77د .ب77ه اين
صورت که يك دستور انتخاب ميتوان77د درون
دستور انتخ77اب ديگر اس77تفاده ش77ود .ب77ه اين
روش ،جمالت تودرتو ميگويند.
مثال 3-12دستورهاي انتخاب تودرتو
اين برنامه همان اثر مثال 3-10را دارد:
)(int main
;{ int n, d
;" cout << "Enter two positive integers:
;cin >> n >> d
وقتي دستور if..elseبه شکل تو در تو به کار
)if (d != 0
تجزي77ه
ميرود ،كامپايلر از قانون زير جهت
;if (n%d = = 0) cout << d << " divides " << n << endl
كند:
else
ي cout
استفادهdم<<
مركب << " does
دستورالعمل" not divide
اين ;<< n << endl
شودelse cout ».
<< << d
does not
<<elseبا " << n
« هر;endl
جفت"مي
divideتنها
آخرين if
}
در برنام777ۀ باال ،دس777تور if..elseدوم درون دس777تور
if..elseاول قرار گرفته است.
-9ساختار else if
دس77تور if..elseتودرت77و ،اغلب ب77راي بررس77ي
مجموعهاي از حالتهاي متن77اوب يا م77وازي ب77ه
كار ميرود .در اين حاالت فق777ط عبارت else
شامل دس77تور ifبع77دي خواه77د ب77ود .اين قبي77ل
کدها را معموال با ساختار else ifميسازند.
براي مشخص کردن محدودۀ نمرهelse if استفاده از ساختار
:برنامۀ زير يك نمرۀ امتحان را به درجۀ حرفي معادل تبديل ميكند
int main()
{ int score;
cout << "Enter your test score: "; cin >> score;
if (score > 100) cout << "Error: that score is out of range.";
else if (score >= 90) cout << "Your grade is an A." << endl;
else if (score >= 80) cout << "Your grade is a B." << endl;
else if (score >= 70) cout << "Your grade is a C." << endl;
else if (score >= 60) cout << "Your grade is a D." << endl;
else if (score >= 0) cout << "Your grade is an F." << endl;
else cout << "Error: that score is out of range.";
}
switch دستورالعمل-10
برايelse if ميتواند به جاي ساختارswitch دستور
وازي77اوب و م77بررسي مجموعهاي از حالتهاي متن
: به شکل زير استswitch نحو دستور.به كار رود
switch (expression)
{ case constant1: statementlist1;
case constant2: statementlist2;
case constant3: statementlist3;
:
:
case constantN: statementlistN;
اين دستور ابتدا expressionرا برآورد ميكن77د
و سپس ميان ثابتهاي caseبه دنبال مق77دار آن
ميگردد .اگر مق777دار مربوط777ه از ميان ثابتهاي
عبارت defaultيک عبارت اختياري اس77ت .يع77ني
statementlist
دس77تور
ش77د،
يافت
ش77ده
ت
فهرس
ميت77وانيم در دس77تور switchآن را قي77د نک77نيم.
م77ورد
مق77دار
اگر
ش77ود.
ي
م
اجرا
case
آن
مقابل
expressionبايد به شکل يك نوع صحيح ارزيابي
default
عبارت
ميان case
نظر
باشند.
نش7777د وصحيح
ثابتهاي
يافت
constantهاها بايد
شود و
وجود داشت ،دستور statementlistمقابل آن اجرا
ميشود.
الزم است در انتهاي هر caseدس7777تور break
قرار بگيرد .بدون اين دستور ،اج77راي برنام77ه
پس از اين كه caseمربوطه را اج777را کرد از
دس77تور switchخ77ارج نميش77ود ،بلک77ه هم77ۀ
caseهاي زيرين را هم خط به خط ميپيماي77د
و دستورات مقابل آنها را اج77را ميکن77د .ب77ه
اين اتفاق ،تلۀ سقوط ميگويند.
;case constant1: statementlist1;break
-11عملگر عبارت شرطي
در اين عملگر ابت77777دا شرط conditionبررس77777ي
اس77ت
يکي
عبارت
عملگر
امکاناتي7ل ک77ل
7ت باز77ود ،حاص7
شرطيدرس7
اين شرط
شود .اگر
مي
دي77ده
کدنويسييتدارک
اختصار در
جهت
که
ش7777ود و اگر
expression1م
براب7777ر با
عبارت
براب77ر با
ک77ل عبارت
اينبود،
نادرست
جاي
ت77وانيم ب77ه
حاص77لرا مي
عملگر
شرطاست.
شده
بهشود.
if..elseمي
expression2
کار ب777بريم .اين عملگر از
دستور
نشانههاي ? و :به شکل زير استفاده ميكند:
;condition ? expression1 : expression2
مثال در دستور انتساب زير:
;) min = ( x<y ? x : y
اگر x<yباشد مقدار xرا درون minقرار
ميدهد و اگر x<yنباشد مق77دار yرا درون
minقرار ميدهد .يعني به همين سادگي و
اختصار ،مق77دار کمين77ۀ xو yدرون متغ77ير
minقرار ميگيرد.
-12كلمات كليدي
اکنون با کلماتي مث77ل ifو caseو floatآش77نا
ش77ديم .دانس77تيم ک77ه اين کلمات ب77راي ++C
زبان
ي77777ك
در
كلي77777دي
كلم77777ۀ
ك
ي
معاني خاصي دارند .از اين کلمات نميتوان به
منظ777وراز قب77ل
هر77ت كه
اييا اس
يک7ي كلمه
نويس7
برنام
ديگري
متغ777ير
عنوانهنام
7ار
مشخص7ک7
انجام همان
فقط ب7بايد
کرد7و
7ي
براي7دف
7راي ه7
7ده و
استفاده7ف ش
تعري7
شوند .مثال کلمۀ floatفقط باي77د
خاص
استفادهاست.
منظور شده
براي معرفي يک نوع اعشاري به کار رود.
andكلمۀ كليديand_eq
asm ++C
:است
74 استاندارد اكنون شامل
auto
bool
catch
compl
continue
dodouble
enum
extern
for
bitand
break
char
const
default
dynamic_cast
explicit
dfalse
friend
Bitor
case
class
const_cast
delete
else
export
float
goto
if
long
new
operator
privat
register
short
static
swich
throw
inline
mutable
not
or
eprotected
reinterpret_cast
signed
static_cast
template
TRUE
int
namespace
not_eq
or_eq
public
return
sizeof
struct
this
try
typedef
typoid
typename
using
union
unsigned
virtual
void
volatile
wchar_t
while
xor
xor_eq
دو نوع كلمۀ كليدي وجود دارد:
-1كلمههاي رزرو شده
-2شناسههاي استاندارد.
يك كلمۀ رزرو شده كلمهاي اس77ت ک77ه ي77ک دس77تور
خاص از آن زبان را نشان ميدهد .كلمۀ كلي77دي ifو
elseكلمات رزرو شده هستند.
يك شناسۀ استاندارد كلمهاي است كه يك ن77وع دادۀ
استاندارد از زبان را مشخص ميكند .كلمات كلي77دي
boolو intشناسههاي استاندارد هستند
پايان جلسه سوم
جلسه چهارم
«تكرار»
:آنچه در اين جلسه مي خوانيد
-1دستور while
-2خاتمه دادن به يك حلقه
-3دستور do..while
-4دستور for
-5دستور break
-6دستور continue
-7دستور goto
-8توليد اعداد شبه تصادفي
رفتاري:
هاي
ف
هد
هدف کلي:
انتظار ميرود پس از مطالعۀ اين جلسه بتوانيد:
حلقه استفاده
براي ايجاد
شناخته و از آن
ش777ناخت whileرا
نحو دستورکنيد.ها و
نح777و آن
تکرار و
ساختارهاي
ان777واع
يکديگر.شناخته و تفاوت آن با دس77تور
do..whileرا
دستور
نحوها به
تبديل آن
whileرا بيان کنيد.
نحو دستور forرا شناخته و با استفاده از آن حلقههايگوناگون بسازيد.
حلقههاي فوق را به يکديگر تبديل کنيد. علت استفاده از «دستورات پرش» را ذکر کرده و تفاوتسه دستور breakو continueو gotoرا بيان کنيد.
اهميت اعداد تصادفي را بيان کرده و نحوۀ توليد «اع77دادشبه تصادفي» را بدانيد.
مقدمه
تكرار ،اج77راي پي در پي ي77ك دس77تور يا بل77وكي از
دستورالعملها در ي77ك برنام77ه اس77ت .با اس77تفاده از
تکرار ميتوانيم کنترل برنامه را مجب77ور ک77نيم ت77ا ب77ه
خطوط قبلي برگردد و آنها را دوباره اجرا نمايد.
++Cداراي سه دستور تكرار اس77ت :دس77تور ،while
دستور do_whileو دستور .forدس777تورهاي تکرار
حلقه ن77يز نامي77ده
ب77ه علت طبيعت چرخهمانندش77ان ،
ميشوند.
-1دستور while
نحو دستور whileبه شکل زير است:
;while (condition) statement
به جاي ،conditionي777ك شرط قرار ميگ777يرد و ب777ه جاي
statementدستوري که بايد تکرار ش777ود قرار ميگ777يرد.
اگر مقدار شرط ،صفر(يع77ني نادرس77ت) باش77دstatement ،
ناديده گرفت77ه ميش77ود و برنام77ه ب77ه اولين دس77تور بع77د از
whileپرش ميكند .اگر مقدار شرط ناصفر(يعني درست)
باشد statement ،اجراشده و دوباره مقدار شرط بررس777ي
ميشود .اين تکرار آن قدر ادامه مييابد تا اين ک77ه مق77دار
شرط صفر شود.
while محاسبۀ حاصل جمع اعداد صحيح متوالي با حلقۀ4-1 مثال
: محاسبه ميكندn را براي عدد وروديn + … + 3 + 2 + 1 اين برنامه مقدار
int main()
{ int n, i=1;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
while (i <= n)
sum += i++;
cout << "The sum of the first " << n << " integers is "
<< sum;
}
-2خاتمه دادن به يك حلقه
)(int main
;i=1كن7
قبال ديديم كه چگونه دستور breakب77راي
7ترل{
int n,
cout
دس77تورالعمل ;"
7ال
<< مث7
("Enterب77ه
positiveم aيش77ود
77integer:تفاده
switchاس
;cin >> n
پايان
ب77راي
break
دس77تور
از
كنيد).
نگاه
4
17
break
دس77777تور
هاي
ت
مزي
ز
يكي ا
;long sum=0
ميخاتم7
نيز7ه را
هاحلق7
7ورا
دادن7تبهكه ف
اين اس7
توان7هاستفاده کرد.
حلق7ه
)while (true
ميده7777د ب7777دون اين ک7777ه مابقي ;{ if (i > n) break
;sum += i++
دستورهاي درون حلقه اجرا شوند.
}
;cout << "The sum of the first " << n << " integers is " << sum
}
ل 4-4اعداد فيبوناچي
* مثا
اعداد فيبون77اچي … ,F0, F1, F2, F3ب77ه ش77کل بازگش77تي توس77ط
معادلههاي زير تعريف ميشوند:
Fn = Fn-1 +
مثال براي n=2داريم:
,
F1 = 1
,
F0 = 0
Fn-2
F2 = F2-1 + F2-2 = F1 + F0 = 0 + 1
=1
يا براي n=3داريم:
F3 = F3-1 + F3-2 = F2 + F1 = 1 + 1
=2
و براي n=4داريم:
F4 = F4-1 + F4-2 = F3 + F2 = 2 + 1
=3
همۀ اعداد فيبوناچي را تا يك محدودۀ مش خص ک ه از ورودي،برنامۀ زير
: محاسبه و چاپ ميكند،دريافت ميشود
int main()
{ long bound;
cout << "Enter a positive integer: ";
cin >> bound;
cout << "Fibonacci numbers < " << bound << ":\n0, 1";
}
long f0=0, f1=1;
while (true)
{ long f2 = f0 + f1;
if (f2 > bound) break;
cout << ", " << f2;
f0 = f1;
f1 = f2;}
Enter a positive integer: 1000
Fibonacci numbers < 1000:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610,
مثال 4-5استفاده از تابع )exit(0
تابع ) exit(0روش ديگري براي خاتمه دادن به يك حلقه است .هرچند که اين تابع
بالفاصله اجراي کل برنامه را پايان ميدهد:
)(int main
;{ long bound
;" cout << "Enter a positive integer:
;cin >> bound
;"cout << "Fibonacci numbers < " << bound << ":\n0, 1
برنامهنويسان ترجيح ميدهن77د
از breakبراي خاتم77ه دادن ب77ه
حلقههاي نامتناهي استفاده کنند
زيرا ق77ابليت انعط77اف بيش77تري
دارد.
;long f0=0, f1=1
)while (true
;{ long f2 = f0 + f1
;)if (f2 > bound) exit(0
;cout << ", " << f2
;f0 = f1
} ;f1 = f2
}
متوقف کردن يك حلقۀ نامتناهي :
با فشردن کلي77دهاي Ctrl+Cسيس77تم عام77ل ي77ک
برنامه را به اجبار خاتمه ميدهد .كليد Ctrlرا پايين
نگه داشته و كليد Cروي صفحهكليد خود را فش77ار
دهيد تا برنامۀ فعلي خاتمه پيدا کند.
-3دستور do..while
ساختار do..whileروش ديگري براي ساختن حلق77ه اس77ت .نح77و آن ب77ه
صورت زير است:
;)do statement while (condition
به جاي conditionي77ك شرط قرار ميگ77يرد و ب77ه
statementرا اج77را ميكن77د و
اين دستور ابت77دا
7يرد ک77ه
قرار ميگ
conditionيارابلوکي
statementدستور
جايسپس شرط
كن777د7.اگر
بررسي مي
شود.
حلقه دوباره تکرار ميش7777ود
تکراربود
استدرست
قرارشرط
وگرنه حلقه پايان مييابد.
دستور do..whileمانند دستور whileاس77ت.
با اين فرق كه شرط کنترل حلقه به جاي اين
انتهاي
گردد ،در
اينارزيابي
حلقه
ابتداي
که در
حلق7777ۀ
اس7777ت كه
ديگر
نتيج7777ۀ
do..whileمي
حلقه ارزيابي
شود.بدون توجه ب77ه مق77دار
هميشه
شرط كنترل ،الاقل يك بار اج77را ميش77ود
نشود.قب77ل
اين كه
جاي
به
كنترلي
متغير
هر
يعني
اما حلقۀ whileميتواند اصال اجرا
از شروع حلق77ه تنظيم ش77ود ،ميتوان77د درون
آن تنظيم گردد.
do..while
محاسبۀ حاصل جمع اعداد صحيحمتوالي با حلقۀ4-7 مثال
: را دارد5-1 اين برنامه همان تأثير مثال
int main()
{ int n, i=0;
cout << "Enter a positive integer: ";
cin >> n;
long sum=0;
do
sum += i++;
while (i <= n);
cout << "The sum of the first " << n << " integers is " << sum;
}
* مثال 4-8اعداد فاكتوريال
اعداد فاكتوريال !0و !1و !2و !3و … با اس77تفاده از رابطههاي بازگش77تي
زير تعريف ميشوند:
!)n! = n(n-1
براي مثال ،به ازاي n = 1در معادلۀ دوم داريم:
,
0! = 1
1! = 1((1-1)!) = 1(0!) = 1(1) = 1
همچنين براي n = 2داريم:
2! = 2((2-1)!) = 2(1!) = 2(1) = 2
و به ازاي n = 3داريم:
3! = 3((3-1)!) = 3(2!) = 3(2) = 6
چاپ،برنامۀ زير هم ۀ اعداد فاكتوريال را که از عدد داده شده کوچکترند
:ميکند
)(int main
;long bound {
;" :cout << "Enter a positive integer
;cin >> bound
;"cout << "Factorial numbers < " << bound << ":\n1
;long f=1, i=1
do
;cout << ", " << f {
;f *= ++i
}
;while (f < bound)
}
- 4دستور for
نحو دستورالعمل forبه صورت زير است:
;for (initialization; condition; update) statement
سه قسمت داخل پرانتز ،حلقه را کنترل ميکنند.
7ترل
7
کن
7ير
7
متغ
7ردن
7
ب
ش
پي
براي
update
عبارت
حلق77ه
اين ک77ه آيا
تع77يين
براي
عبارتcondition
عبارت
مقداردهي اوليه
اعالن يا
براي
initialization
اج777راي
از
پس
عبارت
اين
رود.
ي
م
کار
به
حلقه
عبارت
شود.اين
ي
م
استفاده
حلقه
کنترل
متغير
به تکرار شود يا خير به ک77ار ميرود .يع77ني اين
بايد
گردد.
ي
م
ارزيابي
statement
از
پيش
ش77ود
ي
م
ارزيابي
ک77ه
است
عبارتي
اولين
عبارت ،شرط کنترل حلقه اس7777ت .اگر اين شرط
تکرارها برسد.
نوبت به
اين
statementاجرا ميشود.
دستور
درستکهباشد
بنابراين زنجيرۀ وقايعي که تکرار را ايجاد ميکنند
عبارتند از:
– 1ارزيابي عبارت initialization
– 2بررسي شرط . conditionاگر نادرست باش77د،
حلقه خاتمه مييابد.
هايstatement
اجراي
–3
و
initializationو condition
عبارت
هايupdate
عبارت
ارزيابي
–4
اختياري هس7777تند .يع7777ني
عبارت
update
درتا 4
هاي 2
5م–
حلقه ذکر نکنيم.
تکرار آگانمها را
يتوانيم
مثال 4-9استفاده از حلقۀ forبراي محاسبۀ مجموع اعداد صحيح متوالي
اين برنامه همان تأثير مثال 5-1را دارد:
)(int main
;{ int n
;" cout << "Enter a positive integer:
;cin >> n
;long sum=0
)for (int i=1; i <= n; i++
در ++Cاستاندارد وق77تي ي77ك متغ77ير كن77ترل درون ي77ك حلق77ۀ forاعالن
حلق77ۀ=+
ميشود (مانند iدر مثال باال) حوزۀ آن متغ77ير ب77ه همان ;I
7sumدود
forمح7
شودcout <<.
استفاده"The
حلقه sum of
the first
تواند " << n
integers
متغير" is
;<< sum
<< "آن
بيرون از
نمي
ميگردد .يعني آن
}
نتيجۀ ديگر اين است که ميت77وان از ن77ام مش77ابهي در خ77ارج از حلق77ۀ for
براي يك متغير ديگر استفاده نمود.
مثال 4-12يك حلقۀ forنزولي
ر ده عدد صحيح مثبت را به ترتيب نزولي چاپ ميكند:
برنامۀ زي
)(int main
){ for (int i=10; i > 0; i--
;cout << " " << i
}
مثال 4-15بيشتر از يك متغير كنترل در حلقۀ for
حلقۀ forدر برنامۀ زير دو متغير كنترل دارد:
)(int main
){ for (int m=95, n=11, m%n > 0; m -= 3, n++
;cout << m << "%" << n << " = " << m%n << endl
}
تودرتوfor حلقههاي4-16 مثال
:برنامۀ زير يك جدول ضرب چاپ ميكند
#include <iomanip>
#include <iostream>
int main()
{ for (int x=1; x <= 10; x++)
{ for (int y=1; y <= 10; y++)
cout << setw(4) << x*y;
cout << endl;
}
}
-5دستور break
درون
break
دس777777تور
وق777777تي
دس77تور breakي77ک دس77تور آشناس77ت .قبال از آن
فقط
شود،
استفاده
تودرتو
هاي
ه
حلق
ب77راي خاتم77ه دادن ب77ه دس77تور switchو همچ77نين
آن
درون
7تقيما
7
مس
که
اي
ه
حلق
روي
حلقههاي whileو do..whileاستفاده کردهايم .از
گذارد.
ي
م
تاثير
گرفته
قرار
اين دس77تور ب77راي خاتم77ه دادن ب77ه حلق77ۀ forن77يز
بيروني بدون هيچ تغييري
هاي
ه
حلق
ميتوانيم استفاده کنيم.
ادامه مييابند.
دس77777تور breakدر هر جايي درون حلق77777ه
ميتواند جا بگيرد و در همان جا حلقه را خاتمه
دهد.
-6دستور continue
دس77تور breakبقي77ۀ دس77تورهاي درون بل77وك
حلقه را ناديده گرفته و به اوليندستور ب77يرون
حلقه پرش ميكند .دستور continueنيز شبيه
همين است اما به جاي اين ک77ه حلق77ه را خاتم77ه
فعلي
چرخۀ
ادامۀ
دستور،
اين
ده77د ،اج77را را ب77ه تكرار بع77دي حلق77ه منتق77ل
را لغو کرده و اجراي دور بعدي
كند.
ي
م
ميکند.
حلقه را آغاز
continue وbreak استفاده از دستورهاي4-19 مثال
: را شرح ميدهدcontinue وbreak دستورهاي،اين برنامۀ كوچك
int main()
{ int n = 1;
char c;
for( ; ;n++ )
{ cout << "\nLoop no: " << n << endl;
cout << "Continue? <y|n> ";
cin >> c;
if (c = = 'y') continue;
break;
}
cout << "\nTotal of loops: " << n;
}
-7دستور goto
دس77تور gotoن77وع ديگري از دس77تورهاي پ77رش
اس77ت .مقص77د اين پ77رش توس77ط ي77ك برچسب
معين ميشود.
برچسب شناسهاي اس77ت كه جل77وي آن عالمت
كولن( ) :ميآيد و جلوي يك دستور ديگر قرار
ميگيرد.
يک مزيت دستور gotoاين است که با اس777تفاده
از آن ميتوان از هم77ۀ حلقههاي تودرت77و خ77ارج
شد و به مکان دلخواهي در برنامه پرش نمود.
براي خارج شدن از حلقههاي تودرتوgoto استفاده از دستور4-20 مثال
int main()
{ const int N=5;
for (int i=0; i<N; i++)
{ for (int j=0; j<N; j++)
{ for (int k=0; k<N; k++)
if (i+j+k>N) goto esc;
else cout << i+j+k << " ";
cout << "* ";
}
esc: cout << "." << endl;
}
}
-8توليد اعداد شبه تصادفي
يكي از كاربردهاي بس7777777777777يار مهم رايانهها،
«شبيهسازي » سيس7777تمهاي دنياي واقعي اس7777ت.
تحقيق77ات و توس77عههاي بس77يار پيشرفته ب77ه اين
راهکار خيلي وابسته است .به وس777يلۀ شبيهسازي
ميتوانيم رفت77ار سيس77تمهاي مختل77ف را مطالع77ه
ک77نيم ب77دون اين ک77ه الزم باش77د واقعا آنها را
پيادهسازي نماييم .در شبيهسازي نياز اس77777777ت
«اعداد تصادفي» توس77ط رايانهها تولي77د ش77ود ت77ا
نادانستههاي دنياي واقعي مدلسازي شود.
رايانهها «ثابتکار» هس777تند يع777ني با دادن دادههاي
مشابه به رايانههاي مشابه ،هميشه خروجي يکسان
توليد ميشود .با وجود اين ميت77وان اع77دادي تولي77د
کرد که به ظاهر تصادفي هستند؛ اعدادي که به طور
يکنواخت در يک محدودۀ خاص گستردهاند و براي
هيچک77دام الگ77وي مشخص77ي وج77ود ن77دارد .چ77نين
اعدادي را «اعداد شبهتصادفي» ميناميم.
مثال 4-22توليد اعداد شبه تصادفي
اين برنامه از تابع )(randبراي توليد اعداد شبهتصادفي استفاده ميكند:
and
)(rand
the
#include<cstdlib>//defines
RAND_MAX
>#include <iostream
)(int main
{ // prints pseudo-random numbers:
)for (int i = 0; i < 8; i++
;cout << rand() << endl
;cout << "RAND_MAX = " << RAND_MAX << endl
هر بار ک77ه برنام77ۀ باال اج77را ش77ود ،رايان77ه هش77ت ع77دد ص77حيح
ت در فاص77لۀ 0ت77ا
unsignedتولي77د ميکن77د ک77ه ب77ه ط77ور يکن77واخ
RAND_MAXگس77ترده ش77دهاند RAND_MAX .در اين
رايانه برابر با 2,147,483,647است.
}
هر عدد شبهتصادفي از روي عدد قبلي خ777ود ساخته
ميشود.
اولين عدد شبهتصادفي از روي ي77ك مق77دار داخلي
که «هسته» گفته ميشود ايجاد ميگردد.
هر دفعه که برنامه اجرا شود ،هسته با ي77ک مق77دار
پيشفرض بارگذاري ميشود.
براي حذف اين اثر نامطلوب ک77ه از تصادفي ب77ودن
اعداد ميکاهد ،ميتوانيم با استفاده از تابع ()srand
خودمان مقدار هسته را انتخاب کنيم.
#include <cstdlib> // defines the rand() and srand()
#include <iostream>
intاي
main()
كارگذاري هسته به طور محاوره4-23 مثال
{ // prints pseudo-random numbers:
ز77unsigned
ت بج77اسseed;
4-22 ال77اين برنامه مانند برنامۀ مث
تصادفي
توليدکنندۀ
cout <<اعداد
"Enter
seed: "; اين كه ميتوان هستۀ
cin >> seed; :را به شکل محاورهاي وارد نمود
srand(seed);
// initializes the seed
for (int i = 0; i < 8; i++)
cout << rand() << endl;
}
پايان جلسه چهارم
جلسه پنجم
« توابع»
:آنچه در اين جلسه مي خوانيد
-1توابع كتابخانهاي ++Cاستاندارد
-2توابع ساخت كاربر
-3برنامۀ آزمون
-4اعالنها و تعاريف تابع
-5كامپايل جداگانۀ توابع
-6متغيرهاي محلي ،توابع محلي
›››
-7تابع void
- 8توابع بولي
-9توابع ورودي/خروجي ()I/O
-10ارسال به طريق ارجاع (آدرس)
ق ارجاع ثابت
-11ارسال از طري
-12توابع بيواسطه
›››
-13چندشکلي تواب
ع
-14تابع )(main
ي پيشفرض
-15آرگومانها
هدفهاي رفتاري:
پس از پايان اين جلسه بتوانيد:
يرود
انتظار م
کلي:
هدف
-اهميت توابع و مزيت استفاده از آنها را بيان کنيد.
ش77ناخت و معرفي تواب77ع و مزاياي اس77تفاده از ت77ابع در
هاو «تعري77ف» ت77ابع را بداني77د و خودت77ان ت77وابعي را ايجاد
«اعالن»
-برنامه
کنيد.
«برنامۀ آزمون» را تعريف کرده و دلي77ل اس77تفاده از آن را بياننماييد.
-مفهوم «آرگومان» را بدانيد.
تفاوت ارسال به طري77ق «ارجاع» و ارسال ب77ه طري77ق «مق77دار» وارسال به طريق «ارجاع ثابت» را بيان کنيد و شکل اس777تفاده از هر
يک را بدانيد.
›››
«تابع بيواس77طه» را ش77ناخته و نح77وۀ معرفي آن رابدانيد.
چندش77کلي تواب77ع را تعري77ف کني77د و ش77يوۀ آن رابدانيد.
طريق777ۀ بهک777ارگيري آرگومانهاي پيشفرض رابدانيد.
-فرق بين تابع voidبا ساير توابع را بدانيد.
-1مقدمه
برنامههاي واقعي و تجاري بس7777777يار بزرگتر از
برنامههايي هس77تند ک77ه ت77اکنون بررس77ي کرديم.
ب77راي اين ک77ه برنامههاي ب77زرگ قاب77ل م77ديريت
باش7777777ند ،برنامهنويسان اين برنامهها را ب7777777ه
زيربرنامههايي بخشبن7777777دي ميکنن7777777د .اين
زيربرنامهها «ت777ابع» نامي777ده ميش777وند .تواب777ع را
ميتوان به طور جداگانه کامپايل و آزمايش نمود و
در برنامههاي مختل7777ف دوباره از آنها اس7777تفاده
کرد.
-2توابع كتابخانهاي ++Cاستاندارد
«كتابخان77ۀ ++Cاس77تاندارد» مجم77وعهاي اس77ت ک77ه
ع از پيش تعري77ف ش77ده و ساير عناصر
ش77امل ت77واب
برنامه است .اين توابع و عناصر از طريق «سرفايلها»
قابل دستيابياند.
قبال ب7777رخي از آنها را اس7777تفاده كردهايم :ث7777ابت
INT_MAXک77ه در < >climitsتعري77ف ش77ده ،
تابع () sqrtکه در < >cmathتعري77ف ش77ده اس77ت
و. ...
تابع جذر )(sqrt
ريشۀ دوم يك عدد مثبت ،جذر آن عدد است.
تابع مانند ي77ک برنام77ۀ کام77ل ،دارايرون77د ورودي -
پ77ردازش -خروجي اس77ت هرچن77د ک77ه پ77ردازش،
مرحلهاي پنهان است .يعني نميدانيم ک77ه ت77ابع روي
ع77دد 2چ77ه اعمالي انجام ميده77د ک77ه 41421/1
حاصل ميشود.
ذر را77دۀ ج77 تابع از پيش تعريف ش،برنامۀ سادۀ زير
:به کار ميگيرد
#include <cmath>
// defines the sqrt() function
#include <iostream> // defines the cout object using namespace std;
int main()
{ //tests the sqrt() function:
}
افي77() کsqrt ابع77د ت77ابع مانن77براي اجراي يك ت
for (int x=0; x < 6; x++)
ير در77ک متغ77ورت ي77ه ص77ابع ب77ام آن ت77ت ن77اس
cout << "\t" << x << "\t" << sqrt(x) << endl;
: مانند زير،دستورالعمل مورد نظر استفاده شود
y=sqrt(x);
اين ک77ار «فراخ77واني ت77ابع» يا «احض77ار ت77ابع» گفت77ه
ميشود .بنابراين وقتي كد ) sqrt(xاجرا شود ،ت77ابع
)(sqrtفراخواني ميگردد .عبارت xدرون پران7777تز
«آرگومان» يا «پارامتر واقعي» فراخ7777واني نامي7777ده
ميش77ود .در چ77نين حالتي ميگ77وييم كه xتوس77ط
«مقدار» به تابع فرس77تاده ميش77ود .ل77ذا وق77تي x=3
است ،با اجراي ک77د ) sqrt(xت77ابع )(sqrtفراخ77واني
شده و مقدار 3به آن فرستاده ميشود .تابع مذکور
ن7777يز حاص7777ل 1.73205را ب7777ه عن7777وان پاسخ
برميگرداند…
… اين فرايند در نمودار زير نشان داده شده.
)(Sqrt
3
1.73205
)(Main
int
3
x
1.73205
y
double
متغيرهاي xو yدر تابع )(mainتعريف شدهاند .مقدار xکه برابر
با 3اس77ت ب77ه ت77ابع )(sqrtفرس77تاده ميش77ود و اين ت77ابع مق77دار
1.73205را به تابع )(mainبرميگرداند .جعبهاي كه تابع )(sqrt
را نشان ميدهد به رنگ تيره است ،به اين معنا كه فرايند داخلي و
نحوۀ کار آن قابل رويت نيست.
مثال 5-2آزمايش يك رابطۀ مثلثاتي
اين برنامه هم از سرفايل < >cmathاستفاده ميكند .ه77دف اين
است که صحت رابطۀ Sin2x=2SinxCosxبه ش77کل تج77ربي
بررسي شود.
)(int main
)for (float x=0; x < 2; x += 0.2
{
“cout << x << "\t\t" << sin(2*x) << "\t
;<< 2*sin(x)*cos(x) << endl
}
خروجي برنامه:
0
0
برنام77ۀ مق77دار xرا
0.717356
0.717356
در س7777777تون اول،
0.932039مقدار
دهد که براي هر
خروجي نشان مي
0.932039
مق7777دار Sin2xرا
0.999574
0.999574
مقدار
مقدار Sin2xبا
آزمايشي ،x
و
دوم
س77777تون
در
0.909297
0.909297
2SinxCosxبرابر است.
مق77777777777777777دار
0.675463
0.675463
2SinxCosxرا
0.334988
0.334988
در س7777تون س7777وم
-0.0583744 -0.0583744
چا
-0.442521
پ ميكند-0.442521 .
0.389418
0.389418
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
ماشينحسابها همتابع
مثالمعروف رياضي كه در شرح
وج77ود
بيشتر توابع
دار
) acos(0.2مق
اين
از
بعضي
است.
شده
تعريف
>
cmath
<
سرفايل
دارد در
)acos(x
1.36944را برميگرداند کسينوس معکوس( xبه راديان)
نشان داده شده:
جدول زير
توابع در
دار
) asin(0.2مق
0.201358
برميگرداند
) atan(0.2مق
0.197396
برميگرداند
)ceil(3.141593
مقدار 4.0را برميگرداند
) cos(2مق
0.416147برميگرداند
را
دار
را
دار
را
سينوس معکوس ( xبه راديان)
تانژانت معکوس ( xبه راديان)
مقدار سقف ( xگرد شده)
کسينوس ( xبه راديان)
دار
) exp(2مق
7.38906را برميگرداند تابع نمايي ( xدر پايه )e
)asin(x
)atan(x
)ceil(x
)cos(x
)exp(x
) floor(3.141593مقدار کف ( xگرد
شده)
مقدار 3.0را برميگرداند
لگاريتم طبيعي ( xدر
) log(2مقدار
0.693147را برميگرداند پايه )e
لگاريتم عمومي ( xدر
) log10(2مقدار
0.30103را برميگرداند پايه )10
) pow(2,3مقدار 8.0را
xبه توان p
برميگرداند
) sin(2مقدار
0.909297را برميگرداند سينوس ( xبه راديان)
) sqrt(2مقدار
1.41421را برميگرداند جذر x
) tan(2مقدار
2.18504-را برميگرداند تانژانت ( xبه راديان)
floor(x
)
)log(x
log10(x
)
pow(x,p
)
)sin(x
)sqrt(x
)tan(x
توجه داشته باشيد که هر تابع رياض77ي ي77ک مق77دار از
نوع doubleرا برميگرداند .اگر يك نوع ص77حيح ب77ه
ت77ابع فرس77تاده ش77ود ،قب77ل از اين كه ت77ابع آن را
doubleارتق77ا
پ77ردازش کن77د ،مق77دارش را ب77ه ن77وع
ميدهد.
بعضي از سرفايلهاي كتابخانۀ ++Cاستاندارد که کاربرد
استاندارد گرفته
آمدهC
كتابخان ۀ
ها از
سرفاي
اين
است:
جدول زير
دارندلدر
بيشتري
اس77تفاده از آنها شبيه اس77تفاده از
ش77دهاند.
سرفايل
شرح
اس7777777تاندارد (مانن7777777د
هاي C
تابع <سرفايل
++ميکند
تعريف
>assertرا
><assert
يکند
کاراکترها تعريف م
<براي بررسي
توابعي را
><ctype
ب7777راي مث7777ال اگر
اس7777ت.
) >iostream
اع777دادتعريف مي
ت777ابع شناور را
بخ777واهيماعداد مميز
ثابتهاي مربوط به
><cfloat
کند )(randرا از
تصادفي
محدودۀ اعداد صحيح را روي سيستم موجود تعريف ميکند ><climits
سرفايل < >cstdlibب777ه كار ب777بريم ،باي777د
توابع رياضي را تعريف ميکند
><cmath
7ل
7
فاي
7داي
7
ابت
7ه
7
ب
را
زير
پردازندۀ
ش
پي
دستور
توابعي را براي ورودي و خروجي استاندارد تعريف ميکند
><cstdio
اضافه کنيم:
کاربرديۀرااصلي
توابع برنام
تعريف ميکند
><cstdlib
توابعي را براي پردازش رشتهها تعريف ميکند
><cstring
#include
><cstdlib
توابع تاريخ و ساعت را تعريف ميکند
><ctime
-3توابع ساخت كاربر
گرچ77ه تواب77ع بس77يار متن77وعي در کتابخان77ۀ ++C
استاندارد وج77ود دارد ولي اين تواب77ع ب77راي بيش77تر
ف برنامهنويس77ي كافي نيس77تند .عالوه ب77ر اين
وظاي
برنامهنويسان دوس777ت دارن777د خودش777ان بتوانن777د
توابعي را بسازند و استفاده نمايند.
مثال 5-3تابع )(cube
يك مثال ساده از توابع ساخت كاربر:
اين ت77777ابع ،مكعب
ي77ك ع77دد ص77حيح
ارسالي ب777777ه آن را
برميگردان777777777د.
بن77ابراين فراخ77واني
) cube(2مق77دار 8
را برميگرداند.
)int cube(int x
{ // returns cube of x:
;return x*x*x
}
يك تابع ساخت كاربر دو قسمت دارد:
-2بدنه.
-1عنوان
عنوان يك تابع به صورت زير است:
نا م
نوع بازگشتي )فهرست پارامترها(
تعري77ف
باال
در
که
()
cube
تابع
بازگشتي
نوع
بدنۀ تابع ،يك بلوك كد است كه در ادام77ۀ عن77وان
مثال:
7ک
7
ي
و
7د
7
باش
ي
م
cube
آن
7ام
7
ن
7ت.
7
اس
int
شد،
آن ميآيد .بدنه شامل دس77توراتي اس77ت كه باي77د
7ابع int
cube(int
پارامتر از ن77وع intب77ه ن77ام xداردx).
7
ت
7ني
7
يع
انجام شود تا نتيجۀ مورد نظر به دست آي77د .بدن77ه
)(cubeي777ک مق777دار از ن777وع intميگ777يرد و {
ب7777ه
را
نهايي
پاسخ
كه
است
return
دستور
شامل
پاسخي از نوع intتحويل ميدهد .بدنه تابع …
گرداند.
ي
برم
تابع
فراخواني
مكان
}
دستور returnدو وظيفۀ عم77ده دارد .اول اين ک77ه
اجراي تابع را خاتمه ميدهد و دوم اين که مق77دار
برنامهها
هم77ۀ
)(int main
دس77تور
گرداند.
در مي
ک77ه باز
فراخوان
عبارت برنامۀ
نهايي را به
شود7:ام «ت77ابع
7ابعيب77ه ن7
ايم يک ت7
استفاده م
کردهزير
استفادهشکل
returnبه
اصلي» را تعريف ميکند .ن77وع بازگش77تي
return
expression
;
اين تابع از ن77وع intاس77ت .ن77ام آن main
خ77الي
اس77ت و
گيرد که
آن مي
پارامترهايقرار
فهرس77تهر عبارتي
expression
به جاي
متغيرندارد.
پارامتري
هيچ
بتواناست؛
تخصيص داد .نوع
به يک
يعني را
مقدار آن
آن عبارت بايد با نوع بازگشتي تابع يکي باشد.
برنامۀ آزمون 4-
فورا
برنام777ه،کرديد،
ايننياز را ايجاد
هدفمورد
تنهايک تابع
وقتي
امتحان
که باي77د
است
برنامۀ موقتي
يک
آزمون
برنامۀ
امتحان
ساده
برنام777ۀ
ي777ک
با
را
تابع
آن
بايد
باشد؛ بررس77ي ص77حت
ت77ابع و
کردن
»
کثيف
و
سريع
«
کنيد .چنين برن77امهاي برنام77ۀ آزم77ون نامي77ده
شود.آن است.
کار
مييعني:
الزم نيس77777777777777ت در آن تمام ظرافتهاي
برنامهنويس77777ي – مث77777ل پيغامهاي خروجي،
برچسبها و راهنماهاي خوانا – را لحاظ کنيد.
مثال 5-4يك برنامۀ آزمون براي تابع )(cube
کد زير شامل تابع )(cubeو برنامۀ آزمون آن است:
برنامۀ حاضر اعداد ص77حيح
را از ورودي ميگ777777يرد و
مكعب آنها را چاپ
ميكن77د ت77ا اين كه كاربر
مقدار 0را وارد كند.
)int cube(int x
{ // returns cube of x:
;return x*x*x
}
)(int main
{ // tests the cube() function:
;int n=1
)while (n != 0
;{ cin >> n
}} ;cout << "\tcube(" << n << ") = " << cube(n) << endl
هر عدد صحيحي که خوانده ميشود ،با استفاده از
ک77د ) cube(nب77ه ت77ابع )(cubeفرس7تاده ميش77ود.
مقدار بازگشتي از تابع ،جايگزين عبارت )cube(n
دقت كنيد كه تابع )(cubeدر باالي ت77ابع )(mainتعري77ف ش77ده
چاپ
خروجي
در
cout
از
اس77777تفاده
با
و
گش77777ته
زيرا قب77ل از اين كه ت77ابع )(cubeدر ت77ابع )(mainب77ه كار رود،
شود.
مي
++Cبايد در بارۀ آن اطالع حاصل كند.
كامپايلر
)(cube
)(main
5
5
ت77ابع )(cube 5را
و
()
main
تابع
بين
رابطۀ
توان
مي
int
int
125
شبيه اين شکل تصور نمود:
x
n
)(max يك برنامۀ آزمون براي تابع5-5 مثال
: مقدار بزرگتر را برميگرداند، اين تابع از دو مقدار فرستاده شده به آن.تابع زير دو پارامتر دارد
int max(int x, int y)
{ // returns larger of the two given integers:
int z;
z = (x > y) ? x : y ;
return z;
}
int main()
{ int m, n;
do
{ cin >> m >> n;
cout << "\tmax(" << m << "," << n << ") = " << max(m,n) << endl; }
while (m != 0);}
توابع ميتوانند بيش از يک دستور returnداشته باشند .مثال تابع )(maxرا مانن77د اين
نيز ميتوانستيم بنويسيم:
7رش اس77ت
7تور پ7
int max(int
x, int
دس77تور returnن77وعي دسy) 7
(شبيه دستور ) breakزيرا اجرا را به بيرون
{ // returns larger of the two given integers:
از ت77ابع ه77دايت ميکن77د .اگرچ77ه معم77وال
ت77777ابع قرار م
در انتهاي
returnهر
در اين کد
گ77777يردif،
returnي )(x < y
دس777تور ;y
هر نقط77ۀ ديگري از ت77ابع
را در
توان آن
مي
اج77را
زودتر
returnکه
;else return x
شودقرار
داد.مرب77وطهاش
مقدار
را بازگشت داده و ت77ابع
}
را خاتمه ميدهد.
-5اعالنها و تعاريف تابع
به دو روش ميتوان توابع را تعريف نمود:
-1توابع قبل از تابع )(mainبه طور كامل با بدن77ه
مربوطه آورده شوند.
-2راه ديگري ک77ه بيش77تر رواج دارد اين گون77ه
است که ابتدا تابع اعالن شود ،سپس متن برنام77ۀ
اصلي )(mainبيايد ،پس از آن تعريف کامل ت77ابع
قرار بگيرد.
اعالن تابع با تعريف تابع تفاوت دارد.
اعالن تابع شبيه اعالن متغيرهاست.
اعالن تابع ،فقط عنوان تابع است که يک س77ميکولن
در انتهاي آن قرار دارد.
7امل
هم ش7
7ابعکاراس77ت ک
اين77ل
متن کام
تعريف ت7
باي77د
گرفته77هشود
کهت7به
7ابع،قبل از
متغير
يک
شامل
اعالن است
عنوان
بدنه.طور است با اين فرق
همين
هم هم
شود.وتابع
که متغير را در هر جايي از برنامه ميت77وان اعالن
کرد اما ت77ابع را باي77د قب77ل از برنام77ۀ اص77لي اعالن
نمود.
در اعالن تابع فقط بيان ميش77ود ک77ه ن77وع بازگش77تي
تابع چيست ،نام تابع چيست و نوع پارامترهاي ت77ابع
چيست.
همينها ب77راي کامپايلر ک77افي اس77ت ت77ا بتوان77د
کامپايل برنامه را آغاز کند .سپس در زمان اج777را
به تعريف بدنۀ تابع ن77يز احتياج ميش77ود ک77ه اين
بدنه در انتهاي برنامه و پس از تابع )(mainقرار
ميگيرد.
فرق بين «آرگومان» و «پارامتر» :
پارامترها متغيرهايي هس77تند ک77ه در فهرس77ت
پارامتر يک تابع نام برده ميشوند.
پارامترها متغيرهاي محلي براي تابع محس77وب
ميشوند؛ يعني فقط در طول اجراي ت77ابع وج77ود
دارند.
آرگومانها متغيرهايي هس777تند ک777ه از برنام777ۀ
اصلي به تابع فرستاده ميشوند.
مثال 5-6تابع )(maxبا اعالن جدا از تعريف آن
اين برنامه همان برنامۀ آزمون تابع )(maxدر مثال 6-5اس77ت.
اما اينجا اعالن تابع باالي تابع اصلي ظاهرش77ده و تعري77ف ت77ابع
بعد از برنامۀ اصلي آمده است:
;)int max(int,int
)(int main
;int m, n
{
do
;{ cin >> m >> n
" = )" << cout << "\tmax(" << m << "," << n
} ;<< max(m,n) << endl
توجه كني77د كه پارامترهاي xو y
در بخش عن777وان تعري777ف ت777ابع
آمدهان77د (طب77ق معم77ول) ولي در
اعالن تابع وجود ندارند.
};)while (m != 0
)int max(int x, int y
;{ if (x < y) return y
};else return x
-6كامپايل جداگانۀ توابع
ش77کل
همين
ب77ه
اس77تاندارد
++
C
کتابخان77ۀ
تواب77ع
اغلب اين طور است که تعريف و بدنۀ تواب77ع در
پيادهسازي شدهاند و هنگامي که يکي از آن توابع را
فايلهاي جداگانهاي قرار ميگ777يرد .اين فايلها
در برنامههايت77ان ب77ه ک77ار ميبري77د باي77د با دس77تور
ب777ه
سپس
و
ش777وند
ي
م
1
کامپايل
مستقل
طور
به
راهنماي پيشپردازن777ده ،فاي777ل آن تواب777ع را ب777ه
کنيد.تواب77ع را ب77ه ک77ار ميگ77يرد
7ه آن
تان7لي ک7
برنامۀهاص7
ضميمه
برنام
الصاق 2ميشوند.
اين کار چند مزيت دارد:
-1اولين مزيت «مخفيسازي اطالعات» است.
-2مزيت ديگر اين است که توابع مورد نياز را ميتوان قب77ل
از اين که برنام77ۀ اص77لي نوش77ته ش77ود ،جداگان77ه آزمايش
نمود.
-3س77ومين مزيت اين اس77ت ک77ه در هر زماني ب77ه راح77تي
ميتوان تعريف تواب77ع را ع77وض کرد ب77دون اين ک77ه الزم
باشد برنامۀ اصلي تغيير يابد.
-4چهارمين مزيت هم اين است که ميتوانيد يک بار ي777ک
تابع را کامپايل و ذخيره کنيد و از آن پس در برنامههاي
مختلفي از همان تابع استفاده ببريد.
تابع )(maxرا به خاطر بياوريد .ب77راي اين ک77ه اين
تابع را در فايل جداگانهاي قرار دهيم ،تعري777ف آن
را در فايلي به نام max.cppذخيره ميکنيم .فاي77ل
max.cppشامل کد زير است:
max.cpp
)int max(int x, int y
;if (x < y) return y
{
;else return x
}
#
> راinclude <test.cpp :حال كافي است عبارت
:() اضافه كنيمmainبه اول برنامه اصلي وقبل از
#include <test.cpp>
int main()
{ // tests the max() function:
int m, n;
do
{ cin >> m >> n;
cout << "\tmax(" << m << "," << n << ") = "
<< max(m,n) << endl;
}
while (m != 0);}
نح777وۀ کامپاي777ل کردن فايلها و الصاق آنها ب777ه
يک77ديگر ب77ه ن77وع سيس77تم عام77ل و ن77وع کامپايلر
بستگي دارد .در سيستم عامل ويندوز معموال توابع
را در فايلهايي از ن777وع DLLکامپاي777ل و ذخ777يره
ميکنند و سپس اين فايل را در برنامۀ اصلي احضار
مينمايند .فايلهاي DLLرا ب77ه دو طري77ق ايس77تا و
پويا ميتوان مورد استفاده قرار داد .ب77راي آش77نايي
بيش777تر با فايلهاي DLLب777ه مرج777ع وين777دوز و
کامپايلرهاي ++Cمراجعه کنيد.
-6متغيرهاي محلي ،توابع محلي
متغير محلي ،متغيري است که در داخل يک بلوک
اعالن گردد .اين گون777ه متغيرها فق777ط در داخ777ل
دس77تيابي
قاب77ل
اعالن 7م
7ار
در حال ک7
ش77وند7ابع
ي ک77ه ت7
7تي
ک77ه ت77ا وق
بل77وکيفقط
همانمتغيرها
اين
هستند.وجود دارند.
است
7ت7پس
محلياس7
متغيرهايبل77وک
7ودش ي77ک
7ابع،
چ77ون بدن77ۀ
7وب
محس
7ابع نخ777يز
پارامترهايت7ت7
متغيرهاي اعالن ش777ده در ي777ک ت777ابع متغيرهاي
ميشوند.
محلي براي آن تابع هستند.
* مثال 5-7تابع فاكتوريل
اعداد فاكتوريل را در مثال 5-8ديديم .فاكتوريل عدد صحيح nبرابر است با:
)n! = n(n-1)(n-2)..(3)(2)(1
تابع زير ،فاکتوريل عدد nرا محاسبه ميکند:
)long fact(int n
){ //returns n! = n*(n-1)*(n-2)*...*(2)*(1
;if (n < 0) return 0
اين ت77ابع دو متغ77ير محلي دارد n :و f
پارامتر nيک متغير محلي است زي77را
در فهرس777ت پارامترهاي ت777ابع اعالن
شده و متغير fنيز محلي اس77ت زي77را
درون بدنۀ تابع اعالن شده است.
;int f = 1
)while (n > 1
;f *= n--
;return f
}
همان گونه که متغيرها ميتوانند محلي باشند ،تواب77ع ن77يز ميتوانن77د محلي
باشند.
تابع محلي
يک تابع محلي ت77ابعي اس77ت ک77ه درون ي77ک ت77ابع ديگر ب77ه ک77ار رود .با
استفاده از چن77د ت77ابع ساده و ترکيب آنها ميت77وان تواب77ع پيچي77دهتري
ساخت .به مثال زير نگاه کنيد.
در رياضيات ،تابع جايگشت را با ) p(n,kنشان ميدهن77د .اين ت77ابع بيان
ميکند که به چن77د طري77ق ميت77وان kعنصر دلخ77واه از ي77ک مجموع77ۀ n
عنصري را کن77ار يک77ديگر قرار داد .ب77راي اين محاسبه از رابط77ۀ زي77ر
استفاده ميشود:
!n
P(n, k)
!)(n k
!4
4! 24
P(4,2)
12
(4 2)! 2! 2
چهار
مجموع77ۀ
ت77ابع ي77ک
دلخ77واه از
ت77وانيم دو
طري77ق مي
اينب77ه
پس
اس77ت
فاکتوري77ل
عنصرهمان
ديگري ک77ه
ت77ابع
12خود از
تابع،
بچي77نيم .ب77راي دو عنصر از مجموع77ۀ {}4 ,3 ,2 ,1
کن77ار هم
عنصري
است.
استفادهراکرده
حالتهاي ممکن عبارت است از:
شرط به کار رفته در دستور ifبراي مح7777دود کردن حالتهاي
12, 13, 14, 21, 23, 24, 31, 32, 34, 41, 42,
غير ممکن استفاده شده است .در اين حالتها ،ت77ابع مق77دار 0را
43
برميگرداند تا نشان دهد که ي77ک ورودي اش77تباه وج77ود داش77ته
ي ميكند:
زير تابع جايگشت را پيادهساز
كد
است.
)long perm(int n, int k
{// returns P(n,k), the number of the permutations of k from n:
;if (n < 0) || k < 0 || k > n) return 0
;)return fact(n)/fact(n-k
:() در ادامه آمده استperm برنامۀ آزمون براي تابع
long perm(int,int);
// returns P(n,k), the number of permutations of k from n:
int main()
{ // tests the perm() function:
for (int i = -1; i < 8; i++)
{ for (int j= -1; j <= i+1; j++)
cout << " " << perm(i,j);
cout << endl; }
}
00
010
0110
01220
013660
0 1 4 12 24 24 0
0 1 5 20 60 120 120 0
0 1 6 30 120 360 720 720
0
0 1 7 42 210 840 2520
-7تابع void
الزم نيست يك تابع حتما مق77داري را برگردان77د .در ++Cب77راي
مشخص کردن چنين توابعي از کلمۀ کليدي voidبه عن77وان ن77وع
بازگشتي تابع استفاده ميکنند
يک تابع voidتابعي است که هيچ مقدار بازگشتي ندارد.
از آنجا كه يك تابع voidمقداري را برنميگرداند ،نيازي به دستور return
نيست ولي اگر قرار باشد اين دستور را در تابع voidقرار دهيم ،باي77د آن را
به شکل تنها اس77تفاده ک77نيم ب77دون اين ک77ه بع77د از کلم77ۀ returnهيچ چ77يز
ديگري بيايد:
;return
در اين حالت دستور returnفقط تابع را خاتمه ميدهد.
-8توابع بولي
در بسياري از اوقات الزم است در برنامه ،شرطي بررسي شود.
اگر بررسي اين شرط به دستورات زيادي نياز داشته باشد ،بهتر است که
يک تابع اين بررس77ي را انجام ده77د .اين ک77ار مخصوصا هنگ77امي ک77ه از
حلقهها استفاده ميشود بسيار مفيد است.
توابع بولي فقط دو مقدار را برميگردانند true :يا . false
اسم توابع بولي را معموال به شکل سوالي انتخاب ميکنند زي77را تواب77ع
بولي هميشه به يک سوال مفروض پاسخ بلي يا خير ميدهند.
تابعي ك ه اول بودن اعداد را بررسي ميكند5-10 مثال
: اول است يا خير،کد زير يك تابع بولي است كه تشخيص ميدهد آيا عدد صحيح ارسال شده به آن
bool isPrime(int n)
{ // returns true if n is prime, false otherwise:
float sqrtn = sqrt(n);
if (n < 2) return false;
// 0 and 1 are not primes
if (n < 4) return true;
// 2 and 3 are the first primes
if (n%2 == 0) return false; // 2 is the only even prime
for (int d=3; d <= sqrtn; d += 2)
if (n%d == 0) return false; // n has a nontrivial divisor
return true;
}
// n has no nontrivial divisors
-9توابع ورودي/خروجي ()I/O
بخشهايي از برنامه که به جزييات دست و پا گير ميپردازد و خيلي
به هدف اصلي برنامه مربوط نيس77ت را ميت77وان ب77ه تواب77ع سپرد .در
چنين شرايطي سودمندي توابع محسوستر ميشود.
فرض کني77د نرمافزاري ب77راي سيس77تم آموزش77ي دانش77گاه طراحي
کردهاي77د ک77ه س77وابق تحص77يلي دانشجويان را نگ77ه ميدارد .در اين
نرمافزار الزم است که سن دانشجو به عنوان يکي از اطالعات پروندۀ
دانشجو وارد شود .اگر وظيف77ۀ دريافت س77ن را ب77ه عه77دۀ ي77ک ت77ابع
بگذاريد ،ميتوانيد جزيياتي از قبيل کنترل ورودي معتبر ،يافتن س77ن
از روي تاريخ تولد و ...را در اين تابع پيادهسازي کنيد بدون اين ک77ه
از مسير برنامۀ اصلي منحرف شويد.
قبال نمونهاي از توابع خروجي را ديديم .تابع )(PrintDate
در مثال 5-9هيچ چيزي به برنام77ۀ اص77لي برنميگردان77د و
فقط براي چاپ نتايج به کار ميرود.
اين تابع نمونهاي از توابع خروجي است؛ يعني ت77وابعي ک77ه
فق77ط ب77راي چاپ نت77ايج ب77ه ک77ار ميرون77د و هيچ مق77دار
بازگشتي ندارند.
توابع ورودي نيز به همين روش کار ميکنند اما در جهت
معکوس .يعني توابع ورودي فقط ب777راي دريافت ورودي و
ارسال آن به برنامۀ اصلي به کار ميرون777د و هيچ پارامتري
ندارند.
مثال بعد يک تابع ورودي را نشان ميدهد.
مثال 5-11تابعي براي دريافت سن كاربر
)(int age
{ // prompts the user to input his/her age and returns that value:
ب77ه
تابع سادۀ زير ،سن کاربر را درخواست ميکند و مقدار دريافت ش77ده را
برنامۀ اصلي ميفرستد .اين تابع تقريبا هوش77مند اس77ت و هر ع77دد ;int n
ص77حيح
وروديwhile
ورودي غير منطقي را رد ميکند و به طور مکرر درخواس7777ت )(true
معتبر
{ cout
"How120
old are
ميکند تا اين که يک عدد صحيح در ;"
دريافت<<دارد:
7you:تا
محدودۀ
;cin >> n
if (n < 0) cout << "\a\tYour age could not
;"be negative.
else if (n > 120) cout << "\a\tYou could not
;"be over 120.
;else return n
;"cout << "\n\tTry again.\n
}
}
:يك برنامۀ آزمون و خروجي حاصل از آن در ادامه آمده است
int age()
int main()
{ // tests the age() function:
int a = age();
cout << "\nYou are " << a << " years old.\n";
}
How old are you? 125
You could not be over 120
.Try again
How old are you? -3
Your age could not be negative
.Try again
How old are you? 99
.You are 99 years old
ت77ا اين لحظه تما م پارامترهايي كه در ت77وابع دي77ديم ب ه
طريق مقدار ارسال شدهاند .يعني ابت77دا مق77دار متغ77يري
که در فراخواني تابع ذکر شده برآورد ميشود و سپس
اين مقدار به پارامترهاي محلي تابع فرستاده ميشود.
مثال در فراخواني ) cube(xابتدا مقدار xبرآورد ش77ده و
سپس اين مق77دار ب77ه متغ77ير محلي nدر ت77ابع فرس77تاده
ميشود و پس از آن تابع کار خ77ويش را آغ77از ميکن77د.
در طي اجراي تابع ممکن است مقدار nتغي77ير کن77د اما
چ7777ون nمحلي اس7777ت هيچ تغي7777يري روي مق7777دار x
نميگذارد.
پس خود xبه تابع نميرود بلکه مقدار آن درون تابع کپي ميشود.
تغيير دادن اين مقدار کپي شده درون تابع هيچ تاثيري بر xاصلي ن77دارد.
به اين ترتيب ت77ابع ميتوان77د مق77دار xرا بخوان77د اما نميتوان77د مق77دار xرا
تغيير دهد.
به همين دليل به xيک پارامتر «فقط خواندني» ميگويند.
وقتي ارسال به وسيلۀ مقدار باشد ،هنگام فراخواني تابع ميتوان از عبارات
استفاده کرد.
مثال تابع )(cubeرا ميتوان به صورت) cube(2*x-3فراخواني کرد يا
به شکل )) cube(2*sqrt(x)-cube(3فراخواني نمود .در هر يک از اين
حاالت ،عبارت درون پرانتز به شکل يک مقدار تکي برآورد شده و حاصل
آن مقدار به تابع فرستاده ميشود.
-10ارسال به طريق ارجاع (آدرس)
ارسال به طريق مقدار باعث ميشود ک777ه متغيرهاي
برنامۀ اصلي از تغييرات ناخواسته در تواب77ع مص77ون
بمانند.
اما گ77اهي اوق77ات عم77دا ميخ77واهيم اين اتف77اق رخ
دهد .يع77ني ميخ77واهيم ک77ه ت77ابع بتوان77د محتويات
متغير فرستاده شده ب77ه آن را دس7تکاري کن77د .در
اين حالت از ارسال ب7777ه طري7777ق ارجاعاس7777تفاده
ميکنيم.
براي اين که مشخص کنيم يک پارامتر ب77ه طري77ق ارجاع
ارسال ميش77ود ،عالمت&را ب77ه ن77وع پارامتر در فهرس77ت
پارامترهاي تابع اضافه ميکنيم .اين باعث ميشود که تابع
به جاي اين که يک کپي محلي از آن آرگومان ايجاد کند،
خود آرگومان محلي را به کار بگيرد.
به اين ترتيب تابع هم ميتواند مقدار آرگومان فرس77تاده
شده را بخواند و هم ميتواند مقدار آن را تغيير ده77د .در
اين حالت آن پارامتر ي777ک پارامتر «خواندني-نوش777تني»
خواهد بود.
هر تغييري که روي پارامتر خواندني-نوشتني در تابع ص77ورت گ77يرد ب77ه ط77ور
مستقيم روي متغير برنامۀ اصلي اعمال ميشود .به مثال زير نگاه کنيد.
ع )(swap
* مثال 5-12تاب
ك زير در مرتب کردن دادهها کاربرد فراوان دارد:
تابع كوچ
)void swap(float& x, float& y
{ // exchanges the values of x and y:
ف اين تابع جابجا کردن دو عنصري اس77ت
هد
که به آن فرستاده ميشوند .براي اين منظ77ور
پارامترهاي xو yب7777ه ص7777ورت پارامترهاي
ارجاع تعريف شدهاند:
float& x, float& y
;float temp = x
;x = y
;y = temp
}
آرگومانهاي ارساليy وx ب ميشود ك ه به جاي
ع & موج
عملگر ارجا
: برنامۀ آزمون و اجراي آزمايشي آن در زير آمده است.قرار بگيرند
void swap(float&, float&)
:exchanges the values of x and y //
)(int main
:tests the swap() function // {
;float a = 55.5, b = 88.8
;cout << "a = " << a << ", b = " << b << endl
;swap(a,b)
;cout << "a = " << a << ", b = " << b << endl
}
a = 55.5, b = 88.8
a = 88.8, b = 55.5
وقتي فراخواني ) swap(a,bاجرا ميش77ود x ،ب77ه aاش77اره
ميکند و yبه .bسپس متغ77ير محلي tempاعالن ميش77ود
)swap(a,bگيرد .پس
تابعقرار مي
فراخوانيآن
هنگامدرون
و مقدار ( xکه همان aاست)
)(main
a)a 55.5قرار
همان bاست) درون ( xيع777ني
از آن مقدار ( yکه
x
ميگيرد و آنگاه&float
floatقرار داده
مقدار tempدرون ( yيعني )b
y
b 88.8
يکديگر
اين است که مقادير aو bبا
نهايي
نتيجۀ
شود.
ي
م
&float
float
جابجا مي شوند .شکل مقابل نشان ميدهد ک77ه چط77ور اين
دهد:
ي
م
رخ
جابجايي
)(swap
)(main
بعد از بازگشت
)(swap
x
88.8
float
y
55.5
&float
&float
55.5
float
temp
float
a
b
به اعالن تابع )(swapدقت کنيد:
)&void swap(float&, float
اين اعالن شامل عملگر ارجاع & براي هر پارامتر است.
برنامهنويسان cعادت دارند که عملگر ارجاع & را ب77ه
عنوان پيشوند نام متغ77ير اس77تفاده کنن77د (مثل)float &x
در ++Cفرض ميکنيم عملگر ارجاع & پس777وند ن777وع
است (مثل )float& x
ب7777777777ه هر حال کامپايلر هيچ فرقي بين اين دو اعالن
نميگذارد و شکل نوشتن عملگر ارجاع کامال اختياري و
سليقهاي است.
ق مقدار و ارسال ب ه طريق ارجاع
مثال 5-13ارسال به طري
ت77ابع )(fدو پارامتر دارد ک77ه اولي ب77ه طري77ق مق77دار و
طريق ارجاع را نشان ميدهد:
ارسال به
شود.مقدار و
ق
بهيطري
ن ارسال
تفاوت بي
برنامه،
اين
)f(a,b
فراخواني
ارسال م
ارجاع
طريق
دومي به
باعث ميشود که aاز طريق مقدار به xارسال ش777ود و
)&;void f(int,int
bاز طريق ارجاع به yفرستاده شود.
)(int main
{ ;int a = 22, b = 44
;cout << "a = " << a << ", b = " << b << endl
);f(a,b
;cout << "a = " << a << ", b = " << b << endl
);f(2*a-3,b
};cout << "a = " << a << ", b = " << b << endl
)void f(int x , int& y
a = 22, b = 44
a = 22, b = 99
{ ;x = 88
a = 22, b = 99
};y = 99
شکل زير نحوۀ کار تابع )(fرا نشان ميدهد.
هنگام فراخواني تابع )f(a,b
)(f
22
int
&int
)(main
x
a 22
int
y
b 44
int
)(f
بعد از بازگشت
)(main
xx 88
int
22
int
y
99
&int
int
a
b
در جدول زير خالصۀ تفاوتهاي بين ارسال از طريق مقدار و ارسال
از طريق ارجاع آمده است.
ارسال از طريق ارجاع
ارسال از طريق مقدار
;int& x
;int x
پارامتر xيک ارجاع است
پارامتر xيک متغير محلي است
xمترادف با آرگومان است
xيک کپي از آرگومان است
ميتواند محتويات آرگومان را تغيير دهد
تغيير محتويات آرگومان ممکن نيست
آرگومان ارسال شده از طريق ارجاع فقط بايد
يک متغير باشد
آرگومان ارسال شده از طريق مقدار ميتواند
يک ثابت ،يک متغير يا يک عبارت باشد
آرگومان خواندني-نوشتني است
آرگومان فقط خواندني است
ع م7777ورد نياز
ي ارجا
ي از م7777واقعي كه پارامترها
يك
ك مقدار را
ع بايد بيش از ي
ت كه تاب
ي اس
هستند جاي
بازگرداند.
ك مق7777دار را
دس7777تور returnفق7777ط ميتوان7777د ي
برگرداند.
ك مق77دار برگش77ت داده
ن اگر بايد بيش از ي
بنابراي
ع انجا م ميدهند.
ي ارجا
ن كار را پارامترها
شود ،اي
ك مقدار
ت بيشتر از ي
بازگش5-14 ل
* مثا
وarea :د77دار را بازميگردان77 دو مق،ق دو پارامتر ارجاع77تابع زير از طري
دد77عاع آن ع77ه ش77رهاي ک77راي داي77 (محيط و مساحت) بcircumference
: استr مفروض
void ComputeCircle(double& area, double& circumference,
double r)
returns the area and circumference of a circle with // {
:radius r
;const double PI = 3.141592653589793
;area = PI*r*r
;circumference = 2*PI*r
}
برنامۀ آزمون تابع فوق و يک اجراي آزمايشي آن در شکل زير نشان
:داده شده است
;void ComputerCircle(double&, double&, double)
returns the area and circumference of a circle with //
;radius r
)(int main
:tests the ComputeCircle() function // {
;double r, a, c
;" :cout << "Enter radius
;cin >> r
;ComputeCircle(a, c, r)
" = cout << "area = " << a << ", circumference
};c << endl <<
ارسال از طريق ارجاع ثابت 12-
ارسال پارامترها به طريق ارجاع دو خاصيت مهم دارد:
اول اين که تابع ميتواند روي آرگومان واقعي تغييراتي بدهد
دوم اين که از اشغال بيمورد حافظه جلوگيري ميشود.
روش ديگري نيز براي ارسال آرگومان وجود دارد:
ارسال از طري77ق ارجاع ث77ابت .اين روش مانن77د ارسال از طري77ق
ارجاع است با اين فرق که تابع نميتواند محتويات پارامتر ارجاع
را دستکاري نمايد و فقط اجازۀ خواندن آن را دارد.
براي اين که پارامتري را از ن77وع ارجاع ث77ابت اعالن ک77نيم باي77د
عبارت constرا به ابتداي اعالن آن اضافه نماييم.
ت
ع ثاب
ق ارجا
ل 5-15ارسال از طري
مثا
سه طريقه ارسال پارامتر در تابع زير به کار رفته است:
)void f(int x, int& y, const int& z
;{ x += z
;y += z
" = cout << "x = " << x << ", y = " << y << ", z
;<< z << endl
}
ن پارامتر يعني xاز طريق مقدار ارسال ميش777ود ،دومين
در تابع فوق اولي
پارامتر يعني yاز طريق ارجاع و سومين پارامتر نيز از طريق ارجاع ثابت.
برنامۀ آزمون و يک اجراي آزمايشي از مثال قبل:
a = 22, b = 33, c = 44
;)&void f(int, int&, const int
x = 66, y = 77, z = 44
)(int main
a = 22, b = 77, c = 44
x = 85, y = 121, z = 44
{ // tests the f() function:
a = 22, b = 121, c = 44
;int a = 22, b = 33, c = 44
" = cout << "a = " << a << ", b = " << b << ", c
ت777ابع ف777وق پارامترهاي xو yرا ميتوان777د
;<< c << endl
تغيير ده77د ولي ق77ادر نيس77ت پارامتر zرا
;)f(a,b,c
روي xbص
7يراتي cک77ه
7ورتcout << "a = " << a << ", b
<<= " 7
<< ",
تغيير ده77د .تغي= " 7
ميگ777يرد اثري روي آرگومان aنخواه777د
;<< c << endl
داشت زيرا aاز طريق مقدار به تابع ارسال
;)f(2*a-3,b,c
شده .تغييراتي که روي yصورت ميگ77يرد
زيرا=cout << "a = " << a << ", bb
<< "
<< b
هم = c
روي آرگومان " b
گذارد
تاثير",مي
;<< c << endl
از طريق ارجاع به تابع فرستاده شده.
}
ارسال به طريق ارجاع ث77ابت بيش77تر ب77راي ت77وابعي
اس77تفاده ميش77ود ک77ه عناصر ب77زرگ را وي77رايش
ميکنن777د مث777ل آرايهها يا نمون777ۀ کالسها ک777ه در
جلسههاي بعدي توضيح آنها آمده است .عناصري
که از انواع اصلي هستند (مثل intيا )floatبه طري77ق
مقدار ارسال ميشوند به شرطي که قرار نباشد ت77ابع
محتويات آنها را دستکاري کند.
توابع بيواسطه 13-
تابعي که به شکل بيواسطه تعريف ميشود ،ظاهري شبيه به توابع
معمولي دارد با اين فرق که عبارت inlineدر اعالن و تعري777ف آن
قيد شده است.
واسطه
ع )(cubeبه شکل بي
مثال 5-16تاب
ل 5-3است:
ن تابع )(cubeمثا
ن هما
اي
ي
ت ك ه كلم 7ۀ كلي77د
ت اين اس 7
تنها تفاو
inlineدر ابتداي عنوان تابع ذکر ش777ده.
ن عبارت ب ه كامپايلر ميگوي777د كه در
اي
برنام777ه ب777ه جاي ) cube(nک777د واقعي
( )n(*)n(*)nرا قرار دهد.
)inline int cube(int x
{ // returns cube of x:
;return x*x*x
}
.به برنامۀ آزمون زير نگاه کنيد:
:احتياط
)(int main
{ // tests the cube() function:
استفاده از توابع بيواسطه ميتواند اثرات منفي
;int x, y
داشته باشد .مثال اگر يک ت77ابع بيواس77طه داراي
;cin >> x
نقط77ه
26
در
ت77ابع
اين
و
باش77د
ک77د
خ77ط
40
};)y = cube(2*x-3
وجود77ام
تابعيهنگ
7ود،
گوييش7
7واني
هنگامبرنامۀ
برنامه از
مختلف
نداشته
اصال
فراخي7آيد،
اصليزير درم
کامپايل به شکل
:اين
7لي int
)(main
کامپايل بيش از هزار خط ک77د ب77ه برنام77ۀ اص7
وقتي كامپايلر کد واقعي ت77ابع
{ // tests the cube() function:
همچنين تابع بيواسطه ميتواند
افزوده ميشود.
آن
فراخ777777واني
جايگزين
را
;cout << (4) * (4) * (4) << endl
ک77ه ت77ابع
گ77وييم
ميکن77د ،مي
هاي
م
7ت
7
سيس
روي
را
7ما
7
ش
7ۀ
7
برنام
7ال
7
انتق
قابليت
;int x, y
بيواسطه ،باز ميشود.
مختلف کاهش دهد.
;cin >> x
;cout << cube(4) << endl
};)y = (2*x-3) * (2*x-3) * (2*x-3
چندشکلي توابع 14-
در ++Cميت77وانيم چن77د ت77ابع داش77ته باش77يم ک77ه
همگي يک نام دارند .در اين حالت ميگ77وييم ک77ه
ت77ابع م77ذکور ،چندش77کلي دارد .شرط اين ک77ار آن
است که فهرست پارامترهاي اين توابع با يک77ديگر
تفاوت داشته باشد .يعني تعداد پارامترها متف77اوت
باشد يا دس77ت کم يکي از پارامترهاي متن77اظر هم
نوع نباشند.
ل 5-17چندشکلي تابع )(max
مثا
ع )(maxرا تعريف کرديم .حاال توابع ديگري با همان ن77ام
در مثال 5-3تاب
ولي ش77کلي متف77اوت تعري77ف ميک77نيم و هم77ه را در ي77ک برنام77ه ب77ه ک77ار
ميگيريم:
;)int max(int, int
;)int max(int, int, int
;)int max(double, double
)(int main
<< ){ cout << max(99,77) << " " << max(55,66,33
;)" " << max(44.4,88.8
}
int max(int x, int y)
{ // returns the maximum of the two given integers:
return (x > y ? x : y);
}
int max(int x, int y, int z)
{ // returns the maximum of the three given integers:
int m = (x > y ? x : y); // m = max(x , y)
return ( z > m ? z : m);
}
int max(double x, double y)
{ // return the maximum of the two given doubles:
return (x>y ? x : y);
}
در اين برنامه سه تابع با نام )(maxتعريف شده است.
وقتي تابع )(maxدر جايي از برنامه فراخ77واني ميش77ود،
کامپايلر فهرست آرگومان آن را بررسي ميکند تا بفهمد
که کدام نسخه از maxبايد احضار شود.
مثال در اولين فراخ7777واني ت7777ابع )(maxدو آرگومان int
ارسال شده ،پس نسخهاي که دو پارامتر intدر فهرس777ت
پارامترهايش دارد فراخ77واني ميش77ود .اگر اين نس77خه
وجود نداش77ته باش77د ،کامپايلر intها را ب77ه doubleارتق77ا
ميدهد و سپس نسخهاي ک777ه دو پارامتر doubleدارد را
فرا ميخواند.
-14تابع )(main
برنامههايي که تا کنون نوشتيم هم77ه داراي ت77ابعي ب77ه ن77ام
)(mainهستند.
منطق ++Cاين طور است که هر برنامه بايد داراي ت77ابعي
به نام )(mainباشد.
در حقيقت هر برنامه کامل ،از يک تابع )(mainب777ه همراه
توابع ديگر تشکيل شده است که هر ي77ک از اين تواب77ع ب77ه
ش777کل مس777تقيم يا غ777ير مس777تقيم از درون ت777ابع )(main
فراخواني ميشوند.
خود برنامه با فراخواني تابع )(mainشروع ميشود.
چون اين تابع يک نوع بازگشتي intدارد ،منطقي است که بلوک
ت77ابع )(mainش77امل دس77تور ;return 0باش77د هرچن77د ک77ه در
برخي از کامپايلرهاي ++Cاين خط اجباري نيست و ميتوان آن
را ذکر نکرد.
مقدار صحيحي که با دستور returnبه سيستم عامل برميگردد
بايد تعداد خطاها را شمارش کند .مقدار پيشفرض آن 0اس77ت
به اين معنا که برنامه بدون خطا پايان گرفته است.
با اس777تفاده از دس777تور returnميت777وانيم برنام777ه را ب777ه ط777ور
غيرمعمول خاتمه دهيم.
ك برنام ه
ي پايان دادن ب ه ي
ل 5-18استفاد ه از دستور returnبرا
مثا
)(int main
{ // prints the quotient of two input integers:
دستور returnتابع فعلي را خاتمه ميدهد و کن77ترل را ب77ه
فراخواننده بازميگرداند .به همين دليل اس77ت ک77ه اج77راي
cout << "Enter two
integers:
خاتم77ه
دس77تور returnدر ت77ابع )(mainک77ل;"برنام77ه را
ميدهد.
;int n, d
;cin >> n >> d
;if (d = = 0) return 0
;cout << n << "/" << d << " = " << n/d << endl
}
Enter two integers: 99 17
99/17 = 5
چهار روش وجود دارد که بتوانيم برنامه را ب77ه ش77کل غ77يرمعمول
(يعني قبل از اين که اج77را ب77ه پايان بل77وک اص77لي برس77د) خاتم77ه
دهيم:
- 1استفاده از دستور return
- 2فراخواني تابع )(exit
- 3فراخواني تابع )(abort
– 4ايجاد يک حالت استثنا
اين ت77777777777ابع در سرفايل
< >cstdlibتعري777ف ش777ده
است .تابع )(exitبراي خاتم77ه
دادن ب77ه ک77ل برنام77ه در هر
ت77ابعي غ77ير از ت77ابع )(main
مفيد است.
() براي پايان دادن به برنامهexit استفاده از تابع5-19 مثال
#include <cstdlib>
// defines the exit() function
#include <iostream>
// defines thi cin and cout objects
using namespace std;
double reciprocal(double x);
int main()
{ double x;
cin >> x;
را0 دد77دراين برنامۀ اگر كاربر ع
() خاتمهreciprocal تابع،وارد کند
دار77دون هيچ مق77ه ب77مييابد و برنام
چاپي به پايان ميرسد
cout << reciprocal(x);
}
double reciprocal(double x)1 – Exception
{ // returns the reciprocal of x:
if (x = = 0) exit(1);
return 1.0/x; }
// terminate the program
آرگومانهاي پيشفرض 15-
در ++Cميتوان تعداد آرگومانهاي يک تابع را در زمان اجرا ب77ه
دلخواه تغيير داد.
اين امر با استفاده از آرگومانهاي اختياري و مق777ادير پيشفرض
امکانپذير است.
براي اين که به يک پارامتر مقدار پيشفرض ب77دهيم باي77د آن مق77دار را در
فهرست پارامترهاي تابع و جلوي پارامتر مربوطه به همراه عالمت مساوي
درج کنيم .به اين ترتيب اگر هنگام فراخواني ت7777ابع ،آن آرگومان را ذکر
نکنيم ،مقدار پيشفرض آن در محاسبات تابع اس77تفاده ميش77ود .ب77ه همين
خاطر به اين گونه آرگومانها ،آرگومان اختياري ميگويند.
double p(double, double, double=0,ض
double=0);
double=0,
هايپيشفر
آرگومان5-20 ل
مثا
int main()
براي محاسبۀ.برنامۀ زير حاصل چند جملهاي درجه سوم را پيدا ميکند
{ // tests the p() function:
به اين شکل که براي کارايي.اين مقدار از الگوريتم هورنر استفاده شده
double x = 2.0003;
: دستهبندي ميشودa0 (a1 (a2 a3x)x)x محاسبه به صورت،بيشتر
cout << "p(x,7) = " << p(x,7) << endl;
cout << "p(x,7,6) = " << p(x,7,6) << endl;
cout << "p(x,7,6,5) = " << p(x,7,6,5) << endl;
cout << "p(x,7,6,5,4) = " << p(x,7,6,5,4) << endl;
}
double p(double x, double a0, double a1=0, double a2=0, double
a3=0)
{ // returns a0 + a1*x + a2*x^2 + a3*x^3:
return a0 + (a1 + (a2 + a3*x)*x)*x;
}
p(x,7) = 7
p(x,7,6) = 19.0018
p(x,7,6,5)
Default
=
39.00781
p(x,7,6,5,4) = 71.0222
–
دقت کنيد که پارامترهايي ک77ه مق77دار پيشفرض دارن77د باي77د در فهرس77ت
پارامترهاي تابع بعد از همۀ پارامترهاي اجباري قيد شوند مثل:
// OK
;)void f( int a, int b, int c=4, int d=7, int e=3
// ERROR
;)void g(int a, int b=2, int c=4, int d, int e=3
همچنين هنگام فراخواني تابع ،آرگومانهاي ذکر شده به ترتيب از چپ ب77ه
راس77ت تخص77يص مييابن77د و پارامترهاي بع77دي با مق77دار پيشفرض پ77ر
ميشوند.
مثال در ت77ابع )(pک77ه در باال قي77د ش77د ،فراخ77واني ) p(8.0,7,6باعث
ميشود که پارامتر xمق777دار 8.0را بگ777يرد سپس پارامتر a0مق777دار 7را
بگيرد و سپس پارامتر a1مقدار 6را بگيرد .پارامترهاي a2و a3مق777دار
پيشفرضشان را خواهند داشت .اين ترتيب را نميتوانيم به هم بزنيم .مثال
نميتوانيم تابع را طوري فرا بخوانيم که پارامترهاي xو a0و a3مستقيما
مق77دار بگيرن77د ولي پارامترهاي a1و a2مق77دار پيشفرضش77ان را داش77ته
باشند.
پايان جلسه پنجم
جلسه ششم
«آرايهها»
:آنچه در اين جلسه مي خوانيد
ش آرايهها
-1پرداز
-2مقداردهي آرايهه ا
-3ايندكس بيرون از حدود آرايه
-4ارسال آرايه به تابع
-5الگوريتم جستجوي خطي
-6مرتبسازي حبابي
-7الگوريتم جستجوي دودويي
›››
-8استفاده از انواع شمارشي در آرايه
ف انواع
-9تعري
- 10آرايههاي چند بعدي
هدف کلي:
هدفهاي رفتاري:
انتظار ميرود پس از پايان اين جلسه بتوانيد:
شناخت و معرفي آرايهها و مزيت و طريقۀ بهکارگيري
بتوانيد آنها را در برنامهها ب777ه ک777ار
-علت استفاده از آرايهها را بدانيدآونها
ببريد.
آرايههاي «يکبعدي» و «چندبعدي» را تعريف کنيد. مفهوم «ايندکس» را بدانيد و خطاي «اثر همسايگي» را تعريف و شناساييکنيد.
طريقۀ ارسال آرايه به توابع را بدانيد. «جستجوي خطي» و «جستجوي دودويي» را به اختصار شرح دهيد.« -مرتبسازي حبابي» را به اختصار شرح دهيد.
مقدمه:
در برنامههايي که دادههاي فراواني را پ77ردازش ميکنن77د
استفاده از متغيرهاي معمولي کار عاقالنهاي نيس77ت زي77را
در بسياري از اين برنامهها «پ77ردازش دس77تهاي» ص77ورت
ميگيرد به اين معني که مجموعهاي از دادههاي مرتبط با
کردپ7ک ه
تصور
متغيري
حافظه را م
هم در آرايه
7ردازش ،ک77ل
پس از
7ود و
توان ميش7
قراريداده
مجموعۀ بعدي در
شود و
وليخارج
حافظه
را به طور
چندينميمقدار
مجموعهنامازدارد
اين يک
قرار باشد براي اين ک77ار از
اگر
شود.
ي
م
بارگذاري
حافظه
همزمان نگهداري مينمايد.
متغيرهاي معمولي استفاده شود بيشتر وقت برنامهنويس
صرف پر و خالي کردن انب77وهي از متغيرها ميش77ود .ب77ه
همين دليل در بيش777تر زبانهاي برنامهنويس777ي «آرايهها»
تدارک ديده شدهاند.
يک آرايه ،يك زنجيره از متغيرهايي اس77ت كه هم77ه از
يك نوع هستند.
به اين متغيرها «اعضاي آرايه» ميگويند.
هر عضو آرايه با يک شماره مشخص ميشود که به اين
شماره «ايندکس» يا «زيرنويس» ميگويند
عناصر يک آرايه در خانههاي پش777ت سر هم در حافظ777ه
ذخيره ميشوند .به اين ترتيب آرايه را ميتوان بخشي از
حافظ77ه تص77ور کرد ک77ه اين بخش خ77ود ب77ه قس77متهاي
مساوي تقسيم شده و هر قس77مت ب77ه ي77ک عنصر تعل77ق
دارد.
شکل مقابل آرايۀ aکه پنج عنصر دارد را نشان ميدهد.
عنصر ] a[0حاوي مق777777دار 17.5و عنصر ] a[1حاوي 19.0و عنصر
] a[4حاوي مقدار 18.0است.
17.50
19.00
16.75
15.00
18.00
0
1
2
3
4
پردازش آرايهها 2-
مثال 6-1دستيابي مستقيم به عناصر آرايه
برنامۀ سادۀ زير يک آرايۀ سه عنصري را تعريف ميکند و سپس مقاديري را در
را چاپ ميکند:
مقادير
ي اين
سرانجام
داده
آن قرار
متغيرهاي معمولي تعريف و
مثل
توان
هاو را م
آرايه
7يرint
)(main
استفاده کرد .با اين تف77اوت ک77ه آراي77ه ي77ک متغ7
;]{ int a[3
مرکب است و براي دستيابي به هر يک از خانههاي
;a[2] = 55
نمود.
استفاده
ايندکس
از
بايد
آن
;a[0] = 11
;a[1] = 33
;cout << "a[0] = " << a[0] << endl
a[0] = 11
;cout << "a[1] = " << a[1] << andl
a[1] = 33
;cout << "a[2] = " << a[2] << endl
a[2] = 55
}
نحو کلي براي اعالن آرايه به شکل زير است:
;]type array_name[array_size
عبارت typeن77وع عناصر آراي77ه را مش77خص ميکن77د.
array_nameنام آرايه است .
array_sizeتعداد عناصر آراي77ه را نش77ان ميده77د.
اين مقدار بايد يک ع77دد ث77ابت ص77حيح باش77د و حتما
بايد داخل کروشه [] قرار بگيرد.
-3مقداردهي آرايهها
در ++Cميتوانيم يک آرايه را با استفاده از فهرست مقداردهي ،اعالن و مقدارگ77ذاري
کنيم:
;}float a[] = {22.2,44.4,66.6
به اين ترتيب مقادير داخل فهرست به همان ترتي77بي ک77ه چي77ده
شدهاند درون عناصر آرايه قرار ميگيرند .اندازه آرايه نيز براب77ر
با تعداد عناصر موجود در فهرست خواهد بود.
پس همين خط مختصر ،آرايهاي از نوع floatو با نام aو با تعداد
سه عنصر اعالن کرده و هر س7777ه عنصر را با مق7777دارهاي درون
a
فهرست ،مقداردهي ميکند.
0 22.2
1 44.4
2 66.6
مثال 6-3مقداردهي آرايه با استفاده از فهرست مقداردهي
برنامۀ زير ،آرايۀ aرا مقداردهي کرده و سپس مقدار هر عنصر را چاپ ميكند:
)(int main
;} { float a[] = { 22.2, 44.4, 66.6
;)int size = sizeof(a)/sizeof(float
)for (int i=0; i<size; i++
<< ]cout << "\ta[" << i << "] = " << a[i
;endl
}
a[0] = 22.2
a[1] = 44.4
a[2] = 66.6
هنگام استفاده از فهرس77ت مق77داردهي ب77راي اعالن آراي77ه،
ميتوانيم تعداد عناصر آراي77ه را هم ب77ه ط77ور صريح ذکر
کنيم .در اين صورت اگر تعداد عناصر ذکر شده از تع77داد
عناصر موج777ود در فهرس777ت مق777داردهي بيش777تر باش777د،
خانههاي بعدي با مقدار صفر پر ميشوند:
;} float a[7] = { 55.5, 66.6, 77.7
دقت کنيد که تعداد مقادير موجود در فهرست
مقداردهي نبايد از تعداد عناصر آراي77ه بيش77تر
باشد:
ERROR: too many
float a[3] = { 22.2, 44.4, 66.6, 88.8 }; //
!values
a
55.
5
0
66.
6
1
77.
7
2
3 0.0
4 0.0
يك آرايه را ميتوانيم به طور کامل با صفر مق77داردهي اولي77ه ک77نيم.
براي مثال سه اعالن زير با هم برابرند:
;} float a[ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0
;} float a[9] = { 0, 0
;} float a[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0
اما مطلب فوق اصال به اين معني نيس77ت ک77ه از فهرس77ت مق77داردهي
استفاده نشود.
درست مثل يک متغير معمولي ،اگر ي77ک آراي77ه مق77داردهي اولي77ه
نشود ،عناصر آن حاوي مقادير زباله خواهد بود.
يك آرايۀ مقداردهي نشده6-5 مثال
ود77 با وج.د77داردهي نميكن77 را اعالن ميکند ولي مقa آراي ۀ،برنامۀ زير
: مقادير موجود در آن را چاپ ميكند،اين
int main()
{
const int SIZE=4; // defines the size N for 4
elements
float a[SIZE];
// declares the array's elements as
float
for (int i=0; i<SIZE; i++)
cout << "\ta[" << i << "] = " << a[i] <<
endl;
a[0]
a[1]
a[2]
a[3]
= 6.01838e-39
}= 9.36651e-39
= 6.00363e-39
=0
آرايهها را ميتوان با استفاده از عملگر جايگزيني مق777داردهي
:کرد اما نميتوان مقدار آنها را به يکديگر تخصيص داد
;} float a[7] = { 22.2, 44.4, 66.6
;} float b[7] = { 33.3, 55.5, 77.7
!b = a; // ERROR: arrays cannot be assigned
همچ77نين نميت77وانيم يك آراي77ه را ب77ه ط77ور مس77تقيم ب77راي
مقداردهي به آرايۀ ديگر استفاده كنيم:
;} float a[7] = { 22.2, 44.4, 66.6
!float b[7] = a; // ERROR: arrays cannot be used as nitializers
-4ايندكس بيرون از حدود آرايه
در بعض777ي از زبانهاي برنامهنويس777ي ،اين777دکس آراي777ه
نميتواند از محدودۀ تعريف شده براي آن بيش77تر باش77د.
براي مثال در پاسکال اگر آراي777ۀ aبا تع777داد پنج عنصر
تعريف شده باشد و آنگاه ] a[7دستيابي شود ،برنامه از
کار ميافتد .اين سيستم حف77اظتي در ++Cوج77ود ن77دارد.
مثال بعدي نشان ميدهد که ايندکس ي77ک آراي77ه هنگ77ام
دستيابي ميتواند بيشتر از عناصر تعريف ش77ده ب77راي آن
باشد و باز هم بدون اين که خطايي گرفت77ه ش77ود ،برنام77ه
ادامه يابد.
مثال 6-6تجاوز ايندکس آرايه از محدودۀ تعريف شده براي آن
برنامۀ زير يک خطاي زمان اجرا دارد؛ به بخشي از حافظه دس77تيابي ميکن77د
که از محدودۀ آرايه بيرون است:
)(in main
;{ const int SIZE=4
float a[SIZE} = { 33.3, 44.4, 55.5,
چهار
آرايهاي ک77ه در اين برنام77ه تعري77ف ;}ش77ده،
66.6
a[0] = 33.3عنصر دارد ولي تالش ميش7777ود ب7777ه هفت عنصر
ج77زوfor
;(int i=0
مق77دار;i<7
س77ه )i++
!//ERROR: index is out of bounds
آراي77ه
آخر واقعا
a[1] = 44.4دستيابي شود.
a[2] = 55.5
دقيقا بعد
"["\taهاند
هايي iاز<<حافظ
نيستند و
<<کهcout
سلو=ل ]" <<
فقط<< "
<< ]a[i
;endl
a[3] = 66.6
a[4] = 5.60519e-45از عنصر چهارم آرايه قرار گرفتهان77د .اين س77لولها
a[5] = 6.01888e-39
}
a[6] = 6.01889e-39داراي مقدار زباله هستند.
* مثال 6-7اثر همسايگي
برنامۀ زير از ايندکس خارج از محدوده استفاده ميکند و اين باعث ميشود که مق77دار ي77ک
متغير به طور ناخواسته تغيير کند:
)(int main
;{ const int SIZE=4
;} float a[] = { 22.2, 44.4, 66.6
;float x=11.1
;cout << "x = " << x << endl
!a[3] = 88.8; // ERROR: index is out of bounds
;cout << "x = " << x << endl
}
x = 88.8
متغير xبعد از آراي77ۀ aاعالن ش77ده ،پس ي77ک س77لول چهاربايتي
بالفاص77له بع77د از دوازده بايت آراي77ه ب77ه آن تخص77يص ميياب77د.
بنابراين وقتي برنامه تالش ميکند مقدار 88.8را در ] a[3قرار
دهد (که جزو آرايه نيس77ت) اين مق77دار ب77ه ش77کل ناخواس77ته در x
قرار ميگ77يرد .ش77کل مقاب77ل نش77ان ميده77د چط77ور اين اتف77اق در
دهد.
ي
م
رخ
حافظه
مثال بعدي نوع ديگري از خطاي زمان اجرا را نشان
خطاهاي
ترين
ک
نا
ت
وحش777
از
يکي
خط777ا
اين
بيش از حد بزرگ aباشد
آرايه
ايندکس
وقتي
دهد:
ي
م
.
زمان اجراست زيرا ممکن است اص77ال نت77وانيم
22.2 0
منبع خطا را کشف کنيم .حتي ممکن است ب77ه
44.4 1
اين روش دادههاي برنامههاي ديگري ک77ه در
66.6 2
حال کارند را خراب کنيم و اين باعث ايجاد
اختالل در کل سيستم شود .ب77ه اين خط77ا «اثر
x 88.8
همسايگي» ميگويند .اين وظيفۀ برن77امهنويس
است که تضمين کند ايندکس آراي77ه هيچگ77اه
از محدودۀ آن خارج نشود.
22.2
44.4
66.6
88.8
ايجاد استثناي مديريت نشده6-8 مثال
:برنامۀ زير از كار ميافتد زيرا ايندكس آرايه خيلي بزرگ است
int main()
{ const int SIZE=4;
float a[] = { 22.2, 44.4, 66.6 };
float x=11.1;
cout << "x = " << x << endl;
a[3333] =88.8;//ERROR: index is out of bounds!
cout << "x = " << x << endl;
}
وقتي اين برنامه روي رايانهاي با سيس77تم عام77ل وين77دوز
اجرا شود ،يک صفحۀ هشدار که در شکل نشان داده شده
روي صفحه ظاهر ميشود.
اين پنجره بيان ميکن77د ک77ه برنام77ه تالش دارد ب77ه نش77اني
0040108eاز حافظه دستيابي کند .اين مکان خارج از
حافظۀ تخصيصي است که ب77راي اين برنام77ه منظ77ور ش77ده،
بنابراين سيستم عامل برنامه را متوقف ميکند.
پردازشگر استثنا
خطايي که در مثال 6-8بيان شده يک «استثناي مديريت
نشده» ناميده ميشود زيرا کدي وجود ن77دارد ک77ه ب77ه اين
استثنا پاسخ دهد.
در ++Cميتوانيم ک77دهايي ب77ه برنام77ه اض77افه ک77نيم ک77ه
هنگ777ام رخ دادن حالتهاي اس777تثنا ،از توق777ف برنام777ه
جلوگ777يري کن777د .ب777ه اين ک777دها «پردازشگر اس777تثنا»
ميگويند.
ارسال آرايه به تابع 5-
كد ;][float aكه آراي77ه aرا اعالن ميكن77د دو چ77يز را ب77ه
كامپايلر ميگويد:
-1اين که نام آرايه aاست
-2عناصر آرايه از نوع floatهستند.
سمبل aنشاني حافظۀ آرايه را ذخيره ميکند .الزم نيست تع77داد
عناصر آرايه به کامپايلر گفته شود زيرا از روي نشاني موج77ود در
aميتوان عناصر را بازيابي نمود .ب77ه همين طري77ق ميت77وان ي77ک
آرايه را به تابع ارسال کرد .يعني فقط نوع آرايه و نش77اني حافظ77ۀ
آن به عنوان پارامتر به تابع فرستاده ميشود.
ل 6-9ارسال آرايه به تابعي كه مجموع عناصر آرايه را برميگرداند
مثا
;)int sum(int[],int
)(int main
;} { int a[] = { 11, 33, 55, 77
;)int size = sizeof(a)/sizeof(int
};cout << "sum(a,size) = " << sum(a,size) << endl
فهرست پارامتر تابع ف77وق ب77ه ش77کل (int a[], int
)nاست به اين معنا ک7ه اين ت7ابع ي7ک آراي7ه از ن7وع
intو يک متغير از نوع intدريافت ميکند.
ب7777ه اعالن اين ت7777ابع در باالي ت7777ابع
)(mainنگ77اه کني77د .ن77ام پارامترها
حذف شده است.
)int sum(int a[], int n
;{ int sum=0
)for (int i=0; i<n; i++
;]sum += a[i
;return sum
}
هنگ77ام فراخ77واني ت77ابع ن77يز از عبارت )sum(a,size
استفاده شده که فقط نام آرايه به تابع ارسال شده.
ن77ام آراي77ه در حقيقت نش77اني اولين عنصر آراي77ه اس77ت (يع77ني
])a[0
تابع از اين نشاني براي دستيابي به عناصر آراي77ه اس77تفاده
ميکند .همچنين تابع ميتواند با اس77تفاده از اين نش77اني،
محتويات عناصر آرايه را دستکاري کند.
پس ارسال آرايه به تابع شبيه ارسال متغير به طريق
.ارجاع است .به مثال بعدي دقت کنيد
ه7777ک آراي7777راي ي7777ع ورودي و خروجي ب7777 تواب6-10 ل
ا7777مث
ل77ه داخ77() استفاده ميشود تا مقاديري بread در اين برنامه از تابع
() مقادير داخل آرايهprint سپس با استفاده از تابع.آرايه وارد شود
:چاپ ميشوند
void read(int[],int&;)
void print(int[],int);
int main()
{ const int MAXSIZE=100;
Enter integers. Terminate with 0:
a[0]: 11
a[1]: 22
a[2]: 33
a[3]: 44
int a[MAXSIZE]={0}, size; a[4]: 0
read(a,size);
The array has 4 elements: 11 22
33 44
cout << "The array has " << size << " elements: ";
print(a,size);
void read(int a[], int& n)
{
cout << "Enter integers. Terminate with
0:\n";
n = 0;
do
{ cout << "a[" << n << "]: ";
cin >> a[n];
{ while (a[n++] !=0 && n < MAXSIZE);
--n; // don't count the 0
}
)void print(int a[], int n
){ for (int i=0; i<n; i++
;" " << ]cout << a[i
}
چون nيك متغير است ،براي اين ک77ه ت77ابع )(readبتوان77د
مقدار آن را تغيير دهد اين متغير بايد به شکل ارجاع ارسال
شود.
همچنين براي اين که تابع مذکور بتواند مقادير داخل آراي77ه
aرا تغيير دهد ،آرايه نيز بايد به طريق ارجاع ارسال ش7777ود،
اما ارجاع آرايهها کمي متفاوت است.
در ++Cتوابع قادر نيستند تعداد عناصر آراي77ۀ ارسالي را تش77خيص دهن77د.
بنابراين به منظور ارسال آرايهها به تابع از سه مشخصه استفاده ميشود:
– 1آدرس اولين خانۀ آرايه
– 2تعداد عناصر آرايه
– 3نوع عناصر آرايه
تابع با استفاده از اين سه عنصر ميتوان77د ب77ه ت77ک ت77ک
اعضاي آرايه دستيابي کند.
آدرس اولين خانۀ آرايه ،همان نام آرايه است.
پس وقتي نام آرايه را به تابع بفرستيم آدرس اولين خان77ه
را به تابع فرستادهايم.
نوع آرايه نيز در تعريف تابع اعالن ميشود.
بنابراين با اين دو مقدار ،تابع ميتواند به آرايه دسترسي
داشته باشد.
مثال 6-11آدرس اولين خانۀ آرايه و مقدار درون آن
برنامۀ زير ،آدرس ذخيره ش77ده در ن77ام آراي77ه و مق77دار موج77ود در آن خان77ه را چاپ
ميکند:
a = 0x0064fdec
)(int main
a[0] = 22
;} { int a[] = { 22, 44, 66, 88
// the address of
;cout << "a = " << a << endl
]a[0
]// the value of a[0
;]cout << "a[0] = " << a[0
}
اين برنامه تالش ميکند که به طور مستقيم مقدار aرا چاپ کن77د .نتيج77ۀ
چاپ aاين است که يک آدرس به شکل شانزده دهي چاپ ميش77ود .اين
همان آدرس اولين خانۀ آرايه است .يعني درون نام aآدرس اولين عنصر
آرايه قرار گرفته .خروجي نيز نشان ميدهد ک777ه aآدرس اولين عنصر را
دارد و ] a[0مقدار اولين عنصر را.
-6الگوريتم جستجوي خطي
آرايهها بيشتر براي پردازش ي77ک زنج77يره از دادهها ب77ه
کار ميروند.
اغلب الزم است که بررسي شود آيا ي77ک مق77دار خ77اص
درون يک آرايه موجود است يا خير .سادهترين راه اين
است که از اولين عنصر آراي777ه شروع ک777نيم و يکي يکي
همۀ عناصر آرايه را جستجو نماييم ت77ا بفهميم ک77ه مق77دار
م777ورد نظر در ک777دام عنصر قرار گرفته .ب777ه اين روش
«جستجوي خطي» ميگويند.
جستجوي خطي6-12 مثال
راي77تجوي خطي ب77ابع از روش جس77ه در اين ت77د ک77برنامۀ زير تابعي را آزمايش ميکن
:يافتن يک مقدار خاص استفاده شده
int index(int,int[],int);
int main()
{ int a[] = { 22, 44, 66, 88, 44, 66, 55};
cout << "index(44,a,7) = " << index(44,a,7) <<
endl;
cout << "index(50,a,7) = " << index(50,a,7) <<
endl;
}
int index(int x, int a[], int n)
{ for (int i=0; i<n; i++)
if (a[i] == x) return i; index(44,a,7) = 1
return n; // x not found index(40,a,7) = 7
تابع )(indexسه پارامتر دارد:
.1
پارامتر xمقداري است که قرار است جستجو شود،
.2پارامتر aآرايهاي است که بايد در آن جستجو صورت گيرد
.3و پارامتر nهم ايندکس عنصري است که مقدار مورد نظر در
آن پيدا شده است.
در اين تابع با اس77تفاده از حلق77ۀ forعناصر آراي77ه aپيمايش
شده و مقدار هر عنصر با xمقايسه ميشود .اگر اين مقدار با
xبراب77ر باش77د ،اين77دکس آن عنصر بازگردان77ده ش77ده و ت77ابع
خاتمه مييابد.
اگر مقدار xدر هيچ ي77ک از عناصر آراي77ه موج77ود نباش77د،
مقداري خارج از ايندکس آرايه بازگردانده ميشود ک77ه ب77ه
اين معناست که مقدار xدر آرايۀ aموجود نيست.
در اولين اجراي آزمايشي ،مشخص شده ک77ه مق77دار 44در
] a[1واقع است و در اجراي آزمايشي دوم مشخص ش77ده
که مقدار 40در آرايۀ aموجود نيست (يعني مقدار 44در
] a[7واقع است و از آنجا ک77ه آراي77ۀ aفق77ط ت77ا ]a[6
عنصر دارد ،مقدار 7نشان ميدهد که 40در آرايه موج77ود
نيست).
مرتبسازي حبابي 7-
«مرتبسازي حبابي» يکي از سادهترين الگوريتمهاي مرتبسازي
است.
در اين روش ،آرايه چندين مرتبه پ77ويش ميش77ود و
در هر مرتبه بزرگترين عنصر موجود به سمت باال
هدايت ميشود و سپس محدودۀ مرتبسازي ب777راي
مرتبۀ بعدي يکي کاسته ميشود.
در پايان همۀ پويشها ،آرايه مرتب شده است.
طريقۀ يافتن بزرگترين عنصر و انتقال آن به باالي عناصر ديگر به اين شکل است
.1
اولين عنصر آرايه با عنصر دوم مقايسه ميشود.
.2
اگر عنصر اول بزرگتر بود ،جاي اين دو با هم عوض ميشود.
.3
سپس عنصر دوم با عنصر سوم مقايسه ميشود.
.4
اگر عنصر دوم بزرگتر بود ،جاي اين دو با هم عوض ميشود
و به همين ترتيب مقايسه و جابجايي زوجهاي همسايه ادامه مييابد تا وقتي ب777ه انتهاي
آرايه رسيديم ،بزرگترين عضو آرايه در خانۀ انتهايي قرار خواهد گرفت.
در اين حالت محدودۀ جستجو يکي کاسته ميشود
و دوباره زوجهاي کناري يکي يکي مقايسه ميشوند تا عدد بزرگتر بعدي
به مکان باالي محدوده منتقل شود .اين پويش ادام7ه ميياب7د ت7ا اين ک7ه
وقتي محدوده جستجو به عنصر اول محدود شد ،آرايه مرتب شده است.
مثال 6-13مرتبسازي
برنامۀ زير تابعي را آزمايش ميکند که اين ت777ابع با اس777تفاده از مرتبسازي
حبابي يک آرايه را مرتب مينمايد:
;)void print(float[],int
;)void sort(float[],int
)(int main
;}{float a[]={55.5,22.2,99.9,66.6,44.4,88.8,33.3, 77.7
;)print(a,8
;)sort(a,8
;)print(a,8
}
55.5, 22.2, 99.9, 66.6, 44.4, 88.8, 33.3, 77.7
22.2, 33.3, 44.4, 55.5, 66.6, 77.7, 88.8, 99.9
void sort(float a[], int n)
{ // bubble sort:
for (int i=1; i<n; i++)
// bubble up max{a[0..n-i]}:
for (int j=0; j<n-i; j++)
if (a[j] > a[j+1]) swap (a[j],a[j+1]);
//INVARIANT: a[n-1-i..n-1] is sorted
}
تابع )(sortاز دو حلقۀ تودرتو استفاده ميكند.
-1حلقه forداخلي زوجهاي همسايه را با هم مقايس7777ه
ميكند و اگر آنها خارج از ترتيب باشند ،جاي آن دو را
با هم عوض ميکند.
وق777تي forداخلي ب777ه پايان رس777يد ،بزرگترين عنصر
موجود در محدودۀ فعلي به انتهاي آن هدايت شده است.
-2سپس حلقۀ forبيروني محدودۀ جس77تجو را يکي کم
ميکن77777د و دوباره forداخلي را راه ميان77777دازد ت77777ا
بزرگترين عنصر بعدي ب77ه س77مت باالي آراي77ه ه77دايت
شود.
-8الگوريتم جستجوي دودويي
در روش جستجوي دودويي به يک آرايۀ مرتب نياز است.
هنگ77ام جس77تجو آراي77ه از وس77ط ب77ه دو بخش بااليي و
پاييني تقسيم ميشود.
مق777دار م777ورد جس777تجو با آخرين عنصر بخش پاييني
مقايسه ميشود.
اگر اين عنصر کوچکتر از مق77دار جس77تجو ب77ود ،م77ورد
جس77تجو در بخش پاييني وج77ود ن77دارد و باي77د در بخش
بااليي به دنبال آن گشت.
دوباره بخش بااليي به دو بخش تقسيم ميگردد و
گامهاي باال تکرار ميشود.
سرانجام محدودۀ جستجو به يک عنصر محدود
ميشود که يا آن عنصر با مورد جستجو برابر است
و عنصر مذکور يافت شده و يا اين که آن عنصر با
مورد جستجو برابر نيست و لذا مورد جستجو در
آرايه وجود ندارد.
اين روش پيچيدهتر از روش جستجوي خطي است
اما در عوض بسيار سريعتر به جواب ميرسيم.
ل 6-14جستجوي دودويي
مثا
برنامۀ آزمون زير با برنامۀ آزمون مثال 6-12يکي است اما ت77ابعي ک77ه در
زي77ر آم77ده از روش جس77تجوي دودويي ب77راي يافتن مق77دار درون آراي77ه
استفاده ميکند:
;)int index(int, int[],int
)(int main
;} { int a[] = { 22, 33, 44, 55, 66, 77, 88
<< )cout << "index(44,a,7) = " << index(44,a,7
;endl
<< )cout << "index(60,a,7) = " << index(60,a,7
;endl
}
int index(int x, int a[], int n)
{ // PRECONDITION: a[0] <= a[1] <= ... <=
a[n-1];
// binary search:
int lo=0, hi=n-1, i;
while (lo <= hi)
{ i = (lo + hi)/2;
// the average of lo and hi
if (a[i] == x) return i;
if (a[i] < x) lo = i+1;
a[i+1..hi]
else hi = i-1;
// continue search in
// continue search in a[0..i-1]
}
index(44,a,7) = 2
return n;
index(60,a,7) = 7
// x was not found in a[0..n-1]
ب77راي اين ک77ه بفهميم ت77ابع چط77ور ک77ار ميکن77د ،فراخ77واني
) index(44,a,7را دنبال ميکنيم.
وقتي حلقه شروع ميشود x=44 ،و n=7و lo=0و hi=6
است.
ابتدا iمقدار ( 3 = 2/)6+0را ميگ7777يرد.پس عنصر ] a[iعنصر
وسط آرايۀ ] a[0..6است .مقدار ] a[3برابر با 55است که از
مقدار xبزرگتر است .پس xدر نيمۀ بااليي نيس77ت و جس77تجو
در نيمۀ پاييني ادامه ميياب77د .ل77ذا hiبا i-1يع77ني 2مق77داردهي
ميشود و حلقه تکرار ميگردد.
حاال hi=2و lo=0است و دوباره عنصر وس777ط آراي777ۀ
] a[0..2يعني ] a[1با xمقايسه ميشود a[1] .براب77ر
با 33است که کوچکتر از xميباشد .پس اين دفع77ه lo
برابر با i+1يعني 2ميشود.
در سومين دور حلقه hi=2 ،و lo=2است .پس عنصر
وسط آرايۀ ] a[2..2که همان ] a[2است با xمقايس777ه
ميشود a[2] .برابر با 44است که با xبرابر است .پس
مق77دار 2بازگش77ت داده ميش77ود؛ يع77ني xم77ورد نظر در
] a[2وجود دارد.
lo
0
2
hi
6
i
3
a[i]
55
??
>
x
44
2
1
33
<
44
2
44
==
44
حال فراخ777واني ) index(60,a,7را دنبال ميک777نيم.
وقتي حلقه شروع ميش77ود x=60 ،و n=7و lo=0و
hi=6اس7777ت .عنصر وس7777ط آراي7777ۀ ] a[0..6عنصر
a[3]=55است که از xکوچکتر است .پس loبرابر
با i+1=4ميشود و حلق777ه دوباره تکرار ميش777ود .اين
دفع777ه hi=6و lo=4اس777ت .عنصر وس777ط آراي777ۀ
] a[4..6عنصر a[5]=77اس777ت ک777ه بزرگتر از x
ميباشد .پس hiبه i-1=4تغيير مييابد و دوباره حلق77ه
تکرار ميش777ود .اين بار hi=4و lo=4اس777ت و عنصر
وس777ط آراي777ۀ ] a[4..4عنصر a[4]=66اس777ت ک777ه
بزرگتر از xميباش77د .ل77ذا hiب77ه i-1=3ک77اهش
x
??
]a[i
i
hi
lo
60
<
55
3
6
0
60
>
77
5
60
>
66
4
4
4
اکنون شرط حلقه غلط ميش77ود زي77را hi<lo
اس77ت .بن77ابراين ت77ابع مق77دار 7را برميگردان77د
يعني عنصر مورد نظر در آرايه موجود نيست.
در تابع فوق هر بار ک77ه حلق77ه تکرار ميش77ود ،مح77دودۀ
جستجو %50کوچکتر ميش77ود .در آراي77ۀ nعنصري،
روش جس77تجوي دودويي ح77داکثر ب77ه log2 n 1مقايس77ه
نياز دارد تا به پاسخ برسد.
حال آن که در روش جستجوي خطي ب77ه nمقايس77ه نياز
است.
تفاوتهاي جستجوي دودويي و خطي
جستجوي دودويي سريعتر از جستجوي خطي است.
دومين تفاوت در اين است که اگر چن777د عنصر داراي
مقادير يکساني باشند ،آنگ77اه جس77تجوي خطي هميش77ه
ک77وچکترين اين77دکس را برميگردان77د ولي در م77ورد
جستجوي دودويي نميت77وان گفت ک77ه ک77دام اين77دکس
بازگردانده ميشود.
سومين فرق در اين است که جس77تجوي دودويي فق77ط
روي آرايههاي مرتب ک77777777ارايي دارد و اگر آرايهاي
مرتب نباشد ،جس77تجوي دودويي پاسخ غل77ط ميده77د
ولي جستجوي خطي هميشه پاسخ صحيح خواهد داد.
* مثال 6-15مشخص كردن اين كه آيا آرايه مرتب است يا خير
برنامۀ زير يک تابع بولي را آزمايش ميکند .اين تابع مشخص مينمايد که آيا آرايۀ
داده شده غير نزولي است يا خير:
;)bool isNondecreasing(int a[], int n
)(int main
;} { int a[] = { 22, 44, 66, 88, 44, 66, 55
;cout<<"isNondecreasing(a,4) = " << isNondecreasing(a,4)<< endl
;cout<<"isNondecreasing(a,7) = " << isNondecreasing(a,7) << endl
}
bool isNondecreasing(int a[], int n)
{
// returns true iff a[0] <= a[1] <= ... <=
a[n-1]:
for (int i=1; i<n; i++)
if (a[i]<a[i-1]) return false;
return true;
}
isNondecreasing(a,4) = 1
isNondecreasing(a,7) = 0
اين تابع يک بار کل آراي77777ه را پيمايش کرده و زوجهاي
] a[i-1و ] a[iرا مقايسه ميکند.
اگر زوجي يافت ش77ود ک77ه در آن ] a[i]<a[i-1باش77د،
مق77دار falseرا ب77ر ميگردان77د ب77ه اين مع77ني ک77ه آراي77ه
مرتب نيست.
ببينيد که مقادير trueو falseبه ش77کل اع77داد 1و 0
در خروجي چاپ ميشوند زيرا مقادير بولي در حقيقت به
شکل اعداد صحيح در حافظه ذخيره ميشوند.
اگر پيششرط مث77ال 6-14يع77ني مرتب ب77ودن آراي77ه
رعايت نشود ،جستجوي دودويي پاسخ درستي نميده77د.
به اين منظور ابتدا بايد اين پيششرط بررسي شود.
با اس77تفاده از ت77ابع )(assertميت77وان اج77راي ي77ک
برنامه را به يک شرط وابسته کرد.
اين ت77ابع ي77ک آرگومان ب77ولي ميپ77ذيرد .اگر مق77دار
آرگومان falseباشد ،برنامه را خاتمه داده و موضوع را
به سيستم عامل گزارش ميکن777د .اگر مق777دار آرگومان
trueباشد ،برنامه بدون تغيير ادامه مييابد.
تابع )(assetدر سرفايل < >cassertتعري777ف
شده است.
مثال 6-16اس77تفاده از ت77ابع )(assertب77راي رعايت
كردن يك پيششرط
برنامۀ زير نسخۀ بهبوديافتهاي از تابع )(searchمثال
6-14را آزمايش ميکن7777د .در اين نس7777خه ،از ت7777ابع
)(isNonDecreasingمثال 6-15استفاده شده
تا مشخص شود آرايه مرتب است يا خير.
نتيجه اين تابع به ت777ابع )(assertارسال ميگردد ت777ا
اگر آرايه مرتب نباشد برنامه به بيراهه نرود.
#include <cassert>
function
#include <iostream>
// defines the assert()
// defines the cout object
using namespace std;
int index(int x, int a[], int n);
int main()
{ int a[] = { 22, 33, 44, 55, 66, 77, 88, 60 };
cout<<"index(44,a,7) = " << index(44,a,7) <<
endl;
cout<<"index(44,a,8) = " << index(44,a,8) <<
endl;
cout<<"index(60,a,8) = " << index(60,a,8) <<
bool isNondecreasing(int a[], int n);
int index(int x, int a[], int n)
{ assert(isNondecreasing(a,n));
int lo=0, hi=n-1, i;
while (lo <= hi)
{ i = (lo + hi)/2;
if (a[i] == x) return i;
if (a[i] < x) lo = i+1;
else hi = i-1;
}
return n;
}
index(44,a,7) = 2
آرايۀ ][aکه در اين برنامه استفاده شده كامال مرتب نيس 777
ت
ن مرتب اس777777777ت .بن777777777ابراين در
اما هفت عنصر اول آ
فراخواني) index(44,a,7تابع ب77ولي مق77دار trueرا ب77ه
)(assertارسال ميکند و برنامه ادمه مييابد.
اما در دومين فراخواني ) index(44,a,8باعث ميش777ود
که تابع )(isNondecreasingمقدار falseرا به ت77ابع
)(assertارسال کن77د كه در اين ص77ورت برنام77ه متوق77ف
ميشود و ويندوز پنجرۀ هشدار مقابل را نمايش ميدهد.
9- استفاده از انواع شمارشي در آرايه
.ح داد ه شدهاند
ي در جلسه دو م توضي
ع شمارش
انوا
با استفاده از انواع شمارشي نيز ميتوان آرايهها را
int main()
.پردازش نمود
{ enum Day { SUN, MON, TUE, WED, THU, FRI,
شمارش با استفاده از روزهاي هفته7-17 مثال
SAT };
The high temperature for day 0 was 28.6
float
ت
[] با هفhigh
ا م777ن29.1,
ه777 ب29.9,
ه777آراي31.3,
ك
ه ي30.4,
ام777برن32.0,
ن
اي
floatعنصرازنوع
high[SAT+1]
= {28.6,
The high temperature for day 1 was 29.1
30.7};
ان77ه را نش77ک روز هفت77داکثر دما در ي77د كه هر عنصر ح77ف ميكن
تعري
The high temperature for day 2 was 29.9
for high
(int day
= SUN; for
dayday
<=3SAT;
day++) :ميدهد
The
temperature
was 31.3
cout
"The highfortemperature
for day " <<
The
high<<
temperature
day 4 was 30.4
day
" was
"<< high[day]
endl;
The<<
high
temperature
for day 5<<
was
32.0
The high temperature for day 6 was 30.7
به خاطر بياوري77د ک77ه ان77واع شمارش77ي ب77ه ش77کل مق77ادير ع77ددي
ذخيره ميشوند.
اندازۀ آرايه SAT+1 ،است زي77را SATمق77دار ص77حيح 6را
دارد و آرايه به هفت عنصر نيازمند اس77ت .متغ77ير dayاز ن77وع
intاست پس ميتوان مق77ادير Dayرا ب77ه آن تخص77يص داد.
استفاده از انواع شمارشي در برخي از برنامهها باعث ميشود که
کد برنامه «خود استناد» شود .مثال در مثال 6-17کنترل حلقه به
شکل
;for (int day = SUN; day <= SAT
)day++
باعث ميشود که هر بينندهاي حلقۀ forباال را به خ77وبي
تعريف انواع 10-
انواع شمارشي يكي از راههايي است که کاربر ميتواند نوع ساخت خ77ودش را تعري77ف
کند .براي مثال دستور زير :
enum Color{ RED,ORANGE,YELLOW, GREEN, BLUE,
;} VIOLET
يک نوع جديد به نام Colorتعري77ف ميکن77د ک77ه متغيرهايي از اين ن77وع ميتوانن77د
مق7777777777ادير REDيا ORANGEيا YELLOWيا GREENيا BLUEيا
ش77کل
متغيرهايي ب77ه
نوع م
استفاده از اين
باشند.
VIOLETرا داشته
BLUE
ت77وان با مق77دار
اس7ي7ت و
Color
پس بااز ن77وع
ي
7ير
shirtمتغ7
در اينجا
تعريفينمود:
زير
شده car .يک آرايۀ چهار عنصري است و مق77دار عناصر آن
مقدارده
Color
shirtهمچ77نين
=باش77د.
;BLUEمي
به ترتيب GREENو REDو BLUEو RED
ک777777ه داراي
ن777777وع float
REDآرايهاي
wavelength
Color
اس777777ت][car
= { GREEN,
BLUE,ازRED,
;}
VIOLET+1عنصر يعني 6=1+5عنصر است.
Floatwavelength[VIOLET+1]={420,480,530,570,600,62
;}0
در ++Cميتوان نام انواع استاندارد را تغيير داد.
کلمۀ کليدي typedefيک نام مستعار براي يک ن77وع
استاندارد موجود تعريف ميکند.
نحو استفاده از آن به شکل زير است:
;typedef type alias
كه typeيک نوع استاندارد و aliasن77ام مس77تعار ب77راي
آن است.
ي مثال کساني که با پاسکال برنامه مينويس77ند ب77ه جاي ن77وع longاز
برا
7اراز عبارت
double
جايش7نوع
7توراستفاده ميکنند
Integer
7کل زي77ر بک7
typedefورابهب77ه
عبارت اگر دس7
7راکت مس77تعار
7ر از ن77ام
7
زي
شکل
به
توانند
ي
م
افراد
اين
نمايند.
ي
م
استفاده
Real
ببريم ميت77وانيم آرايهها را ب77دون عالمت ب7
استفاده کنند:
تعريف کنيم:
;typedef long Integer
;][typedef element-type alias
;typedef double Real
مثل تعريف زير :
typedef
float
;][sequence
خواهند بود
زير معتبر
کدهاي
:و پس از آن
سپس ميتوانيم آرايۀ aرا به شکل زير اعالن کنيم:
;Integer n = 22
;}sequence a = {55.5, 22.2, 99.9
;const Real PI = 3.141592653589793
;]Integer frequency[64
دستور typedefنوع جديدي را اعالن نميکند ،بلک77ه فق77ط
به يک نوع موجود نام مستعاري را نسبت ميدهد.
مثال بعدي نحوۀ به کارگيري typedefرا نشان ميدهد.
برنامۀ زير همان برنام ۀ مثال 6-13است با اين فرق
ک77ه از typedefاس77تفاده ش77ده ت77ا بت77وان از ن77ام
مستعار sequrnceب77ه عن77وان ي77ک ن77وع اس77تفاده
کرد .سپس اين نوع در فهرس777ت پارامترها و اعالن a
در تابع )(mainبه کار رفته است:
typedef float Sequence[];
void sort(Sequence,int);
void print(Sequence,int);
int main()
{ Sequence a =
88.8, 33.3, 77.7};
print(a,8);
sort(a,8);
print(a,8);
}
{55.5, 22.2, 99.9, 66.6, 44.4,
)void sort(Sequence a, int n
){ for (int i=n-1; i>0; i--
)for (int j=0; j<i; j++
)]a[j+1
>
]if (a[j
;)]swap(a[j],a[j+1
}
دوباره به دستور typedefنگاه کنيد:
;][typedef float Seguence
عالمت براكتها [] نشان ميدهند که هر چ77يزي ک77ه از ن77وع Sequenceتعري77ف
شود ،يک آرايه است و عبارت floatنيز بيان ميکند ک77ه اين آراي77ه از ن77وع float
آرايههاي چند بعدي 11-
همۀ آرايههايي كه ت77اکنون تعري77ف کرديم ،ي77ک بع77دي
هستند ،خطي هستند ،رشتهاي هستند.
ميتوانيم آرايهاي تعريف ک77نيم ک77ه از ن77وع آراي77ه باش77د،
يعني هر خانه از آن آرايه ،خود يک آرايه باشد.
به اين قبيل آرايهها ،آرايههاي چندبعدي ميگوييم.
يک آرايۀ دو بعدي آرايهاي است که هر خانه از آن ،خود
يک آرايۀ يک بعدي باشد.
يک آرايۀ سه بعدي آرايهاي است که هر خانه از آن يک
آرايۀ دو بعدي باشد.
چندن7777وع int
عنصر از
در پنج
اي با
دستيابي;بهآرايه
]int a[5
آرايههاي
عناصر
دس7777تورشکل
است.
ماننديک
بعدي اين
تعريف ميکند.
بعدياست.
يک بعدي
آرايۀ يک
آرايههاي
مثال دستور
دستور ] ;int a[3][5آرايهاي با س777ه عنصر تعري777ف
]a[1][2][3
;= 99
پنج عنصري از ن777وع
خود يک آرايۀ
ميکند که هر عنصر،
که در مجم77وع
دهدک77ه
ي7ت
قرار ماس7
عنصري77دي
آرايۀ دو بع
intاست .اين
يکرا در
مقدار 99
پانزده عضو دارد.
ايندکس آن عنصر( )1,2,3است.
تعريف
هايهاي
آرايهآراي
مثل;int
]a[2][3][5
دستور
عنصر7ه تواب77ع
دو7دي ب7
يکبا بع7
هاي چند بعدي
آرايه
پنج
هر وآراي77ه
هنگامک77ه
تفاوت77هکهاس77ت
اين77ه آراي
عنصر ،س
فرستادهکهميهر
ميکند
تعري77ف
اعالن
شوند با
7ه
7ت ک7
7دي اس7
تعداداين يک
بايددارد.
مربوطهint،
عضو از نوع
حتما
آخر
بع7بُعد
سه تا
آرايۀدوم
عناصر بُعد
تابع
مجموع سي عضو دارد.
در
ذکر شود.
مثال 6-19نوشتن و خواندن يك آرايۀ دو بعدي
برنامۀ زير نشان ميدهد که يک آرايۀ دوبعدي چگونه پردازش ميشود:
;)]void read(int a[][5
;)]void print(int a[][5
)(int main
;]{ int a[3][5
;)read(a
;)print(a
}
void read(int a[][5])
{ cout << "Enter 15 integers, 5 per row:
\n";
for (int i=0; i<3; i++)
{ cout << "ROW " << i << ": ";
for (int j=0; j<5; j++)
cin >> a[i][j];
}
void print(const int a[][5])
{ for (int i=0; i<3; i++)
{ for (int j=0; j<5; j++)
cout << " " << a[i][j];
cout << endl;
}
}
Enter 15 integers, 5 per row:
row 0: 44 77 33 11 44
row 1: 60 50 30 90 70
row 2: 65 25 45 45 55
44 77 33 11 44
60 50 30 90 70
65 25 45 45 55
دقت کنيد ک77ه در فهرس77ت پارامترهاي تواب77ع باال ،بع77د اول
نامشخص است اما بعد دوم مشخص شده .علت هم اين است
که آرايۀ دو بعدي ][][aدر حقيقت آرايهاي يکبعدي از س77ه
آرايۀ پنج عنصري است .کامپايلر نياز ن77دارد بدان77د ک77ه چ77ه
تعداد از اين آرايههاي پنج عنصري موج77ود اس77ت ،اما باي77د
بداند که آنها پنج عنصري هستند.
بُعد اول مشخص نيست اما همۀ ابعاد،وقتي يک آرايۀ چند بعدي به تابع ارسال ميشود
.ديگر بايد مشخص باشند
پردازش يك آرايۀ دوبعدي از نمرات امتحاني6-20 مثال
const NUM_STUDENTS = 3;
const NUM_QUIZZES = 5;
typedef
int
[NUM_QUIZZES];
Score[NUM_STUDENTS]
void read(Score);
void printQuizAverages(Score);
void printClassAverages(Score);
int main()
{ Score score;
cout << "Enter " << NUM_QUIZZES
<< " quiz scores for each student:
\n";
read(score);
cout << "The quiz averages are:\n";
printQuizAverages(score);
cout << "The class averages are:\n";
void read(Score score)
{ for (int s=0; s<NUM_STUDENTS;
s++)
{ cout << "Student " << s << ":
";
for(int q=0; q<NUM_QUIZZES;
q++)
cin >> score[s][q];
}
void printQuizAverages(Score score)
{ for (int s=0; s<NUM_STUDENTS; s++)
{ float sum = 0.0;
for (int q=0; q<NUM_QUIZZES; q++)
sum += score[s][q];
cout << "\tStudent " << s << ": "
<< sum/NUM_QUIZZES
<< endl;
}}
void printClassAverages(Score score)
{ for (int q=0; q<NUM_QUIZZES; q++)
{ float sum = 0.0;
for (int s=0; s<NUM_STUDENTS; s++)
sum += score[s][q];
cout << "\tQuiz " << q << ": " <<
sum/NUM_STUDENTS
<< endl;
}
}
Enter 5 quiz scores for each student:
student 0: 8 7 9 8 9
در برنام77777ۀ ف77777وق با اس77777تفاده از دس77777تور
typedefبراي آرايههاي دوبعدي 5*3نام student 1: 9 9 9 9 8
مس777تعار Scoreانتخ777اب ش777ده .اين باعث student 2: 5 6 7 8 9
ميشود که توابع خواناتر باشند .هر ت777ابع از دو
The quize averages are:
حلق77ۀ forتودرت77و اس77تفاده کرده ک77ه حلق77ۀ
student 0: 8.2
حلق77ۀ
و
کن77د
ي
م
پيمايش
را
اول
بع77د
ب77يروني،
student 1: 8.8
دروني بعد دوم را پيمايش مي نمايد.
student 2: 7
تابع )(printQuizAveragesميانگينThe class averages are:
هر سطر از نمرات را محاسبه و چاپ مينمايد و
ت777777777ابع )(printClassAverages
ميانگين هر ستون از نمرهها را چاپ ميكند.
Quiz 0: 7.33333
Quiz 1: 7.33333
Quiz 2: 8.33333
Quiz 3: 8.33333
Quiz 4: 8.66667
پردازش يك آرايۀ سه بعدي6-21 ل
مثا
:ن برنام ه تعداد صفرها را در يك آرايۀ سه بعدي ميشمارد
اي
int numZeros(int a[][4][3], int n1, int n2, int
n3);
int main()
{ int a[2][4][3]={{{5,0,2}, {0,0,9},{4,1,0},
{7,7,7} },
{ {3,0,0}, {8,5,0},
{0,0,0}, {2,0,9} } };
cout
<< "This
numZeros(a,2,4,3)
<< " zeros:\n";
array
has
"
<<
int
numZeros(int a[][4][3], int n1, int n2, int
n3)
{ int count = 0;
for (int i = 0; i < n1; i++)
for (int j = 0; j < n2; j++)
for (int k = 0; k < n3; k++)
if (a[i][j][k] == 0) ++count;
return count;
This array has 11 zeros:
توجه كنيد كه آراي77ه چگون77ه مق77داردهي ش77ده اس77ت .اين
قالب مقداردهي به خوبي نمايان ميکند که آراي77ۀ م77ذکور
يک آرايه دو عنصري است که هر عنصر ،خود يک آرايۀ
چهار عضوي است که هر عضو شامل آرايهاي سه عنصري
ميباشد .پس اين آرايه در مجموع 24عنصر دارد .آراي77ۀ
مذکور را به شکل زير نيز ميتوانيم مقداردهي کنيم:
;}int a[2][4][3]={5,0,2,0,0,9,4,1,0,7,7,7,3,0,0,8,5,0,0,0,0,2,0,9
:و يا مانند اين
{{5,0,2,0,0,9,4,1,0,7,7,7},
=
int
]a[2][4][3
;}}{3,0,0,8,5,0,0,0,0,2,0,9
هر سۀ اين قالبها براي کامپايلر يک مفهوم را دارند اما با
نگاه کردن به دو قالب اخير به سختي ميت77وان فهمي77د ک77ه
کدام عنصر از آرايه ،کدام مقدار را خواهد داشت.
پايان جلسه ششم
جلسه هفتم
«اشارهگرها و ارجاعها »
:آنچه در اين جلسه مي خوانيد
-1عملگر ارجاع
-2ارجاعها
-3اشارهگرها
-4مقداريابي
-5چپ مقدارها ،راست مقداره
-6بازگشت از نوع ارجاع
-7آرايهها و اشارهگرها
›››
-8عملگر new
-9عملگر delete
ي پويا
-10آرايهها
-11اشارهگر ثابت
ي از اشارهگرها
-12آرايها
-13اشارهگري به اشارهگر ديگر
-14اشارهگر به توابع
NUL -15و NULL
هدف کلي:
آشنايي با اشارهگرها و نحوۀ کار با آدرسهاي حافظه
هدفهاي رفتاري:
انتظار ميرود پس از پايان اين جلسه بتوانيد:
«ارجاع» را تعريف کنيد و با استفاده از عملگر ارجاع بهمتغيرها دستيابي کنيد.
«اشارهگر» را بشناسيد و بتوانيد اشارهگرهايي به ان77واعمختلف ايجاد کرده و آنها را مقداريابي کنيد.
»»
«چپمقدارها» و «راستمقدارها» را تعريف کرده و آنها رااز يکديگر تميز دهيد.
بازگشتهايي از نوع ارجاع ايجاد نماييد. طريقۀ اس77تفاده از عملگرهاي newو deleteو وظيف77ۀهر يک را بدانيد.
«آرايههاي پويا» را تعريف کرده و مزيت آنها را نسبت بهآرايههاي ايستا ذکر کنيد.
آرايههاي پويا را در برنامههايتان ايجاد کرده و م7777ديريتنماييد.
-تفاوت بين NULو NULLرا توضيح دهيد.
مقدمه 1-
حافظۀ رايانه را ميتوان به صورت يک آرايۀ ب77زرگ
در نظر گرفت .براي مثال رايانهاي با 256مگابايت
RAMدر حقيقت حاوي آرايهاي ب777777ه ان777777دازۀ
)228=( 268،435،456خانه است ک77ه ان77دازۀ هر
خانه يک بايت است.
اين خانهها داراي اين777دکس ص777فر ت777ا 268،435،455
هستند .به ايندکس هر بايت ،آدرس حافظۀ آن ميگويند.
آدرسهاي حافظ777ه را با اع777داد ش777انزدهدهي نش777ان
ميدهن77د .پس رايان77ۀ م77ذکور داراي مح77دوده آدرس
0x00000000تا 0x0fffffffميباشد.
هر وقت ک77ه متغ77يري را اعالن ميک77نيم ،س77ه وي77ژگي
اساسي به آن متغير نسبت داده ميشود« :ن77وع متغ77ير» و
«نام متغير» و «آدرس حافظه» آن.
مثال اعالن ;int nن77وع intو ن77ام nو آدرس چن77د
خانه از حافظه ک77ه مق77دار nدر آن قرار ميگ77يرد را ب77ه
يکديگر مرتبط ميسازد .فرض کني77د آدرس اين متغ77ير
0x0050cdc0است .بنابراين ميت77وانيم nرا مانن77د
شکل مقابل مجسم کنيم:
n
0x0050cdc0
int
خود متغير به شکل جعبه نمايش داده ش77ده .ن77ام متغ77ير،
،nدر باالي جعب77ه اس77ت و آدرس متغ77ير در س77مت چپ
جعبه و نوع متغير ،int ،در زير جعب77ه نش77ان داده ش77ده.
در بيشتر رايانهها نوع intچهار بايت از حافظه را اشغال
مينمايد .بنابراين همان طور ک77ه در ش77کل مقاب77ل نش77ان
داده شده است ،متغير nيک بلوک چهاربايتي از حافظ77ه
را اشغال ميکند که شامل بايتهاي 0x0050cdc0
تا 0x0050cdc3است .توجه کنيد ک77ه آدرس ش77ي،
آدرس اولين بايت از بل77وکي اس77ت ک77ه ش77ي در آن جا
ذخيره شده.
اگر متغير فوق به شکل ;int n=32مقداردهي اولي77ه
شود ،آنگاه بلوک حافظه به شکل زير خواهد ب77ود .مق77دار
32در چهار بايتي که براي آن متغير منظور شده ذخ77يره
ميشود.
0x0050cdb8
0x0050cdb9
0x0050cdc0
n
32
int
0x0050cdc0
32
0x0050cdc1
0x0050cdc2
0x0050cdc3
0x0050cdc4
0x0050cdc5
عملگر ارجاع 2-
در ++Cبراي بدست آوردن آدرس يک متغير ميتوان از
عملگر ارجاع & 1استفاده نم777ود .ب777ه اين عملگر «علمگر
آدرس» نيز ميگويند .عبارت & nآدرس متغ77ير nرا ب77ه
دست ميدهد.
)(int main
;{ int n=44
;cout << " n = " << n << endl
;cout << "&n = " << &n << endl
n = 44
&n = 0x00c9fdc3
}
خروجي نشان ميدهد كه آدرس nدر اين اجرا برابر با
0x00c9fdc3است .ميتوان فهميد ک77ه اين مق77دار
بايد يک آدرس باشد زيرا به شکل ش777انزدهدهي نمايش
داده ش777ده .اع777داد ش777انزدهدهي را از روي عالمت 0x
ميتوان تشخيص داد .معادل ده77دهي ع77دد باال مق77دار
13,237,699ميباشد.
ارجاعها 3-
يك «ارجاع» يك اسم مستعار يا واژۀ مترادف براي متغير ديگر است.
نحو اعالن يک ارجاع به شکل زير است:
;type& ref_name = var_name
typeنوع متغير اس77ت ref_name ،ن77ام مس77تعار
اس777ت و var_nameن777ام متغ777يري اس777ت ک777ه
ميخواهيم براي آن نام مستعار بسازيم .ب77راي مث77ال در
اعالن :
int& rn=n; // r is a synonym for n
rnيک ارجاع يا نام مستعار براي nاست .البته nبايد
مثال 7-2استفاده از ارجاعها
در برنامۀ زير rnبه عنوان يک ارجاع به nاعالن ميشود:
n = 44, rn = 44
n = 43, rn = 43
n = 86, rn = 86
// rn is a synonym for n
)(int main
;{ int n=44
;int& rn=n
cout
<<
متغ"n7
7ک" =
<<
<< n
هاي", rn
<<نا"م =
اين
7ت.
7ير اس7
براي ي7
متفاوتي
<<rnnو rn
;endl
دو هميشه مقدار يکساني دارن77د .اگر nکاس77ته ش77ود،
;--n
rnنيز کاسته ش77ده و اگر rnافزايش ياب77د n ،ن77يز
استcout << "n = " << n << ",.
يافته= rn
<< "
<< rn
افزايش
;endl
;rn *= 2
همانند ثابتها ،ارجاعها باي77د هنگ77ام اعالن مق77داردهي
اوليه شوند با اين تفاوت که مقدار اوليۀ يک ارجاع ،ي77ک
متغير است نه يک ليترال .بنابراين کد زير اشتباه است:
t& rn=44; // ERROR: 44 is not a variable
گرچه برخي از کامپايلرها ممکن است دستور باال را مجاز
بدانند ولي با نشان دادن يک هشدار اعالم ميکنند که يک
متغير موقتي ايجاد شده تا rnبه حافظۀ آن متغير ،ارجاع
داشته باشد.
درست است که ارجاع با يک متغير مقداردهي ميشود،
اما ارجاع به خودي خود يک متغير نيست.
يک متغير ،فضاي ذخيرهسازي و نش77اني مس77تقل دارد،
حال آن که ارجاع از فضاي ذخيرهسازي و نشاني متغ77ير
ديگري بهره ميبرد.
* ارجاعها متغيرهاي مستقل نيستند7-3 مثال
int main()
{ int n=44;
int& rn=n;
cout
// rn is a synonym for n
<< " &n = " << &n << ", &rn = " << &rn <<
endl;
int& rn2=n;
for n
// rn2 is another synonym
int& rn3=rn;
for n
// rn3 is another synonym
&n = 0x0064fde4, &rn = 0x0064fde4
&rn2
=
0x0064fde4,
&rn3
=
در برنام77ۀ ف77وق فق77ط ي77ک ش77ي وج77ود دارد و آن هم n
اس777ت rn .و rn2و rn3ارجاعهايي ب777ه nهس777تند.
خروجي نيز تاييد ميکند ک77ه آدرس rnو rn2و rn3
با آدرس nيکي است.
.يک شي ميتواند چند ارجاع داشته باشد
ارجاعها بيشتر براي ساختن پارامترهاي ارجاع در توابع
به کار ميروند .تابع ميتواند مقدار يک آرگومان را ک777ه
به طريق ارجاع ارسال شده تغي77ير ده77د زي77را آرگومان
هستند.به همان تابع
شي ارجاع
پارامتر
پارامتر است
اصلي وفرق اين
تنها
دامنۀيک
ارجاعکههر دو
.محدود شده است
اشارهگرها 4-
ميدانيم که اعداد صحيح را بايد در متغ77يري از ن77وع int
نگهداري کنيم و اعداد اعشاري را در متغيرهايي از ن777وع
.float
به همين ترتيب کاراکترها را بايد در متغيرهايي از ن777وع
charنگهداريم و مقدارهاي منطقي را در متغيرهايي از
نوع .bool
اما آدرس حافظه را در چه نوع متغيري بايد قرار
دهيم؟
عملگر ارجاع & آدرس حافظۀ يک متغير موج77ود را ب77ه
دست ميدهد .ميتوان اين آدرس را در متغ777ير ديگري
ذخيره نمود.
متغيري که يک آدرس در آن ذخيره ميشود اشارهگر
.ناميده ميشود
ب77راي اين ک77ه ي77ک اش77ارهگر اعالن ک77نيم ،ابت77دا باي77د
مشخص کنيم که آدرس چه نوع دادهاي قرار اس777ت در
آن ذخ777يره ش777ود .سپس از عملگر اش777اره * اس777تفاده
ميکنيم تا اشارهگر را اعالن کنيم.
براي مثال دستور :
;float* px
اش77ارهگري ب77ه ن77ام pxاعالن ميکن77د ک77ه اين اش77ارهگر،
آدرس ي77ک ش77ي از ن77وع intرا فق77ط ميت77وان در
آدرس متغيرهايي از نوع floatرا نگهداري مينمايد .به
اشارهگري از نوع *intذخيره کرد و آدرس يک
طور کلي ب77راي اعالن ي77ک اش77ارهگر از نح77و زي77ر اس77تفاده
شي از نوع floatرا فقط ميت77وان در اش77ارهگري
ميکنيم:
از نوع *floatذخيره نمود .دقت کني77د ک77ه ي77ک
اشارهگر ،يک متغير مستقل است.
;type* pointername
که typeنوع متغيرهايي است ک77ه اين اش77ارهگر آدرس
آنها را نگه777داري ميکن777د و pointernameن777ام
اشارهگر است.
به کارگيري اشارهگرها7-4 * مثال
*int وع77ارهگر از ن77 و يک اشn به نامint برنامۀ زير يک متغير از نوع
: را اعالن ميکندpn به نام
int main()
n = 44, &n = 0x0064fddc
pn = 0x0064fddc
{ int n=44; &pn = 0x0064fde0
cout << "n = " << n << ", &n = " <<
&n << endl;
int* pn=&n;
of n
cout << "
// pn holds the address
pn = " << pn << endl;
متغ77ير nبا مق77دار 44مق77دارده
ي
ش777777777777777777777ده و آدرس آن
0x0064fddcميباش777777777د.
اشارهگر pnبا مق77دار & nيع77ني
آدرس nمق777داردهي ش777ده .پس
مق7777777دار درون pnبراب7777777ر با
0x0064fddcاست (خ77ط دوم
خروجي اين موض77777وع را تايي77777د
ميکند) .
0x0064fddc
44
n
int
0x0064fde0
pn 0x0064fddc
*
int
اما pnيک متغير مستقل اس77ت و آدرس مس77تقلي دارد.
& pnآدرس pnرا ب77ه دس77ت ميده77د .خ77ط س77وم
خروجي ثابت ميکند که متغير pnمس77تقل از متغ77ير n
گوييم «
وقتي
اشارهموض77وع کم77ک
nاين
pnبه7به7تر
درک
زي7م7ري ب77ه
اس77ت .تص77وير
درونيpn
اينکند»
ميکند .در مي
آدرس nnو pnنش77ان
هاي مهم
يعني ويژگ
تص77وير
دارد n .اس77ت و nمق77دار 44
قرارگر به
داده شده pn .يک اشاره
دارد.
وق77تي ميگ77وييم «pn
n
44
int
ب77ه nاش77اره ميکن77د»
يع777777777ني درون pn
pn
*int
آدرس nقرار دارد.
مقداريابي5-
فرض کنيد nداراي مقدار 22باشد و pnاش77ارهگري ب77ه n
باشد .با اين حساب باي77د بت77وان از طري77ق pnب77ه مق77دار 22
رسيد .با استفاده از * ميت77وان مق77داري ک77ه اش77ارهگر ب77ه آن
اشاره دارد را به دست آورد.
به اين کار مقداريابي اشارهگر ميگوييم.
مقداريابي يك اشارهگر7-5 مثال
: فقط يک خط کد بيشتر دارد. است7-4 ن برنام ۀ مثال
ن برنام ه هما
اي
int main()
{ int n=44;
cout <<
endl;
n = 44, &n = 0x0064fdcc
pn = 0x0064fdcc
&pn = 0x0064fdd0
*pn = 44
"n = " << n << ", &n = " << &n <<
int* pn=&n;
of n
// pn holds the address
است زيرا هرn يک اسم مستعار برايpn* ظاهرا
cout << " .دارند
pnمقدار
= "يک
<<دوpn << endl;
cout << "&pn = " << &pn << endl;
cout << "*pn = " << *pn << endl;
اشارهگري به اشارهگرها7-6 * مثال
ک77ه ي77تي ب77 ح،د77تواند اشاره کن
يک اشارهگر به هر چيزي مي
: است7-4 اين کد ادامۀ ساختار برنامۀ مثال
. به مثال زير دقت کنيد.اشارهگر ديگر
int main()
{ int n=44;
cout << " n = " << n << endl;
cout << " &n = " << &n << endl;
int* pn=&n;
// pn holds the address of n
cout << " pn = " << pn << endl;
cout << " &pn = " << &pn << endl;
cout << " *pn = " << *pn << endl;
int** ppn=&pn; // ppn holds the address of pn
cout << " ppn = " << ppn << endl;
cout << " &ppn = " << &ppn << endl;
cout << " *ppn = " << *ppn << endl;
cout << "**ppn = " << **ppn << endl;
}
int
44
n
n = 44
*int
=
&n
0x0064fd78
=
pn
0x0064fd78
=
&pn
0x0064fd7c
pn
**int
ppn
در برنامۀ باال متغير nاز ن77وع intتعري77ف
شده pn .اشارهگري است که ب77ه nاش77اره
دارد .پس نوع pnبايد *intباشدppn .
اشارهگري است که به pnاش77اره ميکن77د.
پس نوع ppnبايد **intباشد .همچنين =
چ7777ون ppnب7777ه pnاش7777اره دارد ،پس
* ppnمقدار pnرا نشان ميدهد و چ77ون =
pnبه nاش77اره دارد ،پس * pnمق77دار n
*pn = 44
ppn
0x0064fd7c
&ppn
0x0064fd80
عملگر مقداريابي * و عملگر ارجاع & معکوس يک77ديگر
رفتار ميکنند .اگر اين دو را با هم ترکيب کنيم ،يک77ديگر
را خنثي مينمايند .اگر nيک متغ77ير باش77د n& ،آدرس
آن متغير است .از طرفي با استفاده از عملگر * ميت777وان
مقداري که در آدرس & nقرار گرفته را به دست آورد.
بنابراين *& nبرابر با خود nخواهد بود .همچنين اگر
pيک اشارهگر باشد p* ،مق77داري ک77ه pب77ه آن اش77اره
دارد را ميده777777د .از طرفي با اس777777تفاده از عملگر &
ميتوانيم آدرس چيزي که در * pقرار گرفت77ه را بدس7ت
آوريم .پس &* pبرابر با خ77ود pخواه77د ب77ود .ترتيب
قرارگرفتن اين عملگرها مهم اس77777ت .يع77777ني *& nبا
&* nبرابر نيست .علت اين امر را توضيح دهيد.
عملگر * دو کاربرد دارد .اگر پسونِد يک نوع
باشد (مثل )*intيک اشارهگر به آن ن77وع را
تعريف ميکند و اگر پيش77ونِد ي77ک اش77ارهگر
باشد (مثل * )pآنگ77اه مق77داري ک77ه pب77ه آن
اشاره ميکند را برميگردان77د .عملگر & ن77يز
دو کاربرد دارد .اگر پس77وند ي77ک ن77وع باش77د
(مثل )&intيک نام مستعار تعريف ميکن77د
و اگر پيش77وند ي77ک متغ77ير باش77د (مث77ل &)n
آدرس آن متغير را ميدهد.
چپ مقدارها ،راست مقدارها 6-
يک دستور جايگزيني دو بخش دارد :بخشي که در س77مت
چپ عالمت جايگزيني قرار ميگيرد و بخشي که در سمت
راست عالمت جايگزيني قرار ميگيرد .مثال دس77تور = n
;55متغير nدر سمت چپ قرار گرفته و مق77دار 55در
سمت راست .اين دستور را نميتوان به شکل ;n = 55
نوشت زيرا مقدار 55يک ث77ابت اس77ت و نميتوان77د مق77دار
بگيرد .پس هنگام استفاده از عملگر جايگزيني باي77د دقت
کنيم که چ77ه چ77يزي را در س77مت چپ قرار ب77دهيم و چ77ه
چيزي را در سمت راست.
چيزهايي ک77ه ميتوانن77د در س77مت چپ جايگزيني
قرار بگيرن777د «چپمق777دار» خوان777ده ميش777وند و
چيزهايي که ميتوانند در سمت راس777ت جايگزيني
قرار بگيرند «راستمقدار» ناميده ميشوند .متغيرها
(و به طور کلي اشيا) چپمق77دار هس77تند و ليترالها
(مثل 15و " )"ABCراست مقدار هستند.
يک ثابت در ابتدا به شکل يک چپمقدار نمايان ميشود:
// MAX is an
;const int MAX = 65535
lvalue
اما از آن پس ديگر نميت77وان ب77ه عن77وان چپ مق77دار از آنها
استفاده کرد:
// ERROR: MAX is
;MAX = 21024
constant
به اين گونه چپمقدارها ،چپمق77دارهاي «تغي77ير ناپ77ذير» گفت77ه
ميشود .مثل آرايهها:
int a[] = {1,2,3}; // O.K
مابقي چپمقدارها که ميتوان آنها را تغي77ير داد ،چپمق77دارهاي «تغي77ير
پذير» ناميده ميشوند .هنگ77ام اعالن ي77ک ارجاع ب77ه ي77ک چپمق77دار نياز
داريم:
// O.K. n is an lvalue
;int& r = n
اما اعالنهاي زير غيرمعتبرند زيرا هيچ کدام چپمقدار نيستند:
// ERROR: 44 is not an lvalue
// ERROR: n++ is not an
;int& r = 44
;int& r = n++
lvalue
;)int& r = cube(n
// ERROR: cube(n) is not
an lvalue1 – L_values
2- R_values
يک تابع ،چپمقدار نيست اما اگر ن77وع بازگش77تي آن ي77ک ارجاع باش77د،
ميتوان تابع را به يک چپمقدار تبديل کرد.
بازگشت از نوع ارجاع 7-
در بحث توابع ،ارسال از طري77ق مق77دار و ارسال از طري77ق
ارجاع را ديديم .اين دو شيوۀ تبادل در م77ورد بازگش77ت از
تابع نيز صدق ميکند:
بازگش77ت از طري77ق مق77دار و بازگش77ت از طري77ق ارجاع.
توابعي که تاکنون ديديم بازگشت به طريق مقدار داشتند.
يع77ني هميش77ه ي77ک مق77دار ب77ه فراخوانن77ده برميگش77ت.
ميتوانيم تابع را طوري تعريف کنيم ک77ه ب77ه جاي مق77دار،
يک ارجاع را بازگشت دهد .مثال به جاي اين که مقدار m
را بازگشت دهد ،يک ارجاع به mرا بازگشت دهد.
وقتي بازگشت به طريق مقدار باشد ،تابع يک راس7تمقدار
خواه77د ب77ود زي77را مق77دارها لي77ترال هس77تند و ليترالها
راستمقدارند .به اين ترتيب تابع را فقط در سمت راس77ت
يک جايگزيني ميتوان به کار برد مثل:
;)(m = f
وقتي بازگشت به طريق ارجاع باشد ،ت77ابع ي77ک چپمق77دار
خواهد بود زيرا ارجاعها چپمقدار هس777تند .در اين حالت
تابع را ميتوان در سمت چپ يک جايگزيني قرار داد مثل
:
;f() = m
براي اين که نوع بازگش77تي ت77ابع را ب77ه ارجاع تب77ديل ک77نيم ک77افي اس77ت
عملگر ارجاع را به عنوان پسوند نوع بازگشتي درج کنيم.
مثال 8-7بازگشت از نوع ارجاع
*
)int& max(int& m, int& n
};){ return (m > n ? m : n
)(int main
;{ int m = 44, n = 22
<< )cout << m << ", " << n << ", " << max(m,n
;endl
;max(m,n) = 55
<< cout
44,m
<<22,
)44 ", " << n << ", " << max(m,n
55, 22, 55
;<< endl
ت777ابع )(maxاز بين mو nمق777دار بزرگتر را پي777دا
کرده و سپس ارجاعي به آن را باز ميگرداند.
بن7777777ابراين اگر mاز nبزرگتر باش7777777د ،ت7777777ابع
) max(m,nآدرس mرا برميگرداند.
پس وقتي مينويسيم ;max(m,n) = 55مقدار
55در حقيقت درون متغ77777ير mقرار ميگ77777يرد (اگر
m>nباشد).
به بياني ساده ،فراخواني ) max(m,nخود mرا ب77ر
ميگرداند نه مقدار آن را.
اخطار:
وقتي يک تابع پايان ميياب77د ،متغيرهاي محلي آن ن77ابود
ميش77وند .پس هيچ وقت ارجاعي ب77ه ي77ک متغ77ير محلي
بازگشت ندهي77د زي77را وق77تي ک77ار ت77ابع تمام ش77د ،آدرس
متغيرهاي محلياش غير معتبر ميشود و ارجاع بازگش77ت
داده شده ممکن است ب77ه ي77ک مق77دار غ77ير معتبر اش77اره
داشته باشد .تابع )(maxدر مثال باال يک ارجاع ب777ه m
يا nرا بر ميگرداند .چ77ون mو nخودش77ان ب77ه طري77ق
ارجاع ارسال ش77دهاند ،پس محلي نيس77تند و بازگردان77دن
ارجاعي به آنها خللي در برنامه وارد نميکند.
به اعالن تابع )(maxدقت کنيد:
)int& max(int& m, int& n
نوع بازگشتي آن با استفاده از عملگر ارجاع & ب77ه ش77کل
يک ارجاع درآمده است.
مث77ال 7-9ب77ه ک77ارگيري ي77ك ت77ابع ب77ه عن77وان عملگر
زيرنويس آرايه
float& component(float* v, int k)
{ return v[k-1];}
int main()
{ float v[4];
v[0] = 1
v[1] = 0.5
v[2] = 0.333333
v[3] = 0.25
for (int k = 1; k <= 4; k++)
component(v,k) = 1.0/k;
for (int i = 0; i < 4; i++)
cout << "v[" << i << "] = " << v[i] <<
endl;
ت77ابع )(componentباعث ميش77ود ک77ه اين77دکس
آرايه vاز «ش77مارهگذاري از ص77فر» ب77ه «ش77مارهگذاري از
ي77ک» تغي77ير کن77د .بن77ابراين )component(v,3
معادل ] v[2است .اين کار از طريق بازگشت از طري77ق
ارجاع ممکن شده است.
آرايهها و اشارهگرها 8-
ح نيستند اما بعضي
گرچه اشارهگرها از انواع عددي صحي
از اعمال حسابي را ميت777وان روي اش777ارهگرها انجام داد.
حاصل اين ميشود که اشارهگر به خانۀ ديگري از حافظ77ه
اشاره ميکند .اشارهگرها را ميت77وان مث77ل اع77داد ص77حيح
افزايش و يا کاهش داد و ميتوان يک عدد ص77حيح را ب77ه
آنها اضافه نمود يا از آن کم کرد .البته ميزان افزايش يا
کاهش اشارهگر بستگي به نوع دادهاي دارد که اش77ارهگر
به آن اشاره دارد.
مثال 7-10پيمايش آرايه با استفاده از اشارهگر
ن ميدهد ك ه چگون ه ميتوان از اشارهگر براي پيمايش يک آرايه استفاده نمود:
ل نشا
اين مثا
int main()
{ const int SIZE = 3;
short a[SIZE] = {22, 33, 44};
cout << "a = " << a << endl;
cout << "sizeof(short) = " << sizeof(short) << endl;
short* end = a + SIZE; // converts SIZE to
offset 6
short sum = 0;
for (short* p = a; p < end; p++)
{ sum += *p;
cout << "\t p =a "=<<
p;
0x3fffd1a
cout << "\t *p = " << *p;
sizeof(short) = 2
cout << "\t sum = " << sum << endl;
p = 0x3fffd1a
*p = 22
}
sum = 22
cout << "end = " << end << endl;
p = 0x3fffd1c
*p = 33
}
sum = 55
اين مثال نشان ميدهد که هر گاه يک اشارهگر افزايش
يابد ،مقدار آن به اندازۀ تعداد بايتهاي شيئي که ب77ه آن
اشاره ميکند ،افزايش مييابد .مثال اگر pاشارهگري ب77ه
doubleباشد و ) sizeof(doubleبرابر با هش77ت
بايت باش77د ،هر گ77اه ک77ه pي77ک واح77د افزايش ياب77د،
اشارهگر pهشت بايت به پيش ميرود.
: مثال کد زير
float a[8];
float* p = a;
++p;
// p points to a[0]
// increases the value of p by sizeof(float)
اگر floatها 4بايت را اشغال كنند آنگاه p++مق77دار
درون pرا 4بايت افزايش ميده7777د و ;p += 5
مقدار درون pرا 20بايت افزايش ميدهد .با اس77تفاده
از خاصيت مذکور ميتوان آرايه را پيمايش نم77ود :ي77ک
اش777ارهگر را با آدرس اولين عنصر آراي777ه مق777داردهي
کنيد ،سپس اشارهگر را پي در پي افزايش دهي7777د .هر
افزايش سبب ميش77ود ک77ه اش77ارهگر ب77ه عنصر بع77دي
آرايه اشاره کند .يعني اشارهگري که به اين نحو به کار
گرفته شود مثل ايندکس آرايه عمل ميکند.
همچنين با استفاده از اشارهگر ميتوانيم مستقيما به عنصر مورد نظر در آرايه دستيابي کنيم:
]// p points to a[0
// now p points to
;float* p = a
;p += 5
]a[5
يک نکتۀ ظريف در ارتباط با آرايهها و اشارهگرها وجود
دارد :اگر اش77ارهگر را بيش از اين77دکس آراي77ه افزايش
دهيم ،ممکن است ب77ه بخشهايي از حافظ77ه ب77رويم ک77ه
هن77وز تخص77يص داده نش77دهاند يا ب77راي کارهاي ديگر
تخصيص يافتهاند .تغيير دادن مقدار اين بخشها باعث
بروز خطا در برنامه و کل سيستم ميش77ود .هميش77ه باي77د
کد زير نشان ميدهد که چطور اين اتفاق رخ ميدهد.
// points to last element in the
;]float a[8
;]float* p = a[7
p points to memory past last
array
++p; //now
!element
;*p = 22.2
!// TROUBLE
مثال بعدي نشان ميدهد كه ارتباط تنگاتنگي بين آرايهها
و اش77ارهگرها وج77ود دارد .ن77ام آراي77ه در حقيقت ي77ک
اشارهگر ث77ابت ( )constب77ه اولين عنصر آراي77ه اس77ت.
همچنين خواهيم ديد که اش77ارهگرها را مانن77د هر متغ77ير
ديگري ميتوان با هم مقايسه نمود.
پيمايش عناصر آرايه از طريق آدرس7-11 * مثال
int main()
{ short a[] = {22, 33, 44, 55, 66};
cout << "a = " << a << ", *a = " << *a <<
endl;
for (short* p = a; p < a +5; p++)
a = <<
0x3fffd08,
22 p << ", *p = " << *p <<
cout
"p =*a"=<<
endl; p = 0x3fffd08, *p = 22
}
p
p
p
p
p
=
=
=
=
=
0x3fffd0a, *p = 33
0x3fffd0c, *p = 44
0x3fffd0e, *p = 55
0x3fffd10, *p = 66
0x3fffd12, *p = 77
در نگ77اه اول a ،و pمانن77د هم هس77تند :هر دو ب77ه ن77وع
shortاش777777اره ميکنن777777د و هر دو داراي مق777777دار
0x3fffd08هستند .اما aيک اشارهگر ثابت است و
نميتواند افزايش يابد تا آرايه پيمايش شود .پس به جاي
آن pرا افزايش ميدهيم تا آرايه را پيمايش کنيم .شرط
( )p < a+5حلقه را خاتمه ميده7د a+5 .ب7ه ش7کل
زير ارزيابي ميشود:
0x3fffd08 + 5*sizeof(short) = 0x3fffd08
+ 5*2 = 0x3fffd08 + 0xa = 0x3fffd12
پس حلقه تا زماني که p < 0x3fffd12باشد ادامه
مييابد.
عملگر زيرنويس[] مث77ل عملگر مق77داريابي * رفت77ار ميکن77د .هر دوي
اينها ميتوانند به عناصر آرايه دسترسي مستقيم داشته باشند.
a[0] == *a
)a[1] == *(a + 1
)a[2] == *(a + 2
...
...
پس با استفاده از کد زير نيز ميتوان آرايه را پيمايش نمود:
)for (int i = 0; i < 8; i++
;cout << *(a + i) << endl
مثال 7-12مقايسۀ الگو
در اين مث777ال ،ت777ابع )(locدر ميان n1عنصر اول آراي777ۀ a1ب777ه دنبال n2عنصر اول آراي777ۀ a2
ميگردد .اگر پيدا شد ،يک اشارهگر به درون a1برميگرداند که a2از آنجا شروع ميش77ود وگرن77ه
اشارهگر NULLرا برميگرداند.
)short* loc(short* a1, short* a2, int n1, int n2
;{ short* end1 = a1 + n1
)for (short* p1 = a1; p1 <end1; p1++
)if (*p1 == *a2
){ for (int j = 0; j < n2; j++
;if (p1[j] != a2[j]) break
;if (j == n2) return p1
}
;return 0
int main()
{ short a1[9] = {11, 11, 11, 11, 11, 22, 33, 44, 55};
short a2[5] = {11, 11, 11, 22, 33};
cout << "Array a1 begins at location\t" << a1 << endl;
cout << "Array a2 begins at location\t" << a2 << endl;
short* p = loc(a1, a2, 9, 5);
if (p)
{ cout << "Array a2 found at location\t" << p << endl;
for (int i = 0; i < 5; i++)
cout << "\t" << &p[i] << ": " << p[i] << "\t"
<< &a2[i] << ": " << a2[i] << endl; }
else cout << "Not found.\n";}
Array a1 begins at location
0x3fffd12
Array a2 begins at location
0x3fffd08
Array a2 found at location
0x3fffd16
0x3fffd16: 11
0x3fffd08: 11
0x3fffd18: 11
0x3fffd0a: 11
0x3fffd1a: 11
0x3fffd0c: 11
0x3fffd1c: 22
0x3fffd0e: 22
0x3fffd1e: 33
0x3fffd10: 33
9-7عملگر new
وقتي يك اشارهگر شبيه اين اعالن شود:
// p is a pointer to a float
;float* p
يک فضاي چهاربايتي ب77ه pتخص77يص داده ميش77ود (معم77وال
) sizeof(floatچهار بايت است) .حاال pايجاد شده است
اما به هيچ جايي اشاره نميکند زيرا هن77وز آدرس77ي درون آن
قرار نگرفته .ب777ه چ777نين اش777ارهگري اش777ارهگر سرگردان
ميگوين777د .اگر س777عي ک777نيم ي777ک اش777ارهگر سرگردان را
مقداريابي يا ارجاع کنيم با خطا مواجه ميشويم.
مثال دستور:
;*p = 3.14159
// ERROR: no storage
has been allocated for *P
خطاست .زيرا pبه هيچ آدرسي اشاره نميکند و سيستم عامل
نميداند که مقدار 3.14159را کجا ذخيره کند .براي رفع اين
مشکل ميتوان اشارهگرها را هنگام اعالن ،مقداردهي کرد:
// x cintains the value 0
;float x = 0
float* p = &x // now p points to x
;*p = 3.14159
// O.K. assigns this
value to address that p points to
در اين حالت ميت77وان ب77ه * pدس77تيابي داش77ت زي77را حاال pب77ه xاش77اره
ميکن77د و آدرس آن را دارد .راه ح77ل ديگر اين اس77ت ک77ه ي77ک آدرس
اختصاصي ايجاد شود و درون pقرار بگيرد .بدين ترتيب pاز سرگرداني
خارج ميشود .اين کار با استفاده از عملگر newصورت ميپذيرد:
;float* p
p = new float; // allocates storage for 1
float
*p = 3.14159; // O.K. assigns this value to that
storage
دقت کنيد که عملگر newفقط خود pرا مقداردهي ميکند ن77ه آدرس77ي
که pبه آن اشاره ميکند .ميتوانيم سه خط فوق را با هم ترکيب کرده و
به شکل يک دستور بنويسيم:
;)float* p = new float(3.141459
با اين دستور ،اشارهگر pاز نوع *floatتعريف ميشود
و سپس ي77ک بل77وک خ77الي از ن77وع floatمنظ77ور ش77ده و
آدرس آن ب77ه pتخص77يص ميياب77د و همچ77نين مق77دار
3.14159در آن آدرس قرار ميگ777777777يرد .اگر عملگر
newنتواند خانۀ خالي در حافظه پيدا کند ،مقدار ص77فر را
برميگرداند .اش77ارهگري ک77ه اين چ77نين باش77د« ،اش77ارهگر
تهي» يا NULLمينامند.
با استفاده از کد هوشمند زير ميتوانيم مراقب باشيم ک77ه
اشارهگر تهي ايجاد نشود:
;double* p = new double
;)(if (p == 0) abort
// allocator
failed: insufficent memory
;else *p = 3.141592658979324
در اين قطعه کد ،هرگاه اشارهگري تهي ايجاد ش77د ،ت77ابع
)(abortفراخواني شده و اين دستور لغو ميشود.
تاکنون دانستيم که به دو طريق ميت77وان ي77ک متغ77ير را ايجاد و
مقداردهي کرد .روش اول:
// allocates
;float x = 3.14159
named memory
و روش دوم:
//
;)float* p = new float(3.14159
allocates unnamed memory
در حالت اول ،حافظۀ مورد نياز براي xهنگام کامپايل تخص77يص
مييابد .در حالت دوم حافظۀ مورد نياز در زمان اج77را و ب77ه ي77ک
شيء بينام تخصيص مييابد که با استفاده از * pقاب77ل دس77تيابي
است.
-10عملگر delete
عملگر deleteعملي برخالف عملگر newدارد .کارش اين است
که حافظۀ اشغال شده را آزاد کند .وق77تي حافظهاي آزاد ش77ود ،سيس77تم
عامل ميتواند از آن براي کارهاي ديگر يا ح77تي تخص77يصهاي جدي77د
استفاده کند .عملگر deleteرا تنها روي اش77ارهگرهايي ميت77وان ب77ه
کار برد که با دستور newايجاد شدهاند .وقتي حافظ77ۀ ي77ک اش77ارهگر
آزاد شد ،ديگر نميتوان به آن دستيابي نم777ود مگر اين ک777ه دوباره اين
حافظه تخصيص يابد:
;)float* p = new float(3.14159
// deallocates q
;delete p
*p = 2.71828; // ERROR: q has been
deallocated
وق77تي اش77اره گر pدر ک77د باال آزاد ش77ود ،حافظهاي ک77ه توس77ط
newب77ه آن تخص77يص يافت77ه ب77ود ،آزاد ش77ده و ب77ه م77يزان
) sizeof(floatب777ه حافظ777ۀ آزاد اض777افه ميش777ود .وق777تي
اشارهگري آزاد شد ،به هيچ چيزي اشاره نميکن77د؛ مث77ل متغ77يري
ک77ه مق77داردهي نش77ده .ب77ه اين اش77ارهگر ،اش77ارهگر سرگردان
ميگويند.
اشارهگر به يک شيء ثابت را نميتوان آزاد کرد:
;const int* p = new int
ERROR: cannot delete pointer to const
delete p; //
objects
علت اين است که «ثابتها نميتوانند تغيير کنند».
اگر متغ77يري را صريحا اعالن کردهاي77د و سپس اش77ارهگري ب77ه آن
نسبت دادهايد ،از عملگر deleteاستفاده نکني77د .اين ک77ار باعث
اشتباه غير عمدي زير ميشود:
float x =3.14159; // x contains the value
3.14159
float* p = &x; // p contains the address of x
delete p; // WARNING: this will make x
free
کد باال باعث ميشود که حافظۀ تخصيصيافته براي xآزاد شود .اين
اشتباه را به سختي ميتوان تشخيص داد و اشکالزدايي کرد.
آرايههاي پويا 11-
ن كامپايل ،ايجاد و
نام آرايه در حقيقت يك اشارهگر ثابت است كه در زما
ص داد ه ميشود:
تخصي
float a[20]; //a is a const pointer to a block of 20
floats
// so is p
;]float* const p = new float[20
هم aو هم pاشارهگرهاي ثابتي هستند ک77ه ب77ه بل77وکي حاوي 20متغ77ير
floatاشاره دارند .به اعالن aبستهبندي ايستا 1ميگوين77د زي77را اين ک77د
باعث ميشود که حافظۀ مورد نياز براي aدر زمان کامپايل تخص77يص داده
شود .وقي برنامه اجرا شود ،به هر حال حافظ77ۀ مربوط77ه تخص77يص خواه77د
يافت حتي اگر از آن هيچ استفادهاي نشود.
ميتوانيم با استفاده از اشارهگر ،آرايۀ فوق را طوري تعري77ف
کنيم که حافظه مورد نياز آن فق77ط در زمان اج77را تخص77يص
يابد:
;]float* p = new float[20
دستور باال 20 ،خانۀ خالي حافظه از نوع floatرا در اختيار
گذاشته و اشارهگر pرا به خان77ۀ اول آن نسبت ميده77د .ب77ه
اين آرايه« ،آرايۀ پويا »2ميگوين77د .ب77ه اين طرز ايجاد اش77يا
بستهبندي پويا 3يا «بستهبندي زمان جرا» ميگويند.
آرايۀ ايستاي aو آرايۀ پوياي pرا با يک777ديگر مقايس777ه
کنيد .آرايۀ ايستاي aدر زمان کامپايل ايجاد ميشود و تا
پايان اج77راي برنام77ه ،حافظ77ۀ تخصيص77ي ب77ه آن مش77غول
ميماند .ولي آرايۀ پوياي pدر زمان اج777را و هر جا ک777ه
الزم شد ايجاد ميشود و پس از اتمام کار ن77يز ميت77وان با
عملگر deleteحافظۀ تخصيصي به آن را آزاد کرد:
;delete [] p
براي آزاد کردن آرايۀ پوياي pبراکتها [] قبل از نام p
بايد حتما قيد شوند زيرا pبه يک آرايه اشاره دارد.
استفاده از آرايههاي پويا7-15 مثال
:() در برنامۀ زير يک آرايۀ پويا ايجاد ميكندget تابع
void get(double*& a, int& n)
{ cout << "Enter number of items: "; cin >> n;
a = new double[n];
cout << "Enter " << n << " items, one per line:\n";
for (int i = 0; i < n; i++)
{ cout << "\t" << i+1 << ": ";
cin >> a[i];
}}
void print(double* a, int n)
{ for (int i = 0; i < n; i++)
cout << a[i] << " " ;
cout << endl;
}
int main()
{ double* a;// a is simply an unallocated
pointer
int n;
get(a,n);
//
now a is an array of n doubles
print(a,n);
delete [] a;//
now a is simply an unallocated pointer
again
get(a,n); //
print(a,n);
}
now a is an array of n doubles
Enter number of items: 4
Enter 4 items, one per line:
1: 44.4
2: 77.7
3: 22.2
4: 88.8
44.4 77.7 22.2 88.8
Enter number of items: 2
Enter 2 items, one per line:
1: 3.33
2: 9.99
3.33 9.99
اشارهگر ثابت 12-
«اشارهگر به يک ثابت» با «اشارهگر ث77ابت» تف77اوت دارد.
اين تفاوت در قالب مثال زير نشان داده شده است.
مث77ال 7-16اش77ارهگرهاي ث77ابت و اش77ارهگرهايي ب77ه
ثابتها
در اين ک777د چهار اش777ارهگر اعالن ش777ده .اش777ارهگر ،p
اشارهگر ثابت ،cpاشاره ب77ه ي77ک ث77ابت ،pcاش77ارهگر
ثابت به يک ثابت : cpc
int n = 44;
int* p = &n;
++(*p);
++p;
int* const cp = &n;
++(*cp);
++cp;
const int k = 88;
const int * pc = &k;
++(*pc);
// an int
// a pointer to an int
// OK: increments int *p
// OK: increments pointer p
// a const pointer to an int
// OK: increments int *cp
// illegal: pointer cp is const
// a const int
// a pointer to a const int
// illegal: int *pc is const
++pc;
// OK: increments pointer pc
const int* const cpc = &k; // a const pointer to a const
int
++(*cpc);
// illegal: int *pc is const
اشارهگر pاشارهگري ب77ه متغ77ير nاس77ت .هم خ77ود pقاب77ل
افزايش است ( )p++و هم مقداري که pبه آن اشاره ميکند
قابل افزايش است ( .))P*(++اش77اره گر cpي77ک اش77ارهگر
ثابت است .يعني آدرسي که در cpاست قابل تغي77ير نيس77ت
ولي مقداري که در آن آدرس اس77ت را ميت77وان دس 7تکاري
کرد .اشارهگر pcاشارهگري است که به آدرس ي77ک ث77ابت
اشاره دارد .خود pcرا ميت77وان تغي77ير داد ولي مق77داري ک77ه
pcبه آن اشاره دارد قابل تغي77ير نيس77ت .در آخر هم cpc
يک اشارهگر ثابت به يک شيء ثابت اس77ت .ن77ه مق77دار cpc
قابل تغيير است و نه مقداري که آدرس آن در cpcاست.
آرايهاي از اشارهگرها 13-
ميت77وانيم آرايهاي تعري77ف ک77نيم ک77ه اعض77اي آن از ن77وع
اشارهگر باشند .مثال دستور:
;]float* p[4
آرايۀ pرا با چهار عنصر از نوع ( *floatيعني اش77ارهگري
ب7777ه )floatاعالن ميکن7777د .عناصر اين آراي7777ه را مث7777ل
اشارهگرهاي معمولي ميتوان مقداردهي کرد:
;)p[0] = new float(3.14159
;)p[1] = new float(1.19
اين آرايه را مي توانيم شبيه شکل مقابل مجسم کنيم:
مثال بعد نشان ميدهد ک77ه آرايهاي از اش77ارهگرها ب77ه چ77ه
دردي ميخورد .از اين آرايه ميت77وان ب77راي مرتبکردن
يک فهرست نامرتب به روش حبابي استفاده کرد .به جاي
اين که خود عناصر جابجا شوند ،اشارهگرهاي آنها جابجا
ميشوند.
p
3.14159
double
1.19
double
0
1
2
3
ي غيرمستقيم
ي حباب
مرتبساز7-17 مثال
void sort(float* p[], int n)
{ float* temp;
for (int i = 1; i < n; i++)
for (int j = 0; j < n-i; j++)
if (*p[j] > *p[j+1])
{ temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
تابع )(sortآرايهاي از اشارهگرها را ميگيرد .سپس درون
حلقههاي تودرتوي forبررسي ميکند که آيا مق77اديري ک77ه
اشارهگرهاي مجاور به آنها اشاره دارند ،مرتب هستند يا نه.
اگر مرتب نبودند ،جاي اش777ارهگرهاي آنها را با هم ع777وض
ميکند .در پايان به جاي اين که يک فهرس77ت مرتب داش77ته
باشيم ،آرايهاي داريم که اش77ارهگرهاي درون آن ب77ه ترتيب
قرار گرفته اند.
اشارهگري به اشارهگر ديگر 14-7
يك اشارهگر ميتواند به اشارهگر ديگري اشاره کند .مثال:
;'char c = 't
;char* pc = &c
;char** ppc = &pc
;char*** pppc = &ppc
// changes value of c to
;'***pppc = 'w
''w
حاال pcاشارهگري ب77ه متغ77ير ک77اراکتري cاس77ت ppc .اش77ارهگري ب77ه
اشارهگر pcاست و اشارهگر pppcهم به اشارهگر ppcاش77اره دارد.
pppc
ppc
pc
'\'t
c
با اين وجود ميتوان با اش77ارهگر pppcمس77تقيما ب77ه
متغير cرسيد.
اشارهگر به توابع 15-
اين بخش ممکن است کمي عجيب به نظر برسد .حقيقت
اين است ک77ه ن77ام ي77ک ت77ابع مث77ل ن77ام ي77ک آراي77ه ،ي77ک
اشارهگر ثابت است .نام تابع ،آدرسي از حافظ77ه را نش77ان
ميده77د ک77ه ک77دهاي درون ت77ابع در آن قس77مت جاي
گرفتهاند .پس بنابر قسمت قبل اگر اش77ارهگري ب77ه ت77ابع
اعالن ک77نيم ،در اص77ل اش77ارهگري ب77ه اش77ارهگر ديگر
تعريف کردهايم .اما اين تعريف ،نحو متفاوتي دارد:
// declares function f
// declares function
;)int f(int
;)int (*pf)(int
pointer pf
اشارهگر pfهمراه با * درون پرانتز قرار گرفت77ه ،يع77ني
اين که pfاشارهگري به يک تابع است .بعد از آن ي77ک
intهم درون پرانتز آمده است ،به اين معني که ت77ابعي
ک77ه pfب77ه آن اش77اره مينماي77د ،پارامتري از ن77وع int
دارد .اشارهگر pfرا ميتوانيم به شکل زير تصور کنيم:
فاي77دۀ اش77ارهگر ب77ه تواب77ع اين اس77ت ک77ه ب77ه اين طري77ق
ميتوانيم توابع مرکب بسازيم .يعني ميتوانيم يک تابع را
به عنوان آرگومان به تابع ديگر ارسال ک77نيم! اين ک77ار با
pf
استفاده از اشارهگر به تابع امکان پذير است.
f
)int f(int n
{
...
}
تابع مرکب جمع7-18 مثال
: n و عدد صحيحpf اشارهگر تابع:() در اين مثال دو پارامتر داردsum تابع
int sum(int (*)(int), int);
int square(int);
int cube(int);
int main()
{ cout << sum(square,4) << endl;
// 1 + 4 +
9 + 16
cout << sum(cube,4) << endl;
+ 64
}
//1 + 8 + 27
ت77ابع )(sumي77ک پارامتر غ77ير معم77ول دارد .ن77ام ت77ابع
ديگري به عنوان آرگومان به آن ارسال شده .هنگامي که
) sum(square,4فراخ77777واني ش77777ود ،مق77777دار
)square(1)+square(2)+square(3
) +square(4بازگش7777777777ت داده ميش7777777777ود.
چ7777ون) square(kمق7777دار k*kرا برميگردان7777د،
فراخ7777777777واني ) sum(square,4مق7777777777دار
30=16+9+4+1را محاسبه نم77777وده و بازميگردان77777د.
تعريف توابع و خروجي آزمايشي به شکل زير است:
int sum(int (*pf)(int k), int n)
{ // returns the sum f(0) + f(1) + f(2) + ... + f(n-1):
int s = 0;
for (int i = 1; i <= n; i++)
s += (*pf)(i);
return s;
}
int square(int k)
{ return k*k;
}
int cube(int k)
{ return k*k*k;
30
}
100
pfدر فهرست پارامترهاي تابع )(sumي77ک اش77ارهگر
به تابع است .اشارهگر به ت77ابعي ک77ه آن ت77ابع پارامتري از
نوع intدارد و مق77داري از ن77وع intرا برميگردان77دk .
در تابع sumاصال استفاده نشده اما حتما بايد قيد شود تا
کامپايلر بفهمد که pfبه تابعي اشاره دارد که پارامتري از
ن77777777777777777777وع intدارد .عبارت (* )i()pfمعادل با
) square(iيا ) cube(iخواهد ب77ود ،بس77ته ب77ه اين
که کدام يک از اين دو تابع به عنوان آرگومان به )(sum
ارسال شوند.
ن777ام ت777ابع ،آدرس شروع ت777ابع را دارد .پس square
آدرس شروع ت77ابع )(squareرا دارد .بن77ابراين وق77تي
ت7777ابع )(sumب7777ه ش7777کل )sum(square,4
فراخواني ش77ود ،آدرس77ي ک77ه درون squareاس77ت ب77ه
اش777ارهگر pfفرس777تاده ميش777ود .با اس777تفاده از عبارت
(* )i()pfمقدار iبه آرگومان تابعي فرستاده ميشود ک77ه
pfبه آن اشاره دارد.
NULL وNUL -16
است اما اين مقدار را به هر نوع بنيادي ديگرint ع
) از نو0( ت صفر
ثاب
:ميتوان تخصيص داد
char c = 0;
short d = 0;
0
int n = 0;
// initializes c to the char '\0'
// initializes d to the short int
// initializes n to the int 0
unsigned u = 0; // initializes u to the unsigned
int 0
float x = 0;
// initializes x to the float 0.0
مقدار صفر معناهاي گون77اگوني دارد .وق77تي ب77راي اش77ياي
عددي به کار رود ،به معناي عدد صفر اس77ت .وق77تي ب77راي
اشياي کاراکتري ب77ه ک77ار رود ،ب77ه معن77اي ک77اراکتر تهي يا
NULاست NUL .معادل کاراکتر '\ '0نيز هست .وق77تي
مقدار صفر براي اشارهگرها ب77ه ک77ار رود ،ب77ه معن77اي «هيچ
چيز» يا NULLاست NULL .يک کلمۀ کلي77دي اس77ت و
کامپايلر آن را ميشناسد .هنگ77امي ک77ه مق77دار NULLيا
صفر در يک اشارهگر قرار ميگيرد ،آن اشارهگر به خان77ه
0x0در حافظه اشاره دارد .اين خان77ۀ حافظ77ه ،ي77ک خان77ۀ
استثنايي است که قاب77ل پ77ردازش نيس77ت .ن77ه ميت77وان آن
خانه را مقداريابي کرد و نه ميت77وان مق77داري را درون آن
قرار داد .به همين دليل به « NULLهيچ چيز» ميگويند.
وقتي اشارهگري را بدون استفاده از newاعالن ميک77نيم ،خ77وب اس77ت
که ابتدا آن را NULLکنيم تا مقدار زبالۀ آن پاک شود .اما هميشه باي77د
به خاطر داشته باشيم که اشارهگر NULLرا نبايد مقداريابي نماييم:
// p points to NULL
ERROR: cannot dereference the NULL
//
;int* p = 0
;*p = 22
pointer
پس خوب است هنگام مقداريابي اشارهگرها ،احتياط کرده و بررسي کنيم
که آن اشارهگر NULLنباشد:
if (p) *p = 22; // O.K.
حاال دستور * ;p=22وقتي اجرا ميشود که pصفر نباشد .ميدانيد که
شرط باال معادل شرط زير است:
;if (p != NULL) *p = 22
اشارهگرها را نميتوان ناديده گرفت.
آنها سرعت پردازش را زياد ميکنند و کدنويس77ي را
کم.
با استفاده از اشارهگرها ميت77وان ب77ه به77ترين ش77کل از
حافظه استفاده کرد.
با به کارگيري اشارهگرها ميتوان اشيايي پيچي77دهتر و
کارآمدتر ساخت.
پايان جلسه هفتم
جلسه هشتم
« رشتههاي كاراكتري و فايلها در C++استاندارد»
ي بر اشارهگرها
مرور
رشتههاي كاراكتري در C
ورودي/خروجي رشتههاي کاراکتري
ع عضو cinو cout
چند تاب
ي Cاستاندارد
توابع كاراكتر
آرايهاي از رشتهها
توابع استاندارد رشتههاي کاراکتري
›››
استاندارد
رشتههاي کاراکتري در ++C
نگاهي دقيقتر به تبادل دادهها
ي قالببندي نشده
ورود
هدف کلي :آشنايي با کالسها و اصول اوليۀ بهکارگيري آنها.
نوع stringدر C++استاندارد
فايلها
هدف کلي:
معرفي رش77تههاي ک77اراکتري ب77ه سبک cو ++cو
نحوۀ ايجاد و دس77تکاري آنها و همچ77نين نح77وۀ
اس777تفاده از فايلهاي مت777ني ب777راي ذخيرهسازي و
بازيابي اطالعات.
هدفهاي رفتاري :انتظار ميرود پس از پايان اين جلسه بتوانيد:
رشتههاي کاراکتري به سبک Cاستاندارد را ايجاد نماييد. توابع معرفي شده عضو cinو coutرا شناخته و وظيفۀ هر يک راشرح دهيد.
رشتههاي کاراکتري به سبک ++Cاستاندارد را ايجاد نماييد. مفهوم «ورودي قالببندي شده» و «ورودي قالببن77دي نش77ده» رادانسته و هر کدام را در مکانهاي مناسب به کار ببريد.
نوع stringرا شناخته و رشتههايي از اين ن777وع ايجاد کني777د و بااستفاده از توابع خاص ،اين رشتهها را دستکاري نماييد.
اطالعات کاراکتري و رشتهاي را در يک فايل متني نوش777ته يا ازآن بخوانيد.
:مقدمه
ميش77وند هميش77ه
رايانهها پردازش
دادههايي که در
ع777دد نيس777تند .معم777وال الزم اس777ت ک777ه اطالعات
نش77انيها – مت77ون –
ک77اراکتري مث77ل ن77ام افراد –
توض77يحات – کلمات و ...ن77يز پ77ردازش گردن77د،
جستجو ش77وند ،مقايس77ه ش77وند ،ب77ه يک77ديگر الصاق
شوند يا از هم تفکيک گردند.
در اين جلسه بررسي ميک77نيم ک77ه چط77ور اطالعات
آنها را به
کاراکتري را از ورودي دريافت کنيم و يا
شکل دلخواه به خروجي بفرس77تيم .در همين راس77تا
ميکنيم که انجام اين کارها را آسان
توابعي معرفي
ميکنند.
مروري بر اشارهگرها:
يك اشارهگر متغيري است که حاوي يک آدرس از
ميباشد .نوع اين متغير از نوع مقداري است
حافظه
که در آن آدرس ذخيره شده .با استفاده از عملگر
ميتوان آدرس يک شي را پيدا کرد.
ارجاع &
ميتوانيم
همچنين با استفاده از عملگر مقداريابي *
مقداري که در يک آدرس قرار دارد را مشخص
کنيم .به تعاريف زير نگاه کنيد:
;int n = 44
;int* p = &n
رشتههاي كاراكتري در C
در زبان ++Cي77777ك «رش77777تۀ ک77777اراکتري» آرايهاي از
کاراکترهاست که اين آرايه داراي ويژگي مهم زير است:
اضافي در انتهاي آرايه وج77ود دارد ک77ه مق77دار
بخش
-1
يك
آن ،ک777اراکتر NULيع777ني '\ ‘0اس777ت .پس تع777داد ک777ل
کاراکترها در آرايه هميشه يکي بيشتر از طول رشته است.
– 2رشتۀ کاراکتري را ميتوان با لي77ترال رش77تهاي ب77ه ط77ور
مستقيم مقدارگذاري کرد مثل:
;"char str[] = "string
هفت عنصر دارد:
اين آرايه
توجه كنيد كه
'و '\ 'g' 0و ' 'nو ' 'iو ' 'rو ' 'tو ''s
–3کل يک رشتۀ کاراکتري را ميتوان مثل ي77ک متغ77ير معم77ولي
چاپ کرد .مثل:
;cout << str
در اين صورت ،همۀ کاراکترهاي درون رشتۀ ک77اراکتري strيکي
يکي به خروجي ميروند تا وقتي که به کاراکتر انتهايي NUL
برخورد شود.
– 4يک رشتۀ کاراکتري را ميت77وان مث77ل ي77ک متغ77ير معم77ولي از
ورودي دريافت کرد مثل:
;cin >> str
در اين صورت ،هم77ۀ کاراکترهاي وارد ش77ده يکي يکي درون str
جاي ميگيرند تا وقتي ک77ه ب77ه ي77ک فض77اي خ77الي در کاراکترهاي
ورودي برخورد شود .برنامهنويس بايد مطمئن باشد که آراي77ۀ str
براي دريافت همۀ کاراکترهاي وارد شده جا دارد.
– 5توابع تعريف ش777ده در سرفايل < >cstringرا
دستکاري رش77تههاي ک77اراکتري ب77ه
ميتوانيم براي
کار بگيريم .اين توابع عبارتند از:
تابع طول رشته )(strlen
توابع کپي رشته )(strcpyو )(strncpy
توابع الصاق رشتهها )(strcatو )(strncat
توابع مقايسۀ رشتهها )(strcmpو )(strncmp
و تابع استخراج نشانه . )(strtok
رشتههاي کاراکتري با كاراكتر NULخاتمه مييابند
ميدهد که کاراکتر '\ '0به رشتههاي کاراکتري الصاق ميشود:
برنامۀ کوچک زير نشان
)(int main
{ ;"char s[] = "ABCD
)for (int i = 0; i < 5; i++
;"cout << "s[" << i << "] = '" << s[i] << "'\n
}
رشتۀ کاراکتري sداراي پنج عضو است که
عضو پنجم ،کاراکتر '\ '0ميباش77د .تص77وير
خروجي اين مطلب را تاييد مينمايد.
وق777تي ک777اراکتر '\ '0ب777ه coutفرس777تاده
ميش77ود ،هيچ چ77يز چاپ نميش77ود .ح77تي
جاي خالي هم چاپ نميشود.
خط آخر خروجي ،عضو پنجم را نش77ان مي
ده77د ک77ه ميان دو عالمت آپس77تروف هيچ
چيزي چاپ نشده.
S
0 A
B
1
2 C
3 D
4 Ø
ورودي/خروجي رشتههاي کاراکتري:
در ++Cبه چند روش ميتوان رشتههاي کاراکتري
را دريافت کرده يا نمايش داد.
يک راه استفاده از عملگرهاي کالس stringاست که
بخشهاي بعدي به آن خواهيم پرداخت.
در
روش ديگر ،استفاده از توابع کمکي است که آن را
ميدهيم.
در ادامه شرح
مثال 8-2روش سادۀ دريافت و نمايش رشتههاي کاراکتري:
در برنامۀ زير يک رشتۀ کاراکتري به طول 79کاراکتر اعالن ش77ده و
کلماتي که از ورودي خوانده ميشود در آن رشته قرار ميگيرد:
)(int main
{ ];char word[80
do
{ ;cin >> word
;"if (*word) cout << "\t\"" << word << "\"\n
} );while (*word
}
چند تابع عضو cinو cout
به cinشيء فرآيند ورودي ميگويند .اين شي
شامل توابع زير است:
)(cin.getline
)(cin.get
همۀ اين توابع شامل پيشوند cinهستند زيرا آنها عض77وي از cin
ن77يز
ميباشند .به coutشيء فرآيند خروجي ميگوين77د .اين ش77ي
)(cin.ignore
شامل تابع )(cout.putاست .نحوۀ ک77اربرد هر ي77ک از اين تواب77ع
)(cin.putback
عضو را در ادامه خواهيم ديد.
)(7cin.peekه
فراخواني ) ;cin.getline(str,nباعث ميش77ود ک77ه nک77اراکتر ب7
درون strخوان77ده ش77ود و مابقي کاراکترهاي وارد ش77ده نادي77ده
گرفته ميشوند.
با دو پارامترcin.getline() تابع
اين برنامه ورودي را خط به خط به خروجي ميفرستد:
int main()
{ char line[80];
do
{ cin.getline(line,80);
if (*line) cout << "\t[" << line << "]\n";
} while (*line);
}
با سه پارامتر
cin.getline)(تابع
متن ورودي را جمله به جمله تفکيک مينمايد،برنامه زير:
)(int main
;char clause[20] {
do
;cin.getline(clause, 20, ',') {
;"if (*clause) cout << "\t[" << clause << "]\n
;while (*clause) }
}
تابع )(cin.get
ف ' 'eدر جريان ورودي را شمار
ش
اين برنام ه تعداد حر
ميكند .تا وقتي ) cin.get(chکاراکترها را با موفقيت به درون
chميخواند ،حلقه ادامه مييابد:
)(int main
{ ;char ch
;int count = 0
))while (cin.get(ch
;if (ch = = 'e') ++count
;"cout << count << " e's were counted.\n
}
)(cout.put تابع
اولين حرف از هر کلمۀ ورودي را به حرف بزرگ تبديل،برنامۀ زير
:کرده و آن را مجددا در خروجي چاپ ميکند
)(int main
;'char ch, pre = '\0 {
while (cin.get(ch))
if (pre = = ' ' || pre = = '\n') {
;cout.put(char(toupper(ch)))
;else cout.put(ch)
;pre = ch
}
}
cin.ignore() وcin.putback() توابع
تابعي آزمايش ميشود که اين تابع اعداد صحيح را از ورودي استخراج،با استفاده از برنامۀ زير
ميکند:
;)(int nextInt
)(int main
;)(int m = nextInt(), n = nextInt {
cin.ignore(80,'\n');
// ignore rest of input line
;cout << m << " + " << n << " = " << m+n << endl
}
)(int nextInt
;char ch {
;int n
while (cin.get(ch))
if (ch >= '0' && ch <= '9') // next character is a digit
cin.putback(ch);
// put it back so it can be {
cin >> n;
// read as a complite int
;break
}
;return n
}
)(cin.peek تابع
:() معادل آن است كه در مثال قبلي بودnextInt اين نسخه از تابع
)(int nextInt
;char ch {
;int n
while (ch = cin.peek())
if (ch >= '0' && ch <= '9')
;cin >> n {
;break
}
;else cin.get(ch)
;return n
}
توابع كاراكتري Cاستاندارد
در مثال 8-6به تابع )(toupperاشاره ش77د .اين فق77ط يکي
از توابعي است که ب77راي دس77تکاري کاراکترها اس77تفاده
ميش777ود .ساير ت777وابعي ک777ه در سرفايل < >ctype.hيا
< >cctypeتعريف شده به شرح زير است:
شرح
نام تابع
;)int isalnum(int c
(isalnum
اگر cکاراکتر الفبايي يا عددي باشد مق{{دار غيرص{{فر
)
وگرنه صفر را برميگرداند
;)int isalpha(int c
(isalpha
اگر cکاراکتر الفبايي باشد مقدار غيرصفر و در غير آن،
)
شرح
;)int iscntrl(int c
اگر cکاراکتر کنترلي باشد مقدار غيرصفر و در غ ير آن،
صفر را برميگرداند
;)int isdigit(int c
اگر cکاراکتر عددي باشد ،مقدار غيرصفر و در غير آن،
صفر را برميگرداند
;)int isgraph(int c
اگر cکاراکتر چاپي و غيرخالي باش د مق دار غيرص فر
وگرنه صفر را برميگرداند
;)int islower(int c
اگر cحرف کوچک باشد مقدار غيرصفر و در غ ير آن،
صفر را برميگرداند
;)int isprint(int c
اگر cکاراکتر قابل چاپ باشد مقدار غيرصفر و در غ ير
آن ،صفر را برميگرداند
نام تابع
)(iscntrl
)(isdigit
)(isgraph
)(islower
)(isprint
شرح
;)int ispunct(int c
اگر cکاراکتر چاپي به غير از حروف و اعداد و فضاي خالي باشد ،مقدار غيرص فر
برميگرداند وگرنه مقدار صفر را برميگرداند
نام تابع
)(ispunct
;)int isspace(int c
اگر cکاراکتر فضاي سفيد شامل فضاي خالي ' ' و عب ور فرم '\ 'fو خ ط
جديد '\ 'nو بازگش ت ن ورد '\ 'rو پ رش افقي '\ 'tو پ رش عم ودي
'\ 'vباشد ،مقدار غيرصفر را برميگرداند وگرنه صفر را برميگرداند
)(isspace
;)int isupper(int c
اگر cحرف بزرگ باشد ،مقدار غيرصفر برميگرداند وگرنه صفر را برميگرداند
)(isupper
;)int isxdigit(int c
اگر cيکي از ده کاراکتر عددي يا يکي از دوازده حرف ع دد ش انزدهدهي ش امل
' 'aو ' 'bو ' 'cو ' 'dو ' 'eو ' 'fو ' 'Aو ' 'Bو ' 'Cو ''D
و ' 'Eو ' 'Fباشد ،مقدار غيرصفر برميگرداند وگرنه مقدار صفر را برميگرداند
)(isxdigit
;)int tolower(int c
اگر cحرف بزرگ باشد ،کاراکتر کوچک معادل آن را برميگرداند وگرنه خود cرا
برميگرداند
)(tolower
;)int toupper(int c
اگر cحرف کوچک باشد ،کاراکتر بزرگ معادل آن را برميگرداند وگرنه خود cرا
برميگرداند
)(toupper
توجه کنيد که همۀ توابع ف77وق ي77ک پارامتر از ن77وع int
دريافت ميکنند و يک مقدار intرا برميگردانند .علت
اين است که نوع charدر اصل يک نوع صحيح است.
در عمل وقتي توابع فوق را به کار ميبرند ،يک مق77دار
charبه تابع ميفرستند و مق77دار بازگش77تي را ن77يز در
يک charذخيره ميکنند .به همين خاطر اين توابع را
به عنوان «توابع کاراکتري» در نظر ميگيريم.
آرايهاي از رشتهها
ب77ه خ77اطر داري77د ک77ه گف77تيم ي77ک آراي77ۀ دوبع77دي در حقيقت
آرايهاي يک بعدي است که هر ک77دام از اعض77اي آن ي77ک آراي77ۀ
يک بعدي ديگر است .مثال در آرايۀ دو بعدي که به ش77کل مقاب77ل
اعالن شده باشد:
];char name[5][20
اين آرايه در اصل پنج عضو دارد که هر عضو ميتواند بيست
کاراکتر داشته باشد .اگر آرايۀ فوق را با تعريف رشتههاي
کاراکتري مقايسه کنيم ،نتيجه اين ميشود که آرايۀ باال يک
آرايۀ پنج عنصري است که هر عنصر آن يک رشتۀ کاراکتري
بيست حرفي است .اين آرايه را ميتوانيم به شکل مقابل
تصور کنيم.
1
9
1
8
1
7
1
6
1
5
1
4
1
3
1
2
11
1
0
9
8
7
6
5
4
3
2
1
0
0
1
2
3
4
از طريق ] name[0و ] name[1و ] name[2و ] name[3و ] name[4ميتوانيم
به هر يک از رشتههاي کاراکتري در آرايۀ باال دسترسي داشته باشيم .يعني آرايۀ
nameگرچه به صورت يک آرايۀ دوبعدي اعالن شده ليکن به صورت يک آراي{{ۀ
يک بعدي با آن رفتار ميشود.
آرايهاي از رشتههاي کاراکتري
برنامۀ زير چند رشتۀ کاراکتري را از ورودي ميخواند و آنها را در يک آرايه
:ذخيره کرده و سپس مقادير آن آرايه را چاپ ميکند
)(int main
;char name[5][20] {
;int count=0
;"cout << "Enter at most 4 names with at most 19 characters:\n
; while (cin.getline(name[count++], 20))
;count-;"cout << "The names are:\n
for (int i=0; i<count; i++)
;cout << "\t" << i << ". [" << name[i] << "]" << endl
}
يك آرايۀ رشتهاي پويا
اين برنامه نشان ميده77د ک77ه چگون77ه ميت77وان از ک77اراکتر
' '$به عنوان ک77اراکتر نگهبان در ت77ابع )(getlineاس77تفاده
کرد .مثال زير تقريبا معادل مثال 9-9است .برنام77ۀ زي77ر
مجموعهاي از اسامي را ميخواند ،طوري که هر اس77م روي
يک خط نوشته ميشود و هر اس777م با ک777اراکتر '\ 'nپايان
ميياب77د .اين اسامي در آراي77ۀ nameذخ77يره ميش77وند.
سپس نامهاي ذخيره شده در آرايۀ nameچاپ ميشوند:
)(int main
;char buffer[80] {
;cin.getline(buffer,80,'$')
;char* name[4]
;name[0] = buffer
;int count = 0
for (char* p=buffer; *p ! '\0'; p++)
if (*p == '\n')
p = '\0';
// end name[count]* {
name[++count] = p+1; // begin next name
}
;"cout << "The names are:\n
for (int i=0; i<count; i++)
;cout << "\t" << i << . [" << name[i] << "]" << endl
}
مقداردهي يك آرايۀ رشتهاي
را مقداردهي کرده و سپس مقادير آن را چاپname اين برنامه هم آرايۀ رشتهاي
:مينمايد
)(int main
;char* name[]= { "Mostafa Chamran", "Mehdi Zeinoddin", "Ebrahim Hemmat" }{
;"cout << "The names are:\n
for (int i = 0; i < 3; i++)
"cout << "\t" << i << ". [" << name[i] << "]
;endl <<
}
توابع استاندارد رشتههاي کاراکتري:
7تههاي
سرفايل < >cstringک77ه ب77ه آن «کتابخان77ۀ رش 7
ميگويند ،شامل خ77انوادۀ ت77وابعي اس77ت
کاراکتري» هم
دستکاري رشتههاي کاراکتري خيلي مفيدند.
که براي
آنها يع77ني ت77ابع ط77ول رش77ته را
سادهترين
مثال بعدي
نشان ميده77د .اين ت77ابع ،ط77ول ي77ک رش77تۀ ک77اراکتري
ارسال شده به آن (يعني تعداد کاراکترهاي آن رش77ته)
برميگرداند.
را
:)(strlen تابع
.() استstrlen برنامۀ زير يک برنامۀ آزمون ساده براي تابع
ه77 کs تۀ77داد کاراکترهاي درون رش77 تع، فراخواني ميشودstrlen(s) وقتي
: بازگشت داده ميشود،گرفتهاند
قرارNUL قبل از کاراکتر
>include <cstring
)(int main
;"char s[] = "ABCDEFG {
;cout << "strlen(" << s << ") = " << strlen(s) << endl
;cout << "strlen(\"\") = " << strlen("") << endl
;char buffer[80]
;cout << "Enter string: "; cin >> buffer
;cout << "strlen(" << buffer << ") = " << strlen(buffer) << endl
}
#
:)(strrchr(), strchr(), strstr توابع
: نشان ميدهدs مکانيابي يک کاراکتر يا زيررشتۀ خاص را در رشتۀ کاراکتري،برنامۀ زير
>include <cstring
)(int main
;".char s[] = "The Mississippi is a long river {
;"cout << "s = \"" << s << "\"\n
;char* p = strchr(s, ' ')
;"cout << "strchr(s, ' ') points to s[" << p - s << "].\n
;p = strchr(s, 'e')
;"cout << "strchr(s, 'e') points to s[" << p - s << "].\n
;p = strrchr(s, 'e')
;"cout << "strrchr(s, 'e') points to s[" << p - s << "].\n
;p = strstr(s, "is")
cout << "strstr(s, \"is\") points to s[" << p – s
;"n\.]" <<
;p = strstr(s, "isi")
cout << "strstr(s, \"is\") points to s[" << p – s
;"n\.]" <<
if (p == NULL) cout << "strstr(s, \"isi\") returns
;"NULL\n
}
#
:)(strcpy ع
تاب
: چه تاثيري داردstrcpy(s1, s2) برنامۀ زير نشان ميدهد که فراخواني
#
#
>include <iostream
>include <cstring
)(int main
;"char s1[] = "ABCDEFG {
;"char s2[] = "XYZ
;"cout << "Before strcpy(s1,s2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
;strcpy(s1,s2)
;"cout << "After strcpy(s1,s2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
}
)(strncpy: تابع
: چه اثري داردstrncpy(s1, s2, n)برنامۀ زير بررسي ميکند که فراخواني
)(int main
;"char s1[] = "ABCDEFG {
;"char s2[] = "XYZ
;"cout << "Before strncpy(s1,s2,2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
;strncpy(s1,s2,2)
;"cout << "After strncpy(s1,s2,2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
}
)(strcat: تابع الصاق رشته
: چه تاثيري داردstrcat(s1, s2) برنامۀ زير بررسي ميکند که فراخواني
)(int main
;"char s1[] = "ABCDEFG {
;"char s2[] = "XYZ
;"cout << "Before strcat(s1,s2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
;strcat(s1,s2)
;"cout << "After strcat(s1,s2):\n
cout << "\ts1 = [" << s1 << "], length = " << strlen(s1)
;endl <<
cout << "\ts2 = [" << s2 << "], length = " << strlen(s2)
;endl <<
}
استاندارد :
رشتههاي کاراکتري در ++C
رشتههاي کاراکتري که تاکنون تشريح شد ،در زبان Cاستفاده ميش77وند
و البته بخش
مهمي از ++Cنيز محسوب ميشوند زيرا وسيلۀ مفي77دي ب77راي پ77ردازش
سريع دادهها
هستند .اما اين سرعت پردازش ،هزينهاي هم دارد :خطر خطاهاي زمان
اجرا.
ين خطاها معموال از اين ناش77ي ميش77وند ک77ه فق77ط ب77ر ک77اراکتر NULب77ه
عنوان پايان رشته
تکيه ميش77ود ++C .رش77تههاي ک77اراکتري خاص77ي ن77يز دارد ک77ه امنتر و
مطمئنتر هستند.
در اين رشتهها ،طول رشته نيز درون رشته ذخيره ميشود و ل77ذا فق77ط ب77ه
کاراکتر NUL
براي مشخص نمودن انتهاي رشته اکتفا نميشود.
نگاهي دقيقتر به تبادل دادهها
وقتي ميخواهيم دادههايي را وارد کنيم ،اين دادهها
را در قالب مجموعهاي از کاراکترها تايپ ميکنيم.
{ارج از
{ه خ{
{ايجي را ب{
همچنين وقتي ميخواهيم نت{
{وعهاي از
{الب مجم{
{ايج در ق{
برنامه بفرستيم ،اين نت{
{ت که اين
کاراکترها نمايش داده ميشوند .الزم اس{
کاراکترها به نحوي براي برنامه تفس{{ير ش{{وند .مثال
وقتي قصد داريم يک عدد صحيح را وارد کنيم ،چن{{د
کاراکتر عددي تايپ ميکنيم
حاال ساز و کاري الزم است که از اين کاراکترها
يک مقدار صحيح بسازد و به برنامه تحويل دهد.
همچنين وقتي قصد داريم يک عدد اعشاري را به
خروجي بفرستيم ،بايد با استفاده از راهکاري،
آن عدد اعشاري به کاراکترهايي تبديل شود ت{{ا
در خروجي نمايش يابد ++C .بر عهده دارند.
جريانها اين وظايف را در ++Cبر عهده دارند .جريانها
شبيه پااليهاي هستند که دادهها را به کاراکتر تبديل ميکنند و
کاراکترها را ب{{ه دادههايي از ي{{ک ن{{وع بنيادي تب{{ديل
مينمايند .به طور کلي ،وروديها و خروجيها را يک کالس
جريان به نام streamکنترل ميکن{{د .اين کالس خ{{ود ب{{ه
زيرکالسهايي تقسيم ميشود:
شيء istreamجرياني است که دادههاي م{{ورد
{د،
نياز را از کاراکترهاي وارد شده از صفحه کلي{
فراهم ميکند .شيء ostreamجرياني است که
دادههاي حاصل را به کاراکترهاي خروجي قابل
{د.
{ديل مينماي{
نمايش روي صفحۀ نمايشگر تب{
شيء ifstreamجرياني است که دادههاي مورد
نياز را از دادههاي داخ{{ل ي{{ک فاي{{ل ،فراهم
ميکند .ش{{يء ofstreamجرياني اس{{ت که
{يره
{ل ذخ{
{ک فاي{
{ل را درون ي{
دادههاي حاص{
مينمايد .اين جريانها و طريقۀ استفاده از آنها
را در ادامه خواهيم ديد.
ي براي كنترل کردن يك حلق ه :
استفاده از عملگر بيرونكش
)(int main
{ ;int n
)while (cin >> n
;cout << "n = " << n << endl
}
ورودي قالببندي نشده:
{راي ورودي دارد.
{ع مختلفي ب{
سرفايل < >iostreamتواب{
اين توابع براي وارد کردن کاراکترها و رشتههاي کاراکتري
به کار ميروند که کاراکترهاي فض{{اي س{{فيد را نادي{{ده
نميگيرند.
رايجترين آنها ،تابع )(cin.getبراي دريافت يک کاراکتر
تکي و تابع )(cin.getlineبراي دريافت يک رشتۀ کاراکتري
است.
)(cin.get: دريافت كاراكترها با استفاده از تابع
while (cin.get(c))
if (c >= 'a' && c <= 'z') c += 'A' - 'a'; // capitalize c {
;cout.put(c)
}
)(cin.getline: وارد كردن يک رشتۀ کاراکتري به وسيلۀ تابع
برنامۀ زير نشان ميدهد که چطور ميتوان دادههاي متني را خط به خط از ورودي خوانده و
:::درون يک آرايۀ رشتهاي قرار داد
const int LEN=32;
// maximum word length
const int SIZE=10;
// array size
typedef char Name[LEN]; // defines Name to be a C_string type
)(int main
Name martyr[SIZE]; // defines martyr to be an array of 10 names {
;int n=0
while(cin.getline(martyr[n++], LEN) && n<SIZE)
;
;n-for (int i=0; i<n; i++)
;cout << '\t' << i+1 << ". " << martyr[i] << endl
}
نوع stringدر C++استاندارد:
در ++Cاستاندارد نوع دادهاي خاصي به نام stringوجود دارد که مشخصات اين نوع
در سرفايل < >stringتعريف شده است .براي آشنايي با اين نوع جدي77د ،از طريق77ۀ
ميکنيم .اشيايي که از نوع stringهستند به چند طري77ق
اعالن و مقداردهي آن شروع
ميتوانند اعالن و مقداردهي شوند:
;string s1
// s1 contains 0 characters
;"string s2 = "PNU University
// s2 contains 14 characters
;)'*' string s3(60,
// s3 contains 60 asterisks
;string s4 = s3
// s4 contains 60 asterisks
;)string s5(s2, 4, 2
"// s5 is the 2-character string "Un
ع string
استفاده از نو
کد زير يک مجموعه کاراکتر را از ورودي ميگيرد و سپس بعد از هر کاراکتر
" "Eيک عالمت ويرگول ' ',اضافه مينمايد.
"The
مثال اگر عبارت
"SOFTWARE MOVEMENT is began
وارد شود ،برنامۀ زير ،آن را به جملۀ زير تبديل ميکند:
The SOFTWARE, MOVE,ME,NT is began
;string word
متن برنامه اين چنين است:
;int k
)while (cin >> word
{ ;k = word.find("E") + 1
))(if (k < word.length
)";word.relace(k, 0, ",
;' ' << cout << word
}
فايلها
يکي از مزيتهاي رايانه ،قدرت نگهداري اطالعات
حجيم است .فايلها اين قدرت را به رايانه ميدهند.
{ايد
{ت ،ش{
{ود نميداش{
{ل وج{
اگر چيزي به نام فاي{
رايانهها به شکل امروزي توس{{عه و کاربرد پي{{دا
نميکردند.
چون اغلب برنامههاي امروزي با فايلها سر و کار
دارند ،يک برنامهنويس الزم است که با فايل آش{{نا
باشد و بتواند با اس{{تفاده از اين امک{{ان ذخ{{يره و
بازيابي ،کارايي برنامههايش را ارتقا دهد.
پردازش فايل در ++Cبس{{{{يار شبيه تراکنشهاي
معمولي ورودي و خروجي است زيرا اينها هم{{{ه از
اشياي جريان مشابهي بهره ميبرند .جريان fstream
براي تراکنش برنام{{ه با فايلها ب{{ه کار ميرود.
fstreamنيز به دو زيرش{{اخۀ ifstreamو ofstream
تقسيم ميشود.
{ل
جريان ifstreamبراي خواندن اطالعات از يک فاي{
به کار ميرود و جريان ofstreamب{{راي نوش{{تن
اطالعات درون يک فايل استفاده ميشود.
فراموش نکنيد که اين جريانها در سرفايل < >fstreamتعري{{{ف
شدهاند.
پس بايد دس{{تور پيشپردازن{{دۀ >include <fstreamرا ب{{ه
ابتداي برنامه بيافزاييد .سپس ميتوانيد عناصري از نوع جريان فايل
به شکل زير تعريف کنيد:
#
)";ifstream readfile("INPUT.TXT
)";ofstream writefile("OUTPUT.TXT
طبق کدهاي فوق readfile ،عنصري است که دادهها را از فايلي به نام
INPUT.TXTميخوان{{د و writefileن{{يز عنصري اس{{ت که
اطالعاتي را در فايلي به نام OUTPUT.TXTمينويسد.
اکنون ميتوان با استفاده از عملگر >> دادهها را به درون readfile
خواند و با عملگر << اطالعات را درون writefileنوشت .به مثال زير
توجه کنيد.
يک دفتر تلفن
چند نام و تلفن مربوط به هر يک را به ترتيب از کاربر دريافت کرده،برنامۀ زير
کاربر براي پايان دادن. ذخيره ميکندPHONE.TXT و در فايلي به نام
. را تايپ کند0 به ورودي بايد عدد
>include <fstream
#
>include <iostream#
;using namespace std
)(int main
;ofstream phonefile("PHONE.TXT") {
;long number
;string name
;" :cout << "Enter a number for each name. (0 for quit)
) ; ; ( for
;" :cout << "Number {
;cin >> number
;if (number == 0) break
;' ' << phonefile << number
;" :cout << "Name
;cin >> name
;' ' << phonefile << name
;cout << endl
}
}
جستجوي يک شماره در دفتر تلفن
##
فايل توليد شده توسط برنامۀ قبل را به کار ميگيرد،اين برنامه
:و درون آن به دنبال يک شماره تلفن ميگردد
>include <fstream
>include <iostream
;using namespace std
)(int main
;ifstream phonefile("PHONE.TXT") {
;long number
;string name, searchname
;bool found=false
;" :cout << "Enter a name for findind it's phone number
;cin >> searchname
;cout << endl
while (phonefile >> number)
;phonefile >> name {
if (searchname == name)
;cout << name << ' ' << number << endl {
;found = true
}
if (!found) cout << searchname
;is not in this phonebook." << endl " <<
}
پايان جلسه هشتم
جلسه نهم
«شيگرايي»
:آنچه در اين جلسه مي خوانيد
-1اعالن كالسها
-2سازندهها
-3فهرست مقداردهي در سازندهها
-4توابع دستيابي
-5توابع عضو خصوصي
ي
كپ
سازندۀ
6
›››
-7نابود کننده
- 8اشياي ثابت
-9اشارهگر به اشيا
-10اعضاي دادهاي ايستا
-11توابع عضو ايستا
هدف کلي :
آشنايي با کالسها و اصول اوليۀ
بهکارگيري آنها.
هدفهاي رفتاري:
انتظار ميرود پس از پايان اين جلسه بتوانيد:
نحوۀ اعالن «کالسها» را بدانيد و اعضاي يک کالس را برشماريد. تفاوت بين اعضاي «عمومي» و «خصوصي» را شرح داده و نح777وۀ اعالن هرکدام را بيان کنيد.
«تابع سازنده» را شناخته و وظيفۀ آن را شرح دهيد. روشهاي گوناگون مقداردهي با استفاده از فهرست مقداردهي را بدانيد. «تابع سازندۀ کپي» را معرفي کرده و وظيفۀ آن را شرح دهيد. -اعضاي «ايستا» را تعريف کرده و نحوۀ اعالن و استفاده از آنها را بدانيد.
مقدمه
«شيگرايي» رهيافت جديدي ب77ود ک77ه ب77راي
پاره اي از مشکالت برنام77ه نويس77ي راه ح77ل
داشت .اين مضمون از دنياي فلسفه به جهان
برنامهنويسي آمد و کمک کرد ت77ا معض77الت
توليد و پشتيباني نرمافزار کمتر شود.
اشيا را ميتوان با توجه به مشخصات ورفتار
آنها دسته بندي کرد.
در بحث ش777يگرايي ب777ه دس777تهها «کالس»
ميگوين77د و ب77ه نمونههاي هر کالس «ش77ي»
گفته ميشود.
مشخصات هر شي را «ص77فت» مينامن77د و ب77ه
رفتارهاي هر شي «متد» ميگويند.
برنامهنويسي شيگرا بر سه ستون استوار است:
الف .بس{{تهبندي :يع ني اين ک ه دادههاي
مرتب ط ،با هم ترکيب ش وند و جزييات
پيادهسازي مخفي شود.
ب .وراثت :در دنياي واقعي ،وراثت ب ه اين
معناست که يک ش ي وق تي متول د ميش ود،
خصوص يات و ويژگيهايي را از وال د خ ود ب ه
همراه دارد .
امتياز وراثت در اين اس77ت ک77ه از ک77دهاي
مشترک اس77تفاده ميش77ود و عالوه ب77ر اين
که ميتوان از کدهاي قبلي استفاده مج77دد
کرد ،در زمان ن7777يز صرفهجويي ش7777ده و
اس77777تحکام منطقي برنام77777ه هم افزايش
مييابد.
ج .چند ريختي :که به آن چندشکلي هم
ميگويند به معناي يک چيز بودن و چن د
شکل داشتن است .چن دريختي بيش تر در
وراثت معنا پيدا ميکند.
اعالن كالسها
کد زير اعالن يک کالس را نشان ميدهد.
class Ratio
{ public:
;)void assign(int, int
;)(viod print
private:
;int num, den
;}
اعالن کالس با کلمۀ کليدي classشروع
ميشودسپس نام کالس ميآيد.
اعالن اعضاي کالس درون يک بلوک انجام ميشود
و سرانجام ي77ک س77ميکولن بع77د از بل77وک نش77ان
ميدهد که اعالن کالس پايان يافته است.
عبارت publicو عبارت . privateهر عض77وي ک77ه
ذيل عبارت publicاعالن شود ،يک «عضو عمومي»
محسوب ميشود و هر عض77وي ک77ه ذي77ل عبارت
privateاعالن ش777ود ،ي777ک «عض777و خصوص777ي»
محسوب ميشود.
سازندهها
وظيفۀ تابع سازنده اين است که حافظۀ الزم را براي
شيء جديد تخصيص داده و آن را مقداردهي نمايد
و با اجراي وظايفي که در تابع سازنده منظور ش77ده،
شيء جديد را براي استفاده آماده کند.
هر کالس ميتواند چندين سازنده داشته باش77د .در
حقيقت ت77ابع سازنده ميتوان77د چندش77کلي داش77ته
باشد.
سازندهها ،از طريق فهرست پارامترهاي متفاوت
از يکديگر تفکيک ميشوند .به مثال بعدي نگاه کنيد.
مثال 9-5افزودن چند تابع سازندۀ ديگر به كالس Ratio
class Ratio
{ public:
} ;Ratio() { num = 0; den = 1
} ;Ratio(int n) { num = n; den = 1
} ;Ratio(int n, int d) { num = n; den = d
} ;void print() { cout << num << '/' << den
private:
;int num, den
;}
اين نسخه از كالس Ratioسه سازنده دارد:
اولي هيچ پارامتري ندارد و ش يء اعالن ش ده را
با مقدار پيشفرض 0و 1مقداردهي ميکند.
دومين سازنده ي ک پارامتر از ن وع intدارد و
شيء اعالن شده را طوري مقداردهي ميکند که
حاصل کسر با مقدار آن پارامتر برابر باشد.
سومين سازنده نيز همان سازندۀ مثال 2-4
است.
ي77ک کالس ميتوان77د سازندههاي مختلفي داش77ته
باشد .سادهترين آنها ،سازندهاي اس77ت ک77ه هيچ
پارامتري ندارد .به اين سازنده سازندۀ پيشفرض
ميگويند.
اگر در يک کالس ،سازندۀ پيشفرض ذکر
نشود ،کامپايلر به طور خودکار آن را براي
کالس مذکور ايجاد ميکند.
فهرست مقداردهي در سازندهها
سازندهها اغلب به غير از مقداردهي دادههاي
عضو يک شي ،کار ديگري انجام نميدهند .به
همين دلي77ل در ++Cي77ک واح77د دس77توري
مخصوص پيشبيني شده که تولي777د سازنده را
تسهيل مينمايد .اين واحد دستوري فهرس77ت
مقداردهي نام دارد.
به سومين سازنده در مثال 9-5دقت کنيد .اين سازنده را
ميتوانيم با استفاده از فهرست مق داردهي ب ه ش کل زي ر
خالصه کنيم:
} { )Ratio(int n, int d) : num(n), den(d
مثال 9-6استفاده از فهرست مقداردهي در كالس Ratio
class Ratio
{ public:
} { )Ratio() : num(0) , den(1
} { )Ratio(int n) : num(n) , den(1
} { )Ratio(int n, int d) : num(n), den(d
private:
;int num, den
;}
توابع دستيابي
دادههاي عض و ي ک کالس معم وال ب ه ص ورت
خصوصي ( )privateاعالن ميشوند تا دستيابي به
آنها محدود باشد اما همين امر باعث ميشود
ک ه نت وانيم در مواق ع لزوم ب ه اين دادهها
دسترسي داشته باشيم .براي ح ل اين مش کل از
ت وابعي با عن وان تواب ع دس تيابي اس تفاده
ميکنيم.
تابع دستيابي يک تابع عمومي عضو کالس است و
به همين دليل اجازۀ دسترسي ب77ه اعض77اي دادهاي
خصوصي را دارد.
با استفاده از توابع دستيابي فق77ط ميت77وان اعض77اي
دادهاي خصوصي را خوان77د ولي نميت77وان آنها را
دستکاري کرد.
Ratio افزودن توابع دستيابي به كالس9-8 مثال
class Ratio
{ public:
Ratio(int n=0, int d=1) : num(n) ,
den(d) { }
int numerator() { return num; }
int denomerator() { return den; }
private:
int num, den;
};
() مقادير موجودdenumerator () وnumerator در اينجا توابع
.در دادههاي عضو خصوصي را نشان ميدهند
توابع عضو خصوصي
توابع عض و را گ اهي ميت وانيم ب ه ش کل ي ک عض و
خصوصي کالس معرفي ک نيم .واضح اس ت ک ه چ نين
ت ابعي از داخ ل برنام ۀ اص لي ب ه هيچ عن وان قاب ل
دستيابي نيست .اين تابع فقط ميتوان د توس ط ساير
توابع عضو کالس دستيابي شود .به چ نين ت ابعي ي ک
تابع سودمند محلي ميگوييم.
در برنام77ه زي77ر ،کالس Ratioداراي ي77ک
مثال 9-9استفاده از توابع عضو خصوصي
Ratioست.
تابع عضو خصوصي به نام )(toFloatا
class
معادل{
وظيف77ۀتابع م77ذکور اين اس77ت ک77ه public:
} { )Ratio(int n=0, int d=1) : num(n), den(d
برگرداند
را
کسري
عدد
يک
شناور
مميز
<< void print() { cout << num << '/' << den
} ;endl
} ;void printconv() { cout << toFloat() << endl
private:
اين تابع فقط درون بدنۀ ت77ابع عض77و
;int num, den
)(printconvاس777تفاده ش777ده و ب777ه
;)(double toFloat
انجام وظيف77ۀ آن کم77ک مينماي77د و
;}
هيچ نقشي در برنامۀ اصلي ندارد.
سازندۀ كپي
:ميدانيم که به دو شيوه ميتوانيم متغير جديدي تعريف نماييم
;int x
;int x=k
در روش اول متغيري به نام xاز نوع intايجاد ميش7ود.
در روش دوم هم همين ک7777ار انجام ميگ7777يرد با اين
تفاوت که پس از ايجاد xمقدار موجود در متغير kک77ه
از قبل وجود داشته درون xکپي ميش77ود .اص77طالحا x
يک کپي از kاست.
;)Ratio y(x
کد باال يک شي به نام yاز نوع Ratioايجاد
ميکند و تمام مشخصات ش777يء xرا درون
آن قرار ميده777د .اگر در تعري777ف کالس،
سازندۀ کپي ذکر نش7777ود (مث7777ل هم7777ۀ
کالسهاي قبلي) ب77ه ط77ور خودک77ار ي77ک
سازندۀ کپي پيشفرض ب7777ه کالس افزوده
خواهد شد.
مثال 9-10افزودن يك سازندۀ كپي به كالس Ratio
{ :public
)} { Ratio(int n=0, int d=1) : num(n), den(d
)} { Ratio(const Ratio& r) : num(r.num), den(r.den
} ;void print() { cout << num << '/' << den
:private
;int num, den
};
در مث77ال باال ،ت77ابع سازندۀ کپي ط77وري تعري77ف ش77ده ک77ه
عنصرهاي numو denاز پارامتر rب77777777ه درون عنصرهاي
متناظر در شيء جديد کپي شوند.
سازندۀ کپي در سه وضعيت فرا خوانده ميشود:
– 1وقتي که يک شي هنگام اعالن از روي شيء ديگر کپي
شود.
– 2وقتي که يک شي به وسيلۀ مقدار به ي77ک ت77ابع ارسال
شود.
– 3وقتي که يک شي به وسيلۀ مقدار از يک تابع بازگشت
داده شود .
نابود کننده
وقتي که يک شي ايجاد ميش77ود ،ت77ابع سازنده ب77ه ط77ور
خودکار براي ساختن آن فراخ77واني ميش77ود .وق77تي ک77ه
شي به پايان زندگياش برسد ،تابع عضو ديگري به طور
فقط
کالس
هر
خودک77ار فراخ77واني ميش77ود ت77ا ن77ابودکردن آن ش77ي را
نابودکننده
نابودکننده ناميده ميشود .
يکعضو،
مديريت کند .اين تابع
سازنده وظيفه دارد ت77ا من77ابع الزم
را ب77راي ش77ي تخص77يص ده77د و
.دارددارد آن من77ابع
نابودکننده وظيف77ه
را آزاد کند.
Ratio افزودن يك نابودكننده به كالس9-12 مثال
class Ratio
{ public:
Ratio() { cout << "OBJECT IS BORN.
\n"; }
~Ratio() { cout << "OBJECT DIES.\n"; }
private:
int num, den;
};
اشياي ثابت
اگر قرار است شيئي بسازيد که در طول اجراي برنامه هيچگاه تغيير
نميکند ،بهتر است منطقي رفتار کنيد و آن ش77ي را ب77ه ش77کل ث77ابت
اعالن نماييد .اعالنهاي زير چند ثابت آشنا را نشان ميدهند:
اش77يا را ن77يز ميت77وان با اس77تفاده از
عبارت constبه صورت يک ش77يء
ثابت اعالن کرد:
;' ' = const char BLANK
;const int MAX_INT = 2147483647
const
RatioPI
;)PI(22,7
const
double
=
;3.141592653589793
;)void int(float a[], const int SIZE
اشارهگر به اشيا
ميتوانيم اشارهگر به اشياي کالس ن77يز داش77ته
باشيم .از آنجا که يک کالس ميتواند اش77ياي
دادهاي متنوع و متفاوتي داشته باشد ،اشارهگر
به اشيا بسيار سودمند و مفيد است.
اشارهگر به اش77يا ب77راي ساختن فهرس77تهاي
پيوندي و درختهاي دادهاي به کار ميرود.
class X
{ public:
int data;
};
main()
{ X* p = new X;
(*p).data = 22;
استفاده از اشارهگر به اشيا9-13 مثال
// equivalent to: p->data = 22;
cout << "(*p).data = " << (*p).data << " = " << p->data << endl;
p->data = 44;
cout << " p->data = " << (*p).data << " = " << p->data << endl;
}
در اين مثال p ،اشارهگري ب77ه ش77يء xاس77ت .پس
* pيک شيء xاس77ت و (* data.)pدادۀ عض77و
آن شي را دستيابي ميکند.
حتما باي777د هنگ777ام اس777تفاده از * pآن را درون
پرانتز قرار دهيد زي77را عملگر انتخ77اب عض77و ().
تقدم باالتري نسبت ب777ه عملگر مق777داريابي (*)
دارد.
اگر پرانتزها قيد نش77وند و فق77ط * p.dataنوش77ته
شود ،کامپايلر اين خ77ط را ب77ه ص77ورت *()p.data
تفسير خواهد کرد که اين باعث خطا ميشود.
مثال بعدي اهميت بيشتري دارد و کاربرد اشارهگر به اشيا را بهتر
نشان ميدهد.
مثال 9-14فهرستهاي پيوندي با استفاده از كالس Node
به کالسي که در زير اعالن شده دقت کنيد:
class Node
{ public:
Node(int d, Node* p=0) : data(d),
} { )next(p
;int data
;Node* next
;}
عبارت باال کالسي به نام Nodeتعريف ميکند
ک77ه اش77ياي اين کالس داراي دو عض77و دادهاي
هس77تند ک77ه يکي متغ77يري از ن77وع intاس77ت و
ديگري يک اشارهگر از نوع همين کالس .اين
کار واقعا ممکن است و باعث ميش77ود بت77وانيم
يک شي را با استفاده از همين اشارهگر به شيء
ديگر پيوند دهيم و يک زنجيره بسازيم.
اگر اشياي qو rو sاز نوع Nodeباش7ند ،ميت77وانيم
پيوند اين سه شي را به صورت زير مجسم کنيم:
s
q
r
int
data
int
data
int
data
*Node
next
*Node
next
*Node
next
يء77و دادهاي ش77ور هر دو عض77ه چط77به تابع سازنده نيز دقت کنيد ک
.جديد را مقداردهي ميکند
int main()
{ int n;
Node* p;
Node* q=0;
while (cin >> n)
{ p = new Node(n, q);
q = p;
}
for ( ; p->next; p = p->next)
cout << p->data << " -> ";
cout << "*\n";
}
q
int data
.شکل زير روند اجراي برنامه را نشان ميدهد
Node* next
q
int data
Node* next
قبل از شروع حلقه- الف
p پس از اولين تکرار حلقه- ب
int data
Node* next
q
int data
Node* next
int data
Node* next
پس از دومين تکرار حلقه- ج
p
int data
Node* next
اعضاي دادهاي ايستا
هر وقت که شيئي از روي يک کالس ساخته ميش777ود ،آن
شي مستقل از اشياي ديگر ،دادههاي عضو خ77اص خ77ودش
را دارد .گاهي الزم است ک77ه مق77دار ي77ک عض77و دادهاي در
همۀ اشيا يکسان باشد .اگر اين عضو مفروض در همۀ اشيا
تکرار شود ،هم از کارايي برنامه ميکاه77د و هم حافظ77ه را
تلف ميکند .در چنين مواقعي به77تر اس77ت آن عض77و را ب77ه
عنوان يک عضو ايستا اعالن کنيم.
عضو ايستا عضوي است که فقط يک نمونه از آن ايجاد ميش77ود و هم77ه اش77يا از همان
نمونۀ مشترک اس77تفاده ميکنن77د .با اس77تفاده از کلم77ۀ کلي77دي staticدر شروع اعالن
متغير ،ميتوانيم آن متغير را به صورت ايستا اعالن نماييم .ي77ک متغ77ير ايس77تا را فق77ط
بايد به طور مستقيم و مستقل از اشيا مقداردهي نمود .کد زير نحوۀ اعالن و مقداردهي
يک عضو دادهاي ايستا را بيان ميکند:
class X
{ public:
// declaration of n as a static data member
;static int n
;}
// definition of n
;int X::n = 0
خط آخر نشان ميدهد که متغيرهاي ايستا را بايد ب77ه ط77ور مس77تقيم و مس77تقل از اش77يا
مقداردهي کرد.
متغيرهاي ايستا به ط77ور پيشفرض با ص77فر مق77داردهي اولي77ه
ميش77وند .بن77ابراين مق77داردهي صريح ب77ه اين گون77ه متغيرها
ضروري نيست مگر اين که بخواهيد يک مقدار اوليۀ غير ص77فر
داشته باشيد.
مثال 9-15يك عضو دادهاي ايستا
کد زير ،کالسي به نام widgetاعالن ميکند که اين کالس ي77ک
عضو دادهاي ايستا به نام countدارد .اين عض77و ،تع77داد اش77ياي
widgetکه موج77ود هس77تند را نگ77ه ميدارد .هر وقت ک77ه ي77ک
شيء widgetساخته ميش77ود ،از طري77ق سازنده مق77دار count
يک واحد افزايش ميياب77د و هر زمان ک77ه ي77ک ش77يء widget
ن77ابود ميش77ود ،از طري77ق نابودکنن77ده مق77دار countي77ک واح77د
کاهش مييابد:
class Widget
{ public:
Widget() { ++count; }
~Widget() { --count; }
static int count;
Now there are 2 widgets.
Now there are 6 widgets.
Now there are 2 widgets.
Now there are 3 widgets.
};
int Widget::count = 0;
main()
{ Widget w, x;
cout << "Now there are " << w.count << " widgets.\n";
{ Widget w, x, y, z;
cout << "Now there are " << w.count << " widgets.\n";
}
cout << "Now there are " << w.count << " widgets.\n";
Widget y;
cout << "Now there are " << w.count << " widgets.\n";
توجه کني77د ک77ه چگون77ه چهار ش77يء widgetدرون بل77وک
داخلي ايجاد شده است .هنگامي ک77ه اج77راي برنام77ه از آن
بلوک خارج ميشود ،اين اشيا نابود ميش77وند و ل77ذا تع77داد
کل widgetها از 6به 2تقليل مييابد.
يک عضو دادهاي ايستا مثل يک متغير معمولي است :فق77ط
يک نمونه از آن موجود است بدون توج77ه ب77ه اين ک77ه چ77ه
تعداد شي از آن کالس موج77ود باش77د .از آنجا ک77ه عض77و
دادهاي ايستا عض77وي از کالس اس77ت ،ميت77وانيم آن را ب77ه
شکل يک عضو خصوصي نيز اعالن کنيم.
يك عضو دادهاي ايستا و خصوصي9-16 * مثال
class Widget
{ public:
Widget() { ++count; }
~Widget() { --count; }
int numWidgets() { return count; }
private:
static int count;
};
int Widget::count = 0;
main()
{ Widget w, x;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
{ Widget w, x, y, z;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
}
cout << "Now there are " << w.numWidgets() << " widgets.\n";
Widget y;
cout << "Now there are " << w.numWidgets() << " widgets.\n";
}
اين برنامه مانند مثال 9-15کار ميکند با اين تفاوت که متغ77ير
ايستاي countب77ه ش77کل ي77ک عض77و خصوص77ي اعالن ش77ده و ب77ه
همين دلي77ل ب77ه ت77ابع دس77تيابي )(numWidgetsنياز داريم ت77ا
بت77وانيم درون برنام77ۀ اص77لي ب7ه متغ7ير countدسترس77ي داش77ته
باش77يم .ميت77وانيم کالس Widgetو اش77ياي xو yو wرا مانن77د
مقابل تصور کنيم:
Widget
y
)(Widget
x
w
~)(Widget
)(numWidgets
3
count
توابع عضو ايستا 12-
با دقت در مثال قبلي به دو اي77راد ب77ر ميخ77وريم :اول اين ک77ه گرچ77ه
متغير countيک عضو ايستا است ولي براي خواندن آن حتما بايد از
ي77ک ش77يء موج77ود اس77تفاده ک77نيم .در مث77ال قبلي از ش77يء wب77راي
خواندن آن استفاده کردهايم .اين باعث ميش77ود ک77ه مجب77ور ش77ويم
هميشه مواظب باشيم عضو ايستاي مفروض از طري77ق ي77ک ش77ي ک77ه
االن موجود است فراخواني شود.
* مثال 9-17يك تابع عضو ايستا
کد زير همان کد مثال قبلي است با اين فرق که در اين کد ،تابع دستيابي کننده نيز به شکل
ايستا اعالن شده است:
class Widget
{ public:
} ;Widget() { ++count
} ;~Widget() { --count
} ;static int num() { return count
private:
;static int count
;}
int Widget::count = 0;
int main()
{ cout << "Now there are " << Widget::num() << " widgets.\n";
Widget w, x;
cout << "Now there are " << Widget::num() << " widgets.\n";
{ Widget w, x, y, z;
cout << "Now there are " << Widget::num() << " widgets.\n";
}
cout << "Now there are " << Widget::num() << " widgets.\n";
Widget y;
cout << "Now there are " << Widget::num() << " widgets.\n";
}
وقتي تابع )(numبه صورت ايستا تعري77ف ش77ود،
از اشياي کالس مستقل ميشود و براي فراخواني
آن نيازي به يک شيء موجود نيست و ميتوان با
ک77د )(Widget::numب77ه ش77کل مس77تقيم آن را
فراخواني کرد.
پايان جلسه نهم
جلسه دهم
«سربارگذاري عملگرها »
:آنچه در اين جلسه مي خوانيد
-1توابع دوست
-2سربارگذاري عملگر جايگزيني (=)
-3اشارهگر this
-4سربارگذاري عملگرهاي حسابي
-5سربارگذاري عملگرهاي جايگزيني حسابي
-6سربارگذاري عملگرهاي رابطهاي
-7سربارگذاري عملگرهاي افزايشي و كاهشي
هدف کلي:
بيان اهميت سربارگذاري عملگرها براي يک
کالس و نحوۀ انجام اين کار.
هدفهاي رفتاري :انتظار ميرود پس از پايان اين جلسه بتوانيد:
«سربارگذاري» را تعريف کرده و اهميت آن را شرح دهيد. «تابع دوست» را تعريف کنيد و علت و اهميت استفاده از چنين توابعي رابيان نماييد.
اشارهگر thisرا بشناسيد و علت استفاده از چنين اشارهگري را بياننماييد.
نحوۀ سربارگذاري عملگر جايگزيني را بيان کنيد. نحوۀ سربارگذاري عملگرهاي حسابي را بيان کنيد. نحوۀ سربارگذاري عملگرهاي جايگزيني حسابي را بيان کنيد. نحوۀ سربارگذاري عملگرهاي رابطهاي را بيان کنيد. -نحوۀ سربارگذاري عملگرهاي افزايشي و کاهشي را بيان کنيد.
:مقدمه
در ++Cمجموعهاي از 45عملگر مختلف وجود دارد که ب777راي کارهاي
ميشوند .همۀ اين عملگرها ب777راي ک777ار کردن با ان777واع
متنوعي استفاده
بنيادي (مثل intو floatو )charسازگاري دارند.
هنگامي که کالسي را تعريف ميک77نيم ،در حقيقت ي77ک ن77وع جدي77د را ب77ه
انواع موجود اضافه کردهايم .ممکن است بخواهيم اشياي اين کالس را در
محاسبات رياضي به کار ببريم.
اما چون عملگرهاي رياضي (مثل +يا = يا *= ) چ77يزي راج77ع ب77ه اش77ياي
کالس جديد نميدانند ،نميتوانند به درستي ک77ار کنن77د ++C .ب77راي رف77ع
اين مشکل چاره انديشيده و امکان سربارگذاري عملگرها را تدارک ديده
است .سربارگذاري عملگرها ب77ه اين معناس77ت ک77ه ب77ه عملگرها تعاريف
جديدي اضافه کنيم تا بتوانند با اشياي کالس م77ورد نظر ب77ه درس77تي ک77ار
کنند.
:توابع دوست 1-
class Ratio
{ );friend int numReturn(Ratio
به کد زير نگاه کنيد:
:public
;)(Ratio
private
;)()Ratio
اعضايي از کالس ک77ه ب77ه ش77کل خصوص77ي ( ~
اعالن ميش77وند فق77ط از داخ77ل همان کالس قاب77ل
:private
7لي);int
num,
denاص7
دس77تيابياند و از ب77يرون کالس (درون بدن77ۀ
}
نيست.
ها
آن
به
دسترسي
امکان
)int numReturn(Ratio r
;return
r.numاس7ت
اما يک استثنا وجود دارد .تابع دوس7ت{ ت7ابعي
که عضو يک کالس نيست اما اجازه دارد به اعض77اي }
)(int main
باشد.
داشته
دسترسي
خصوصي آن
– Ratio x(22, 7);1
Friend
function
{
;cout << numReturn(x) << endl
}
-2سربارگذاري عملگر جايگزيني(=):
در بين عملگرهاي گوناگون ،عملگر جايگزيني ش77ايد
بيشترين کاربرد را داشته باشد.
هدف اين عملگر ،کپي کردن يک شي در شيء ديگر
است.
پيشفرض ،سازندۀ کپي و نابودکنن777ده،
مانند سازندۀ
عملگر جايگزيني ن77يز ب77ه ط77ور خودک77ار ب77راي ي77ک
کالس ايجاد ميشود اما اين تابع را ميتوانيم به شکل
صريح درون کالس اعالن نماييم.
مثال :افزودن عملگر جايگزيني به كالس:
کد زير يک رابط کالس براي Ratioاست که ش777امل سازندۀ
پيشفرض ،سازندۀ کپي و عملگر جايگزيني ميباشد:
class Ratio
{ public:
;)Ratio(int = 0, int = 1
;)&Ratio(const Ratio
;)&void operator=(const Ratio
private:
;int num, den
;}
به نحو اعالن عملگر جايگزيني دقت نماييد.
نام اين تابع عضو =operator ،است و فهرس777ت آرگومان
آن مانند سازندۀ کپي ميباشد يعني يک آرگومان منفرد
دارد که از نوع همان کالس است که به طريقۀ ارجاع ثابت
ارسال ميشود .عملگر جايگزيني را ميتوانيم به شکل زير
تعريف کنيم:
)void Ratio::operator=(const Ratio& r
کد فوق اعض77اي دادهاي ش77يء rرا ;{ num = r.num
;den = r.den
به درون اعضاي دادهاي ش77يئي ک77ه
}
مالک فراخواني اين عملگر اس777ت،
کپي ميکند.
-3اشارهگر this:
در ++Cميتوانيم عملگر جايگزيني را به شکل زنج77يرهاي مث77ل
زير به کار ببريم:
;x = y = z = 3.14
اجراي کد باال از راس77ت ب77ه چپ ص77ورت ميگ77يرد.
يع77ني ابت77دا مق77دار 3.14درون zقرار ميگ77يرد و
سپس مق7777دار zدرون yکپي ميش7777ود و سرانجام
مق777777دار yدرون xقرار داده ميش777777ود .عملگر
جايگزيني که در مثال قب77ل ذکر ش77د ،نميتوان77د ب77ه
شکل زنجيرهاي به کار رود.
: سربارگذاري عملگر جايگزيني به شکل صحيح10-2 مثال
class Ratio
:public {
Ratio(int =0, int =1);
// default constructor
Ratio(const Ratio&);
// copy constructor
Ratio& operator=(const Ratio&); // assignment operator
other declarations go here //
:private
;int num, den
other declarations go here //
;}
Ratio& Ratio::operator=(const Ratio& r)
;num = r.num {
;den = r.den
;return *this
}
توجه داشته باش77يد ک77ه عم77ل جايگزيني با عم77ل
مقداردهي تفاوت دارد ،هر چند هر دو از عملگر
يکساني استفاده ميکنند .مثال در کد زير:
Ratio x(22,7); // this is an initialization
;)Ratio y(x
// this is an initialization
;Ratio z = x
// this is an initialization
;Ratio w
;w = x
// this is an assignment
وليولي
خواند7تند
7داردهييهس7
7
مق
دستورات
اول،
دستور
سه
دستور مقداردهي ،سازندۀ کپي را فرا م
جايگزيني است.
دستور آخر
دستور
فراخواني ميکند.
دستورجايگزيني را
يکعملگر
جايگزيني
:سربارگذاري عملگرهاي حسابي4-
چهار عملگر حسابي +و – و * و /در همۀ زبانهاي برنامهنويسي وج77ود دارن77د و
با همۀ انواع بنيادي ب77ه ک77ار گرفت77ه ميش77وند .قص77د داريم سرباري را ب77ه اين
عملگرها اضافه کنيم تا بتوانيم با استفاده از آنها ،اش7777ياي ساخت خودمان را
در محاسبات رياضي به کار ببريم.
عملگرهاي حسابي به دو عملوند نياز دارند .مثال عملگر ضرب (*) در رابطۀ زير:
;z = x*y
با توجه به رابطۀ فوق و آنچه در بخش قبلي گفتيم ،عملگر ضرب سربارگذاري
شده بايد دو پارامتر از نوع يک کالس و به طريق ارجاع ث77ابت بگ77يرد و ي77ک
مق77دار بازگش77تي از ن77وع همان کالس داش77ته باش77د .پس انتظ77ار داريم ق77الب
سربارگذاري عملگر ضرب براي کالس Ratioبه شکل زير باشد:
)Ratio operator*(Ratio x, Ratio y
{ );Ratio z(x.num*y.num, x.den*y.den
;return z
}
اگر ت77ابعي عض77و کالس نباش77د ،نميتوان77د ب77ه اعض77اي
خصوصي آن کالس دستيابد .براي رفع اين مح77دوديتها،
تابع سربارگذاري عملگر ضرب را باي77د ب77ه عن77وان ت77ابع
دوس777ت کالس معرفي ک777نيم .ل777ذا ق777الب کلي ب777راي
سربارگذاري عملگر ضرب درون کالس مفروض Tب77777ه
شکل زير است:
Class T
{ friend T operator*(const T&, const
;)&T
public:
// public members
private:
// private members
}
نيس77ت،
دوس77ت
سربارگذاري ت77ابع
ودراز آنجا ک77ه
کالس قالبهاي
عض77وي /ازن7777يز از
حسابي +و – و
عملگرهاي
در
پ77ذيرد.
کالس
بايديخارج
بدنۀ آن
تعريف
ت77ابع
ص77ورتدر ن77ام
تف77اوت ک77ه
از اين
ک77نيم با
اس77تفاده م
ف77وق
کلي
عالمت عملگر
باي77777د
کلم*7
ضرب
7ابعجاي
ب77777ه
سربارگذاري،
friend
7دي
7ۀ کلي7
عالمت77ه
دوس77ت ب
7ۀ ت7
تعريف بدن7
طبق نياز تغيير
بدنۀ تابع
عملگردستورات
قرارودهيم و
مربوطه را
اس77تفاده
ح77وزهرا ::نيزن77يز
جداسازي
نيست
نيازي
دهيم.
شود:
نمي
T operator*(const T& x, const
)T& y
;{ T z
= // required operations for z
Ratio: سربارگذاري عملگر ضرب براي کالس10-3 مثال
class Ratio
;friend Ratio operator*(const Ratio&, const Ratio&) {
:public
;Ratio(int = 0, int = 1)
;Ratio(const Ratio&)
;Ratio& operator=(const Ratio&)
other declarations go here //
:private
;int num, den
other declarations go here //
;}
Ratio operator*(const Ratio& x, const Ratio& y)
;Ratio z(x.num * y.num , x.den * y.den) {
;return z
}
)(int main
;Ratio x(22,7) ,y(-3,8) ,z {
z = x;
// assignment operator is called
;z.print(); cout << endl
x = y*z;
// multiplication operator is called
;x.print(); cout << endl
}
-5سربارگذاري عملگرهاي جايگزيني حسابي:
به خاطر بياوريد که عملگرهاي جايگزيني حسابي ،ترکيبي از عملگر جايگزيني و ي7777ک
عملگر حسابي ديگر اس7777ت .مثال عملگر *= ترکي7777بي از دو عم7777ل ضرب * و سپس
جايگزيني = است .نکتۀ قابل توجه در عملگرهاي جايگزيني حسابي اين اس777ت ک777ه اين
عملگرها ب777ر خالف عملگرهاي حسابي ساده ،فق777ط ي777ک عملون777د دارن777د .پس ت777ابع
ميتوان77د عض77و
سربارگذاري عملگرهاي جايگزيني حسابي بر خالف عملگرهاي حسابي ،
کالس باش77777د .سربارگذاري عملگرهاي جايگزيني حسابي بس77777يار شبيه سربارگذاري
عملگر جايگزيني است .قالب کلي براي سربارگذاري عملگر *= ب7777راي کالس مفروض
Tبه صورت زير است:
class T
{ :public
)&;T& operator*=(const T
other public members //
:private
private members //
};
بدنۀ تابع سربارگذاري به قالب زير است:
)T& T::operator*=(const T& x
{ // required operations
;return *this
}
استفاده از اشارهگر * thisباعث ميشود که بت777وانيم عملگر *= را
در يک رابط77ۀ زنج77يرهاي ب77ه ک77ار ب77بريم .در ++Cچهار عملگر
جايگزيني حسابي =+و =-و *= و =/وجود دارد .قالب کلي براي
فق77ط در
سربارگذاري همۀ اين عملگرها به شکل ق77الب باال اس77ت فق77ط
نام تابع به جاي *= باي7777د عالمت عملگر مربوط7777ه را ذکر کرد و
دستورات بدنۀ تابع را نيز به تناسب ،تغيير داد .مثال بعدي نش77ان
ميدهد ک77ه عملگر *= چگون77ه ب77راي کالس Ratioسربارگذاري
شده است.
: با عملگر *= سربارگذاري شدهRatio كالس10-4 مثال
class Ratio
:public {
;Ratio(int = 0, int = 1)
دۀ جايگزيني777ه عملگر سربارگذاري ش777ت ک777ديهي اس777ب
;Ratio& operator=(const Ratio&)
،معادلش
شدۀ حسابي
بايد با عملگر سربارگذاري،حسابي
;Ratio&
operator*=(const
Ratio&)
دو از کالسgo
هرhere
y و//
x مثال اگر.نتيجۀ يکساني داشته باشد
other declarations
:privateابهي77ۀ مش77د نتيج77ر باي77د زي77ط ک77 آنگاه دو خ، باشندRatio
;int num, den
:داشته باشند
other declarations
x *= y; go here //
;}
x = x*y;
Ratio& Ratio::operator*=(const Ratio& r)
;num = num*r.num {
;den = den*r.den
;return *this
}
-6سربارگذاري عملگرهاي رابطهاي:
شش عملگر رابطهاي در ++Cوج777777ود
دارد که عبارتند از > :و < و => و <=
و == و != .
اين عملگرها به همان روش عملگرهاي
حسابي،يع77ني ب77ه ش77کل تواب77ع دوس77ت
سربارگذاري ميش7777777وند .اما ن7777777وع
بازگشتيشان فرق ميکند.
حاص77ل عبارتي ک77ه ش77امل عملگر رابطهاي باش77د،
همواره يک مقدار بولين است .يعني اگر آن عبارت
درست باشد ،حاصل trueاست و اگر آن عبارت
نادرست باشد ،حاصل falseاست.
چون نوع بولين در حقيقت ي77ک ن77وع ع77ددي ص77حيح
اس77ت ،ميت77وان ب77ه جاي trueمق77دار 1و ب77ه جاي
falseمق777دار 0را قرار داد .ب777ه همين جهت ن777وع
بازگش777تي را ب777راي تواب777ع سربارگذاري عملگرهاي
رابطهاي ،از نوع intقرار دادهاند.
:قالب کلي براي سربارگذاري عملگر رابطهاي == به شکل زير است
class T
;friend int operator==(const T&, const T&)
:public
public members //
:private
private members //
}
{
همچنين قالب کلي تعريف بدنۀ اين تابع به صورت زير ميباشد:
&int operator==(const T& x,const T
)y
{ required operations to finding //
result
;return result
که به جاي resultيک مقدار بولين يا يک عدد صحيح قرار}
ميگيرد .ساير عملگرهاي رابطهاي نيز از قالب باال پ77يروي
ميکنند.
Ratio: سربارگذاري عملگر تساوي (==) براي كالس10-5 مثال
class Ratio
ورت77ه ص77 بRatio ياي کالس77چون اش
;friend int operator==(const Ratio&, const Ratio&) {
a
x==yconst
تساوي
بررسي، هستندbکسر
;frined Ratio operator*(const Ratio&,
Ratio&)
a
c
other declarations go here // راي77ه ب77ت ک77اس
b
dي77معادل بررس
:public
دار77وانيم مق77ي اين تساوي ميت77بررس
;Ratio(int = 0, int = 1)
ۀ77 بدن.نيم77ي ک77) را بررسa*d==b*c(
;Ratio(const Ratio&)
;Ratio& operator=(const Ratio&)تابع سربارگذاري در مثال همين رابطه
other declarations go here //
.را بررسي ميکند
:private
;int num, den
other declarations go here //
;}
int operator==(const Ratio& x, const Ratio& y)
;return (x.num * y.den == y.num * x.den) {
}
-7سربارگذاري عملگرهاي افزايشي و كاهشي:
عملگر افزايشي ++و کاهشي --هر کدام دو ش77کل
دارند:
-1شکل پيشوندي.
-2شکل پسوندي.
ميت777وان سربارگذاري
حالتها را
هر ک777دام از اين
کرد.
قالب کلي براي سربارگذاري عملگر پيشافزايشي به شکل زير است:
)(++T T::operator
{ required operations //
;return *this
}
اينجا هم از اشارهگر * thisاستفاده ش77ده .علت هم
اين اس77ت ک77ه مش77خص نيس77ت چ77ه چ77يزي باي77د
بازگشت داده شود .به همين دليل اشارهگر * thisبه
پيشافزايش روي آن
کار رفته ت77ا ش77يئي ک77ه عم77ل
صورت گرفته ،بازگشت داده شود.
افزودن عملگر پيشافزايشي به كالس Ratio:
اگر yيک شي از کالس Ratioباشد و عبارت y++ارزيابي
گردد ،مقدار 1به yافزوده ميشود اما چ77ون yي77ک ع77دد
کسري است ،افزودن مق77دار 1ب77ه اين کسر اثر متف77اوتي
دارد .فرض کنيد y=22/7باشد .حاال داريم:
22
22 7 29
y 1
7
7
7
افزودن عملگر پسافزايشي به كالس :Ratio
در عبارت ;++y = xاز عملگر پسافزايشي استفاده کردهايم .تابع اين عملگر باي77د ط77وري
تعريف شود که مقدار xرا قبل از اين ک77ه درون yقرار بگ77يرد ،تغي77ير نده77د .ميدانيم ک77ه
اشارهگر * thisبه شيء جاري (مالک فراخواني) اشاره دارد .کافي است مق77دار اين اش77ارهگر
را در يک محل موقتي ذخيره کنيم و عم77ل افزايش را روي آن مق77دار موق77تي انجام داده و
حاصل آن را بازگشت دهيم .به اين ترتيب مقدار * thisتغي77يري نميکن77د و پس از شرکت
در عمل جايگزيني ،درون yقرار ميگيرد:
class
Ratio
()
int main
;:public
{ ++Ratio{ x(22,7) , y = x
Ratio(int
)d=1) : num(n) , den(d
;})({cout
<< "yn=0,
= "; int
y.print
;)(operator++
//pre-increment
}Ratio
;)(cout
<< ", x = "; x.print
;)operator++(int
//post-increment
)Ratio Ratio::operator++(int
)(print
;void
Ratio
temp{ =cout
<<*this
} ;{ num << '/' << den << endl
;:private
num += den
int num,temp
den
;return
};}
عملگرهاي پيشکاهشي و پسکاهشي ن77يز ب77ه
همين ش77777يوۀ عملگرهاي پيشافزايش77777ي و
پسافزايش77ي سربارگذاري ميش77وند .غ77ير از
اينها ،عملگرهاي ديگري ن777يز مث777ل عملگر
خروجي (<<) ،عملگر ورودي (>>) ،
عملگر انديس ([]) و عملگر تبديل ن77يز وج77ود
دارن77د ک77ه ميت77وان آنها را ب77راي سازگاري
براي کالسهاي جديد سربارگذاري کرد.
پايان جلسه دهم
جلسه يازدهم
«تركيب و وراثت»
مقدمه
«تركيب و وراثت»
تركيب
وراثت
اعضاي حفاظت شد
غلبه کردن بر وراثت
اشارهگرها در وراثت
توابع مجازي و چندريختي
نابودكنن777777777777دۀ مجازي
كالسهاي پايۀ انتزاعي
پرسشهاي گزينهاي
پرسشهاي تشريحي
تمرينهاي برنامهنويسي
ضميمه الف :پاسخنامۀ پرسشهاي گزينهاي
ضميمه ب:جدول اسکي
ضميمه ج :کلمات کليدي ++Cاستاندارد
ضميمه د :عملگرهاي ++Cاستاندارد
ضميمه هـ :فهرست منابع و مأخذ
هدف کلي:
بيان اهميت ترکيب و وراثت در
شيگرايي و چگونگي انجام اين کارها.
هدفهاي رفتاري:
انتظار ميرود پس از پايان اين جلسه بتوانيد:
علت استفاده از «ترکيب» و «وراثت» را در برنامههاي ش77يگراتوضيح دهيد.
نحوۀ ترکيب دو يا چن77د کالس را ب77راي ايجاد کالس جدي77د،بدانيد.
-وراثت را تعريف کنيد.
«اعضاي حفاظت شدۀ کالس» را تعري77ف کني77د و تف77اوتاين اعض77ا با اعض77اي عم77ومي و خصوص77ي کالس را شرح
دهيد.
نحوۀ غلبه کردن بر وراثت را شرح دهيد. «تابع مجازي» را تعري77ف کني77د و علت اس77تفاده از تواب77عمجازي را بدانيد.
«چن777دريختي» را تعري777ف کني777د و ش777يوۀ پيادهسازيچندريختي در کالسها را بدانيد.
«کالس پايۀ انتزاعي» را تعريف کنيد و علت تعريف اينکالسها را ذکر کنيد.
مقدمه
اغلب اوقات براي ايجاد يک کالس جديد ،نيازي نيس777ت
که همه چيز از اول طراحي ش77ود .ميت77وانيم ب77راي ايجاد
کالس م7777777ورد نظر ،از تعاريف کالسهايي ک7777777ه قبال
ساختهايم ،استفاده نماييم.
اين باعث صرفهجويي در وقت و اس77تحکام منط77ق برنام77ه
ميشود.
در شيگرايي به دو شيوه ميت77وان اين ک77ار را انجام داد:
ترکيب 1و وراثت .2در اين جلس777ه خ777واهيم دي777د ک777ه
چگون77ه و چ77ه م77واقعي ميت77وانيم از اين دو ش77يوه به77ره
ببريم.
:تركيب
ترکيب کالسها (يا تجميع کالسها) يعني اس77تفاده
از يک يا چند کالس ديگر در داخ77ل تعري77ف ي77ک
کالس جديد.
هنگ77امي ک77ه عض77و دادهاي کالس جدي77د ،ش77يئي از
کالس ديگر باشد ،ميگ77وييم ک77ه اين کالس جدي77د
ترکيبي از ساير کالسهاست.
به تعريف دو کالس زير نگاه کنيد.
Date كالس
تفاده77اريخ اس77 را نشان ميدهد که اشياي اين کالس براي نگهداري تDate کالس،کد زير
.ميشوند
class Date
:public {
: Date(int y=0, int m=0, int d=0)
;}{ year(y), month(m), day(d)
void setDate(int y, int m, int d)
} ;year = y; month = m; day = d {
)(void getDate
} ; cin >> year >> month >> day {
)(void showDate
} ; cout << year << '/' << month << '/' << day {
:private
;int year, month, day
}
Book كالس
رخي از7ياي اين کالس ب7ه اش7د ک7 را نشان ميدهBook کالس،کد زير
:مشخصات يک کتاب را نگهداري ميکنند
class Book
:public {
: Book(char* n = " ", int i = 0, int p = 0)
} { name(n), id(i), page(p)
void printName() { cout << name; }
void printId() { cout << id; }
void printPage() { cout << page; }
:private
;string name, author
;int id, page
}
Book بهبود دادن کالس
#
"include "Date.h
class Book
:public {
: Book(char* n = " ", int i = 0, int p = 0)
} { name(n), id(i), page(p)
void printName() { cout << name; }
void printId() { cout << id; }
void printPage() { cout << page; }
void setDOP(int y, int m, int d)
} ; publish.setDate(y, m, d) {
void showDOP() { publish.showDate(); }
:private
;string name, author
;int id, page
;Date publish
}
وراثت :
وراثت روش ديگري براي ايجاد کالس جدي777د از
روي کالس قبلي است .گاهي ب77ه وراثت «اش77تقاق»
نيز ميگويند.
اگر از قب77ل با برنامهنويس77ي مبت77ني ب77ر پنجرهها
آش777نايي مختصر داش777ته باش777يد ،احتماال عبارت
«کالس مشتقشده» را فراوان ديدهايد .اين موضوع
به خوبي اهميت وراثت را آشکار مينمايد.
اعضاي حفاظت شده:
گرچه کالس Ebookدر مثال قبل نميتواند مستقيما ب77ه اعض77اي
خصوصي کالس والدش دسترسي داشته باشد ،اما با اس7777تفاده از
توابع عضو عمومي که از کالس وال77د ب77ه ارث ب77رده ،ميتوان77د ب77ه
اعضاي خصوصي آن کالس دستيابي کند .اين محدوديت ب77زرگي
محسوب ميشود .اگر توابع عض77و عم77ومي کالس وال77د انتظ77ارات
کالس فرزند را برآورده نسازند ،کالس فرزند ناکارآمد ميشود.
اوض77اع زماني وخيمتر ميش77ود ک77ه هيچ ت77ابع عم77ومي ب77راي
دسترسي ب77ه ي77ک دادۀ خصوص77ي در کالس وال77د وج77ود نداش77ته
باشد.
غلبه کردن بر وراثت :
اگر Yزير کالسي از Xباشد ،آنگاه اشياي Yهمۀ اعضاي عم77ومي و
حفاظت شدۀ کالس Xرا ارث ميبرند.
مثال تمامي اش77ياي Ebookت77ابع دس77تيابي )(printNameاز کالس
Bookرا به ارث ميبرند .به تابع )(printNameيک «عضو موروثي»
ميگوييم .گاهي الزم است يک نسخۀ محلي از عضو م77وروثي داش77ته
باشيم.
يعني کالس فرزند ،عضوي هم نام با عضو م77وروثي داش77ته باش77د ک77ه
مخصوص به خ77ودش باش77د و ارثي نباش77د .ب77راي مث77ال فرض کني77د
کالس Xيک عض77و عم77ومي ب77ه ن77ام pداش77ته باش77د و کالس Yزي77ر
کالس Xباشد.
در اين حالت اشياي کالس Yعضو موروثي pرا خواهند داشت.
حال اگر يک عض77و ب77ه همان ن77ام pدر زي77رکالس Yب77ه ش77کل
صريح اعالن کنيم ،اين عضو جدي77د ،عض77و م77وروثي همن77امش را
مغلوب ميکند.
به اين عضو جديد« ،عضو غالب» ميگوييم .بنابراين اگر y1ي77ک
شي از کالس Yباشد y1.p ،به عضو pغالب اشاره دارد نه ب77ه p
موروثي.
البته هنوز هم ميتوان ب77ه pم77وروثي دسترس77ي داش77ت .عبارت
y1.X::pبه pموروثي دستيابي دارد.
هم ميتوان اعضاي دادهاي موروثي را مغلوب کرد و
هم اعضاي تابعي موروثي را.
يعني اگر کالس Xداراي يک عضو تابعي عم77ومي ب77ه
ن77ام )(fباش77د و در زي77رکالس Yن77يز ت77ابع )(fرا ب77ه
شکل صريح اعالن کنيم ،آنگاه )(y1.fبه ت77ابع غ77الب
اشاره دارد و )(y1.X::fبه تابع م77وروثي اش77اره دارد.
در برخي از مراجع به توابع غالب overrideميگويند
و دادههاي غ777الب را dominateمينامن777د .ما در اين
کتاب هر دو مفهوم را به عنوان اعضاي غالب ب77ه ک77ار
ميبريم .به مثال زير نگاه کنيد.
: دادهاي و تابعي غالب
اعضاي
class X
:public {
void f() { cout << "Now X::f() is running\n"; }
;int a
;}
class Y : public X
:public {
void f() { cout << "Now Y::f() is running\n"; }
)(this f() overrides X::f //
;int a
this a dominates X::a //
;}
:سازندهها و نابودکنندههاي والد
class X
:public {
X() { cout << "X::X() constructor executing\n"; }
X() { cout << "X::X() destructor executing\n"; }~
;}
clas Y : public X
:public {
Y() { cout << "Y::Y() constructor executing\n"; }
Y() { cout << "Y::Y() destructor executing\n"; }~
;}
clas Z : public Y
:public {
Z(int n) {cout << "Z::Z(int) constructor executing\n";}
Z() { cout << "Z::Z() destructor executing\n"; }~
;}
)(int main
;Z z(44) {
}
اشارهگرها در وراثت :
در شيگرايي خاصيت جالبي وجود دارد و آن اين است که اگر pاش77ارهگري از ن77وع کالس
والد باشد ،آنگاه pرا ميتوان به هر فرزندي از آن کالس نيز اش77اره داد .ب77ه ک77د زي77ر نگ77اه
کنيد:
class X
{ :public
;)(void f
}
class Y : public X
// Y is a subclass of X
{ :public
;)(void f
}
)(int main
;X* p
{ // p is a pointer to objects of base class X
;Y y
;p = &y
// p can also point to objects of subclass Y
}
:اشارهگري از کالس والد به شيئي از کالس فرزند
هر دوي اين کالسها.ت777 اسX ي از777 زيرکالسY کالس،در برنامۀ زير
*X وع77ارهگري از ن77 اشp تند و77() هسf ام77ه ن77ابعي ب77و ت77داراي يک عض
class X
:تعريف شده
:public {
void f() { cout << "X::f() executing\n"; }
;}
class Y : public X
:public {
void f() { cout << "Y::f() executing\n"; }
}
)(int main
;X x {
;Y y
;X* p = &x
*p->f();
// invokes X::f() because p has type X
;p = &y
*p->f();
// invokes X::f() because p has type X
}
توابع مجازي و چندريختي :
تابع مجازي تابعي است که با کلمۀ کليدي virtual
مشخص ميشود .وقتي يک تابع به ش777کل مجازي
اعالن ميشود ،يعني در حداقل يکي از کالسهاي
فرزند نيز تابعي با همين ن77ام وج77ود دارد .تواب77ع
مجازي امک77ان ميدهن77د ک77ه هنگ77ام اس77تفاده از
اش77ارهگرها ،بت77وانيم ب77دون در نظر گرفتن ن77وع
اشارهگر ،به توابع شيء جاري دستيابي ک77نيم .ب77ه
مثال زير دقت کنيد.
:استفاده از توابع مجازي
class X
public:1 – Virtual function {
virtual void f() { cout << "X::f() executing\n"; }
;}
class Y : public X
:public {
void f() { cout << "Y::f() executing\n"; }
}
)(int main
;X x {
;Y y
;X* p = &x
)(p->f();
// invokes X::f
;p = &y
)(p->f();
// invokes Y::f
}
: چندريختي از طريق توابع مجازي
ور77ه آن ط77 برنام، بدون استفاده از توابعمجازي.سه کالس زير را در نظر بگيريد
:که مورد انتظار است کار نميکند
class
Ebook
public Book
Book
class
Book:: public
class
Notebook
:public
:public
:public
{ { {
s, {int
float
:=Book(s),
size(g)
;Ebook(char*
Book(char* s)
name
new char[strlen(s+1)]
}{ }{
Notebook(char*
s,
n) g)
: Book(s)
, pages(n)
" void
print()
{ cout
"Here
an Ebookwith
withname
name
;print()
strcpy(name,
s)<<
" void
{ cout
<<
"Here
is aisNotebook
" name
<<
}<< "<<
name
and" "and
<<size
pages
<<
;"size
<<
" MB.\n
<<
" void
{ cout
<< "Here is a book with name
;"pages.\n
"print()
<<
} } ;"name << ".\n <<
:private
}
:private
float
size
:protected
;int ;pages
;} } ;char* name
;}
:نابودكنندۀ مجازي
با توجه به تعريف توابع مجازي ،به نظر ميرسد ک77ه نميت77وان تواب77ع
سازنده و نابودکننده را به شکل مجازي تعريف نمود زيرا سازندهها
و نابودگرها در کالسهاي وال77د و فرزن77د ،همن77ام نيس77تند .در اص77ل،
سازندهها را نميتوان به شکل مجازي تعري777777ف کرد اما نابودگرها
قصۀ ديگري دارند.
مث77ال بع77دي اي77راد مهلکي را نش77ان ميده77د ک77ه با مجازي کردن
نابودگر ،برطرف ميشود.
: حافظۀ گم شده
:به برنامۀ زير دقت کنيد
class X
:public {
x() { p = new int[2]; cout << "X(). "; }
X() { delete [] p; cout << "~X().\n" }~
:private
;int* p
;}
class Y : public X
:public {
Y() { q = new int[1023]; cout << "Y() : Y::q = " << q
} ;" ." <<
Y() { delete [] q; cout << "~Y(). "; }~
:private
;int* q
;}
)(int main
for (int i=0; i<8; i++) {
;X* r = new Y {
;delete r
}
}
كالسهاي پايۀ انتزاعي :
در شيگرايي رسم بر اين است که ساختار برنامه و کالسها را طوري طراحي کنن77د ک77ه بت77وان
آنها را به شکل يک نمودار درختي شبيه زير نشان داد:
BOOK
EBOOK
HTML
HLP
CHM
Paper BOOK
PDF
MAGAZINE COOKBOOK
REFERENCE