ﻣﺒﺎﻧﯽ ﺑﺮﻧﺎﻣﻪ ﻧﻮﻳﺴﯽ ﺟﻠﺴﻪ ﯼ ﻫﺠﺪﻫﻢ -۱۱( -۱۳ ۱۳۹ )
ﻣﺒﺎﻧﯽ ﺑﺮﻧﺎﻣﻪ ﻧﻮﻳﺴﯽ ﺟﻠﺴﻪ ﯼ ﻫﺠﺪﻫﻢ -۱۱( -۱۳ ۱۳۹ )
ﻣﺒﺎﻧﯽ ﺑﺮﻧﺎﻣﻪ ﻧﻮﻳﺴﯽ ﺟﻠﺴﻪ ﯼ ﻫﺠﺪﻫﻢ -۱۱( -۱۳ ۱۳۹ )
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
مبانی برنامه نويسی<br />
جلسه ی هجدهم<br />
(۱۱-۱۳-۱۳۹)<br />
دانشگاه شهيد بهشتی<br />
پاييز<br />
دانشکده ی مهندسی برق و کامپيوتر<br />
احمد محمودی ازناوه<br />
۱۳۹۱<br />
http://faculties.sbu.ac.ir/~a_mahmoudi/
فهرست مطالب<br />
•<br />
•<br />
•<br />
•<br />
•<br />
ارسال با ارجاع<br />
تابع بازگشتي<br />
استقرا<br />
روابط بازگشتي<br />
تابع بازگشتي<br />
ويرايش جديد با كمك هاي آقاي<br />
«محمدرضا بهرامي» تهيه شده است.<br />
مبانی برنامه نويسی<br />
2
•مروي بر جلسهي پيش<br />
ارسال از طريق مقدار<br />
به صورت معمول، هنگامي كه تابعي فراخواني<br />
مي شود، آرگومان هاي ورودي به صورت ارسال از<br />
طريق مقدار در نظر گرفته مي شوند.<br />
در اين حالت يك كپي از مقادير گرفته شده،<br />
فرآيند ها به روي كپي مورد نظر اعمال مي گردند.<br />
در بسياري موارد هنگامي كه مقادير ارسالي<br />
حجم بالا باشند، كپي به حافظه ي زيادي نياز<br />
مقرون به صرفه نيست.<br />
call by value<br />
داراي<br />
دارد و<br />
•<br />
•<br />
•<br />
راه حل ارسال از طريق ارجاع<br />
3
•مروي بر جلسهي پيش<br />
ارسال با ارجاع<br />
–<br />
متغير ارجاعي نام ديگري براي متغير اصلي است.<br />
به همين علت هر تغييري كه به<br />
ارجاعي اعمال گردد، متغير اصلي نيز<br />
كرد.<br />
روي<br />
تغيير<br />
متغير<br />
خواهد<br />
در مواردي كه نياز باشد تغييرات به روي متغير<br />
اصلي نيز صورت پذيرد آرگومان هاي تابع را به<br />
صورت «ارجاع» در نظر مي گيريم.<br />
مثال: تابعي كه دو عدد را جا به جا مي كند.<br />
call by reference<br />
•<br />
•<br />
•<br />
4
•<br />
•مروي بر جلسهي پيش<br />
ارسال با ارجاع<br />
(ادامه...)<br />
متغير ارجاعي همانند<br />
مي شود و تنها يك<br />
در نظر گرفته مي شود.<br />
«&»<br />
متغير refVar يك رفرنس به int خواهد بود<br />
Ampersand<br />
متغير معمولي تعريف<br />
براي نشان دادن نوع ارجاع<br />
prototype<br />
5
•مروي بر جلسهي پيش<br />
ارسال با ارجاع<br />
(مثال)<br />
هنگامي كه با متغير ارجاعي كار مي كنيم فرآيند به<br />
روي متغيري كه با آن ارجاع مي شود صورت مي گيرد<br />
6
•مروي بر جلسهي پيش<br />
ارسال با ارجاع<br />
(مثال)<br />
7
ارسال با ارجاع (نکات)<br />
تنها «متغير ها» از طريق<br />
گردند.<br />
ارسال عبارات و ثابت ها<br />
با خطا مواجه مي كند.<br />
ارجاع مي توانند ارسال<br />
از طريق ارجاع برنامه را<br />
•<br />
•<br />
به دليل تغيير متغير خارج<br />
طريق ارجاع، اين پتانسيل<br />
كه به صورت سهوي مقادير<br />
از تابع هنگام ارسال از<br />
به برنامه داده مي شود<br />
تغيير يابد.<br />
•<br />
تنها در مواردي كه نياز است از ارسال به طريق ارجاع استفاده كنيد<br />
8
ارسال با ارجاع (نکات)<br />
–<br />
چه زمان ارسال از طريق ارجاع داشته باشيم چه<br />
زمان از طريق مقدار؟<br />
هنگامي كه آرگومان ورودي ثابت است،<br />
طريق مقدار صورت مي گيرد (تنها متغيرها<br />
ارجاع قابليت ارسال دارند)<br />
ارسال از<br />
از طريق<br />
ارسال از طريق مقدار<br />
•<br />
هنگامي كه مقدار يك متغير نمي بايد در جريان<br />
فراخواني تابع تغيير كند ارسال از طريق مقدار است.<br />
هنگامي كه خروجي تنها يك<br />
بازگشت داده مي شود<br />
است.<br />
return<br />
متغير است از طريق<br />
و ارسال از طريق مقدار<br />
–<br />
–<br />
9
ارسال با ارجاع (نکات -<br />
ادامه...)<br />
–<br />
–<br />
–<br />
چه زمان ارسال از طريق ارجاع داشته باشيم چه<br />
زمان از طريق مقدار؟<br />
هنگامي كه بيش از يك مقدار بناست تغيير داده شود<br />
(چون تنها يك مقدار بازگشتي مي توان داشت)، ارسال<br />
از طريق ارجاع صورت مي گيرد.<br />
هنگامي كه داده ي اصلي مقدار بزرگي است، كپي آن<br />
فرآيندي منطقي نيست، ارسال به شيوه ي ارجاع<br />
صورت مي گيرد.<br />
تغيير<br />
تابع ماهيت هنگامي كه باشد.<br />
آرگومان هاي ورودي<br />
تابع Swap<br />
•<br />
10
ارسال با ارجاع(مثال-<br />
تغییر روی آرگومان های ورودی)<br />
11
(تغيير روی آرگومان های ورودی)<br />
12
ارسال با ارجاع (مثال-<br />
تغییر روی آرگومان های ورودی)<br />
13
14<br />
تغيير روی آرگومان های ورودی
15<br />
مثال
16<br />
مثال
ارسال با ارجاع (مثال-<br />
چند خروجی)<br />
استفاده از ارجاع هنگامي كه بيش از يك خروجي در<br />
تابع نياز است:<br />
•<br />
17
ارسال به وسيله ی ارجاع ثابت<br />
يكي از مواردي كه ارسال به وسيله ي ارجاع<br />
پيشنهاد داده مي شود زماني است كه آرگومان<br />
ارسالي حجيم است.<br />
در اين صورت است كه از كپي كردن آرگومان<br />
جلوگيري مي شود و برنامه بازده بيشتري خواهد<br />
داشت.<br />
ممكن است تابع آرگومان را ناخواسته تغيير دهد<br />
•<br />
•<br />
پيشنهاد<br />
ارسال ارجاع ثابت<br />
18
19<br />
مثال (ارسال به وسيله ی ارجاع ثابت)
مثال (ارسال به وسيله ی ارجاع ثابت)<br />
اگر سعي كنيد ارجاعي را كه ثابت است در تابع<br />
تغيير دهيد، با خطاي كامپايلري مواجه مي شويد<br />
•<br />
error C3892: 'z' : you cannot assign to a variable that is const<br />
20
exit function<br />
تابع خروج<br />
استفاده از تابع<br />
خارج شويم.<br />
exit<br />
main<br />
سبب مي شود كه از برنامه<br />
return<br />
return<br />
main<br />
هنگامي كه در به دستور مي رسيم<br />
برنامه پايان مي يابد. استفاده از در توابع<br />
ديگر سبب مي شود كنترل برنامه به (يا<br />
تابعي كه تابع فعلي را صدا زده است) بازگردد.<br />
در بعضي موارد نياز است در هر موقعيتي از برنامه<br />
خارج شويم.<br />
تابع از هر exit<br />
برنامه مي گردد.<br />
كجا فراخواني شود، سبب خروج از<br />
•<br />
•<br />
•<br />
•<br />
21
22<br />
مثال (تابع خروج)
Scope های تودرتو و موازی<br />
23
های تودرتو و موازی<br />
(ادامه...)<br />
Scope<br />
هر متغير تنها در محدوده ي خويش معتبر است.<br />
مقدار هر متغير سراسري با تعريف در محدوده ي<br />
جديد override مي گردد.<br />
•<br />
•<br />
استفاده<br />
از اپراتور<br />
باعث مي شود متغير<br />
نشان داده شود<br />
.<br />
global<br />
::<br />
Scope resolution operator<br />
24
توابع بازگشتی<br />
توابع بازگشتی<br />
Overhead<br />
•<br />
•<br />
–<br />
–<br />
–<br />
بالا به دليل فراخواني تابع<br />
نگاه داشتن آدرس بازگشتي، ايجاد متغير ها<br />
مديريت حافظه<br />
در هر بار فراخواني تابع مقداري حافظه اختصاص داده شده مصرف<br />
مي شود.<br />
پياده سازي با دستورالعمل هاي كم تر همراه با ظرافت و خوانايي<br />
بهتر برنامه
مروری بر تابع<br />
در جلسات گذشته در مورد تابع و دلايل استفاده از آن<br />
صحبت كرديم.<br />
گفتيم كه يك تابع به ازاي هر ترتيب از آرگومان هاي<br />
دارد؛<br />
ورودي حداكثر يك خروجي رسمي<br />
با اين حال تاكنون اجباري در استفاده از توابع براي حل<br />
مسائل نداشتيم و هر سوالي كه در مورد آن صحبت<br />
كرديم، مستقل از پياده سازي به وسيله ي توابع نيز، قابل<br />
حل بوده است.<br />
(return value)<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
26
ecursive function<br />
توابع بازگشتی<br />
–<br />
–<br />
–<br />
در اينجا قصد داريم «توابع بازگشتي» را به عنوان ابزاري<br />
براي حل دسته اي وسيع از مسائل معرفي كنيم. اين ابزار<br />
قدرتمند حل بسياري از مسائل را ممكن كرده يا<br />
پياده سازي كد را بسيار ساده مي كند.<br />
به جهت اهميت اين مبحث و دخيل بودن مباني رياضي<br />
مهم ابتدا برخي از اين مباحث را اندكي تشريح مي كنيم.<br />
مطالب مورد بحث به ترتيب عبارت اند از:<br />
استقراي رياضي<br />
روابط بازگشتي<br />
طراحي توابع بازگشتي<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
27
اصل استقرای رياضی<br />
همه شما در دبيرستان با استقراي رياضي آشنا شده ايد و<br />
از آن براي اثبات برخي از احكام رياضي استفاده كرده ايد.<br />
به طور مثال:<br />
«1»<br />
ثابت كنيد كه هر عدد طبيعي بزرگ تر از را مي توان به<br />
عوامل اول تجزيه كرد.<br />
همان طور كه به ياد داريد براي حل يك مسئله توسط<br />
استقرا به يك پايه و يك فرض نيازمنديم. سپس با<br />
استفاده از گام استقرايي و نتيجه گرفتن حكم براي يك<br />
عدد طبيعي خارج از مجموعه فرض، حل را كامل<br />
مي كرديم. يعني از پايه بديهي حكم را براي بقيه اعداد<br />
تعميم مي داديم.<br />
•<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
28
حل<br />
پايه ي استقرا:<br />
بديهي است كه در حالت = 2 n<br />
فرض قوي استقرا:<br />
همه چيز صحيح است.<br />
فرض مي كنيم براي تمام اعداد كوچك تر از k مسئله درست<br />
است.<br />
گام استقرايي:<br />
:<br />
عدد 1+k<br />
يا اول است يا مركب<br />
اگر اول باشد: چون عدد اول است مي توان آن را به صورت<br />
1*(1+k) نوشت و اثبات تمام است.<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
29
حل (ادامه...)<br />
اگر مركب باشد:<br />
چون اين عدد مركب است پس حتما عددي مانند p كه<br />
اولا، اول است و ثانيا از 1+k كوچك تر است وجود دارد به<br />
طوري كه:<br />
k+1 = p*q<br />
كه q<br />
عددي كوچك تر از 1+k است و طبق فرض قوي<br />
استقرا مي توان q را به صورت حاصل ضرب اعداد اول<br />
نوشت و در اينجا كار تمام است.<br />
•<br />
مبانی برنامه نويسی<br />
30
آشنايی با روابط<br />
بازگشتی<br />
گاهي قادر به حل مسائل به خصوص مسائل<br />
شمارشي به صورت صريح نيستيم ولي در صورت<br />
داشتن جواب مسئله در حالات ديگر به راحتي قادر<br />
به حل سوال در حالت جديد خواهيم بود.<br />
به مثال زير كه يك مسئله ي شمارشي است توجه<br />
كنيد:<br />
10 سكه در اختيار داريد كه هر يك داري دو طرف سفيد و سياه<br />
هستند، با اين فرض كه هيچ دو سكه سياهي كنار هم نباشند.<br />
تعداد حالت هاي ممكن چينش را حساب كنيد؟<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
31
روابط بازگشتی (مثال)<br />
–<br />
–<br />
اگر به صورت بندي مسئله بيشتر دقت كنيم مي توانيم<br />
بهتر آن را درك كنيم.<br />
اگر كمي بيشتر به مسئله فكر كنيم درخواهيم يافت<br />
كه مجموعه جواب هاي مسئله به دو دسته افراز<br />
مي شوند:<br />
دسته ي اول شامل اعضايي هستند كه اولين سكه در آن ها<br />
به رنگ سفيد است.<br />
دسته دوم شامل آن هايي كه با سياه آغاز مي شوند.<br />
بديهي است كه عناصر دوم از دسته دوم حتما به رنگ<br />
سفيد هستند (چرا؟)<br />
قبل از ادامه ي داستان(!) توجه شما را به اين حالات<br />
بديهي جلب مي كنيم:<br />
•<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
32
مثال (ادامه...)<br />
فرض كنيد كه تعداد جواب ها براي تعداد n سكه<br />
با نشان داده شوند. در اين صورت:<br />
• F(1) = 2<br />
• F(2) = 3<br />
• ….<br />
F(n)<br />
بياييد كمي به عقب برگرديم، به استقراي رياضي!<br />
مانند استقرا فرض كنيد حل مسئله براي تمام<br />
اعداد كوچك تر از n ممكن بوده و جواب را داريم!<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
33
مثال (ادامه...)<br />
آيا مي شود جواب را محاسبه كرد؟<br />
گفتيم جواب ها چگونه افراز خواهند شد؛ اگر حالت<br />
اول را در نظر بگيريد با داشتن همه<br />
جواب ها را خواهيد داشت:<br />
F(n-1)<br />
•<br />
•<br />
F(n-1)<br />
? ? ….<br />
F(n)<br />
مبانی برنامه نويسی<br />
n - 1<br />
34
مثال (ادامه...)<br />
–<br />
اما از طرفي ديديم كه در حالت دوم مجبور به<br />
گذاشتن سفيد در خانه دوم هستيم پس:<br />
F(n-2)<br />
اگر حاصل را داشته باشيم قادر به محاسبه<br />
اين مجموع نيز هستيم(افزودن تصاوير):<br />
•<br />
F(n-2)<br />
? ? ….<br />
F(n)<br />
n - 2<br />
مبانی برنامه نويسی<br />
35
مثال (ادامه...)<br />
بنابراين براي جوابمان خواهيم داشت:<br />
F(n) = F(n-1) + F(n-2)<br />
در اينجا گام استقرايي ما براي رسيدن به جواب<br />
يك عمل جمع است!<br />
F(n-2)<br />
F(n-1)<br />
•<br />
•<br />
F(n)<br />
مبانی برنامه نويسی<br />
36
مثال (ادامه...)<br />
پس جواب خواهد شد:<br />
• F(1) = 2 F(2) = 3<br />
• F(3) = 5 F(4) = 8<br />
• F(5) = 13 F(4) = 21<br />
• F(7) = 34 F(8) = 55<br />
• F(9) = 89<br />
•<br />
F(10) = 144<br />
مبانی برنامه نويسی<br />
37
الگوريتم های تکراری<br />
براي پياده سازي الگوريتم هايي كه فرايندي را تكرار<br />
مي كنند معمولاً به دو شيوه عمل مي شود:<br />
توابع بازگشتي<br />
Overhead<br />
–<br />
•<br />
–<br />
بالا به دليل فراخواني تابع<br />
نگاه داشتن آدرس بازگشتي، ايجاد متغير ها<br />
مديريت حافظه<br />
•<br />
–<br />
استفاده از حلقه ها<br />
استفاده از توابع بازگشتي<br />
در هر بار فراخواني تابع مقداري حافظه اختصاص داده شده<br />
مصرف مي شود.<br />
پياده سازي با دستورالعمل هاي كم تر همراه با ظرافت<br />
•<br />
•<br />
و خوانايي بهتر برنامه<br />
38<br />
مبانی برنامه نويسی
A recursive function is one that calls itself.<br />
توابع بازگشتی<br />
ساختار توابع بازگشتي به گونه اي است كه خود را<br />
فراخواني مي نمايند.<br />
فراخواني مي تواند به صورت مستقيم و يا<br />
غيرمستقيم از طريق توابع ديگر صورت پذيرد.<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
39
توابع بازگشتی (ادامه...)<br />
تابع زير در<br />
فرامي خواند:<br />
فراخواني بار هر<br />
را خود مجدداً<br />
•<br />
در آيا مشكلي<br />
تابع مي بينيد؟<br />
•<br />
هيچ راه كاري براي توقف تابع تعبيه نشده است.<br />
تابع مانند حلقه ي بي پايان عمل مي كند.<br />
مبانی برنامه نويسی<br />
40
توابع بازگشتی (ادامه...)<br />
براي كاربردي بودن تابع بازگشتي مي بايد به گونه اي<br />
راهي براي توقف تابع در نظر گرفت:<br />
•<br />
مبانی برنامه نويسی<br />
41
مثال<br />
مبانی برنامه نويسی<br />
42
توابع بازگشتی (ادامه...)<br />
مبانی برنامه نويسی<br />
43
Function Calling<br />
پيش تر در مورد صدا كردن يك تابع، ارسال آرگومان و بازگرداندن<br />
خروجي صحبت شد.<br />
•<br />
A complete guide to programming in C++<br />
مبانی برنامه نويسی<br />
44
مثال<br />
مبانی برنامه نويسی<br />
45
توابع بازگشتی (ادامه...)<br />
تابع بازگشتي با شكستن فرآيند ي تكراري به حل<br />
مساله كمك مي كند.<br />
اجراي فرآيند تا زماني كه به يك<br />
برسيم ادامه خواهد داشت.<br />
در<br />
«base case»<br />
base case<br />
مثال قبل زماني است كه پارامتر<br />
برابر با صفر است.<br />
اين صورت فرآيند فراخواني متوقف مي شود.<br />
time<br />
در<br />
•<br />
•<br />
•<br />
•<br />
مبانی برنامه نويسی<br />
46
توابع بازگشتی (ادامه...)<br />
مبانی برنامه نويسی<br />
47
تمرين<br />
• خروجي برنامه ي زير چيست؟<br />
مبانی برنامه نويسی<br />
48
تمرين<br />
• خروجي برنامه ي زير چيست؟<br />
مبانی برنامه نويسی<br />
49