تیم برنامه نویسی گروه تمدن

مرجع کامل فارسی برنامه نویسی به زبان سی پلاس پلاس

  • Increase font size
  • Default font size
  • Decrease font size

توابع

فرستادن به ایمیل چاپ مشاهده در قالب پی دی اف

به نام خدا

در اين بخش قصد داريم مسائل مربوط به توابع را بيان كنيم.

مفهوم تابع و كاربرد آن

پياده سازي توابع

توابعي با نام يكسان اما با كاركرد متفاوت

نحوه استفاده از توابع در برنامه

فراخواني تابع با اشاره گرها

فراخواني تابع با ارجاع

 

مفهوم تابع و كاربرد آن:

در واقع تابع مفهوم جديدی در برنامه نويسي نيست. براي بيان مفهوم تابع از يك مثال استفاده مي كنيم. فرض كنيد شما مي خواهيد يك سري از محاسبات را براي 10 عدد انجام دهيد. مثلا مي خواهيد ابتدا عدد را با 2 جمع كنيد سپس آن را ضرب در 3 كنيد اگر عدد بزرگ تر از 5 بود منهاي 5 كنيد و در غير اينصورت 5 واحد به عدد اضافه كنيد. همان طور كه مي بينيد براي هر عدد 4 دستور نياز است (1. دستور جمع 2. دستور ضرب 3. دستور if و 4. دستوري كه با چك شدن if صورت مي گيرد.). از سوي ديگر تعداد اعداد ما 10 تاست. ما مي توانيم براي هر عدد اين دستورات را تكرار كنيم. يعني مي بايست 40 خط كد مربوط به اين برنامه را بزنيم. از سوي ديگر اگر تعداد اعداد بيشتر شود مثلا 100تا عدد داشته باشيم  ديگر اين كار غير ممكن است. همچنين اگر يك اشتباه در يك قسمت داشته باشيم يا بخواهيم عمل ديگري به آن اضافه كنيم بايد براي تك تك اين اعداد اين كار را انجام دهيم. به منظور راحتي در برنامه نويسي و امكان اضافه كردن و يا چك كردن سريع و بهينه در برنامه مفهوم تابع ايجاد شده است.

توابع مجموعه دستورات يكساني هستند كه در بدنه برنامه تنها يك بار تعريف مي شوند و براي استفاده از آن مجموعه دستورات كافي است نام آن تابع را بيان كرد و فوايدي همچون جلوگيري از طولاني شدن برنامه، سهولت در بازيابي برنامه ، امكان اضافه كردن منوي جديد به برنامه و ... را دارا مي باشد.

همان طور كه متوجه شديد براي مثال بالا ما اين مجموعه دستورات را فقط يك بار تعريف مي كنيم و هر بار تنها ورودي را تغيير مي دهيم. اين مجموعه دستورات براي متغيري مثل a به صورت زير مي شود:

a+=2;
a*=3;
if (a>5) a-=5;
else     a+=5;

حال كافي است به كامپايلر بفهمانيم كه هر عددي كه به آن معرفي مي كنيم را در دستورات بالا اعمال كن. براي اين كار بايد نحوه تعريف تابع را بدانيم.


 

پياده سازي توابع:

تابع نوشتن هنر جديدي در برنامه نويسي نيست. كافي است دستوراتي كه به طور عادي در main برنامه مي نوشتيم را به صورت زير پياده سازي كنيم.

}(پارامترهاي ورودي) نام تابع    نوع خروجي

مجموعه دستورات

}

پارامتر ورودي:

هر تابع يك سري از عدد،‌كاركتر و... را مي گيرد و روي آن ها پردازش انجام مي دهد. مثلا در مثال بالا پارامتر ورودي از نوع داده اي عدد است. در قسمت پارامتر ورودي نوع داده اي ورودي ها را مشخص مي كنيم. در توابع از متغيرهاي كمكي استفاده مي شود. مثلا در مثال بالا متغير a  را به نمايندگي از تمام اعدادي كه وارد تابع مي شوند در نظر گرفتيم. اين متغيرها را در پارامتر ورودي به همان صورت كه در main‌برنامه تعريف مي كرديم در اين جا نيز تعريف مي كنيم. اگر پارامترهاي ورودي بيش از يكي بودند بايد بين آن ها از ويرگول استفاده كنيم.

فرض كنيد يك تابع داريم كه دو متغير از جنس عدد صحيح و يك متغير از جنس كاراكتر و يك متغير از جنس اعشار دارد. پارامترهاي ورودي به صورت زير تعريف مي شوند:

(int a, char b, double c)

نوع خروجي:

توابع به منظور مختلفي تعريف مي شوند:

1. امكان دارد يك تابع يك سري ورودي از قبيل اعداد را بگيرد و پس از انجام مجموعه دستورات يك نوع داده اي  خاصي را برگرداند (مثلاً براي محاسبه معدل يك دانش آموز، يك تابع نمرات دانش آموز را به عنوان پارامتر ورودي از كاربر مي گيرد و پس از انجام محاسبات مربوطه معدل را بر مي گرداند)

2. امكان دارد در يك تابع نياز باشد تا تابع بيش از يك مقدار را برگرداند.(مثلا علاوه بر محاسبه معدل، نمره بيشترين درس را نيز اعلام كند)

3. امكان دارد يك تابع هيچ مقداري را برنگرداند(مثلا تابع فقط پيغامي را روي صفحه نمايش چاپ  كند)

همان طور كه مشخص است در شماره 1 تابع تنها يك نوع داده اي را بر مي گرداند (در اين مثال معدل از جنس double مي باشد.) ما در نوع خروجي نوع داده اي را مشخص مي كنيم كه تابع قرار است مقدار آن را برگرداند. انواع خروجي مثل همان انواع داده اي در متغير ها مي باشند: double, char, int, float,bool ,...

در اين حالت مقداري كه قرار است تابع برگرداند را در تعریف تابع بعد از كلمه return مي آوريم. نكته قابل توجه اين است كه اگر بعد از كلمه return دستوراتي را بياوريد آن دستورات اجرا نمي شوند. به عبارت ديگر وقتي تابع به كلمه return مي رسد فعاليت خود را پايان مي دهد و به قولي برنامه از تابع خارج مي شود.

}(پارامترهاي ورودي) نام تابع    نوع خروجي

مجموعه دستورات

return مقدار خروجي;

}

براي مثالی كه در ابتدا آورده ايم،  تابع آن به صورت زير مي شود. (نام تابع دلخواه است):

double f1 ( double a){
a+=2;
a*=3;
if (a>5)
 a-=5;
else
     a+=5;
return a;
}//end f1

همان طور كه گفتيم وقتي تابع به كلمه return برسد از تابع خارج مي شود. در اين مثال نيز وقتي شرط چك مي شود كار تابع به پايان مي رسد يعني در مرحله آخر يا از عدد 5 واحد كم مي شود يا 5 واحد به آن اضافه مي شود. اگر از آن 5 واحد كم شود كار تابع تمام است. پس اين گونه تابع فوق را بازنويسي مي كنيم:

double f2 ( double a){
a+=2;
a*=3;
if (a>5)
 return(a-=5);
else
     return (a+=5);
}//end f2

نكته قابل توجه اين است كه نوع خروجي از نوع اعشار است. از طرفي نوع ورودي نيز اعشار است براي همين توانستيم ورودي را به عنوان خروجي در نظر بگيريم. فرض كنيد مثال بالا را براي ورودي صحيح مي خواهيم انجام دهيم اما نوع خروجي از نوع اعشار باشد. براي اين كار دو راه حل وجود دارد:

double f3 (int a){
a+=2;
a*=3;
if (a>5)
a-=5;
else
  a+=5;
double b=a;
return b;
}//end f3


double f4 ( int a){
a+=2;
a*=3;
if (a>5)
 a-=5;
else
    a+=5;
return (a*1.0);
}//end f4

تابع f3 كه نياز به توضيح ندارد. در تابع f4 وقتي عدد a را در يك عدد اعشاري كه همان 1.0 است ضرب مي كنيم حاصل برابر نوع داده اي بزرگ تر يعني double مي شود.

 

در شماره 2و 3 چون تابع يا هيچ مقداري را برنمي گرداند و يا بيش از يك مقدار را برمي گرداند نمي توانيم بگوييم كه نوع داده اي يا نوع خروجي تابع چيست. بنابراين در اين جا نوع تابع را void‌ تعريف مي كنيم. همچنين به دليل اينكه تابع مقدار خاصي را برنمي گرداند ديگر از كلمه return استفاده نمي كنيم.

مثال: تابعي بنويسيد كه پيغام hello world‌ را چاپ نمايد.

void f5(){
cout<<"hello world";
}//end f5

همان گونه كه مشخص است در اين تابع پارامتر ورودي نداريم بنابراين جاي آن را خالي مي گذاريم و نوع خروجي را void‌معرفي مي كنيم.

فرض كنيد ما از تابع f5 در برنامه خود در 20 جاي مختلف استفاده كرده ايم و مي خواهيم علاوه بر اين پيغام در ابتداي آن پيغام Dear User  را نيز چاپ كنيم. اگر از تابع استفاده نمي كرديم مجبور بوديم 20 بار اين پيغام را چاپ كنيم اما حال كافي است اين ويرايش را در تابع انجام دهيم:

void  f5(){
cout<<"Dear User:"}//end f5

 


توابعي با نام يكسان اما با كاركردي متفاوت:

گاهي لازم است از توابعي با نام يكسان اما با كاركردي متفاوت استفاده كرد. يا حتي مي خواهيد مجموعه دستورات يكسان باشد اما به دليل مختلف بودن نوع ورودي بايد دو تابع جداگانه تعريف نماييد.

شما مي توانيد از توابعي با نام يكسان استفاده كنيد. شايد از خود بپرسيد كه كامپايلر از كجا مي فهمد كه شما كدام تابع را فراخواني نموده ايد. جواب اين است كه وقتي مي خواهيد توابعي با نام يكسان تعريف كنيد مي بايست در هنگام تعريف پارامترهاي ورودي آنها با هم متفاوت باشد (نوع خروجي مهم نيست كه يكسان باشد يا نباشد) بنابراين در هنگام استفاده مشخص مي شود كه شما كدام تابع را فراخواني كرده ايد.

مثال اول را براي ورودي صحيح و اعشار يك بار ديگربنويسيد، اگر عدد صحيح بود در پايان پيغام مربوطه و اگر اعشاري بود نيز پيغام مربوط به خودش چاپ شود:

double f6 ( double a){
a+=2;
a*=3;
cout<<"adade vared shode ashari boode"5)
return(a-=5);
else    
return (a+=5);
}//end f6


int f6 ( int a){
a+=2;
a*=3;
cout<<"adade vared shode sahih boode"5)
return(a-=5);
else
     return (a+=5);
}//end f6

همان طور كه مشاهده مي كنيد نام توابع يكسان هستند اما پارامترهاي ورودي فرق مي كنند.

راه ديگر تعريف توابع با نام يكسان اما با عملكرد متفاوت:

راه ديگر اين است كه تعداد پارامترهاي ورودي و يا ترتيب پارامترهاي ورودي را متفاوت در نظر بگيريم. براي روشن شدن موضوع مي توانيم در يك برنامه توابعي با نام هاي زير داشته باشيم:

int f7(int a);
int f7(float a);
void f7(int a,int b);
double f7(int a, float b);
double f7(float a, int b);
...

 


نحوه استفاده از توابع در برنامه
براي تعريف توابع دو روش وجود دارد:
1. قبل از main برنامه و بعد از header ها نام و تعريف توابع را بياوريد. مثال:
# include 
using namespace std;

void f(int a,char b){
...}//end f

int main(){
...}//end programme

2. مي توانيد تعريف آن را بعد از main بياوريد. در اين صورت مي بايست قبل از main‌ به برنامه بگوييد كه چه توابعي در برنامه مورد استفاده قرار گرفته است. براي اين كار كافي است نوع خروجي،‌ اسم تابع، نوع داده اي پارامترها به ترتيب را قبل از main آورده و بعد از main همان گونه كه گفته شد تابع را تعريف نماييد. مثال:

#  include 
using namespace std;

void f(int ,char);

int main(){
...}//end programme

void f(int a,char b){...}//end f
همان طور كه مشاهده مي شود در اعلان تابع قبل از main تنها مشخص كردن نوع داده اي پارامترهاي ورودي كافي است و نيازي نيست كه نام آنها را بياوريم. اما اگر هم بياوريم مشكلي ندارد. ترجيحاً براي تعريف تابع از روش دوم استفاده كنيد. چون كسي كه برنامه شما را مي خواند نيازي ندارد كه بداند شما تابع خود را چگونه تعريف كرده ايد. تنها كافيست كه بداند توابع در برنامه شما چه كارهايي انجام مي دهند كه مي توانيد آن را با كامنت گذاري صحيح بعد از اعلان تابع به كاربر ارائه دهيد.
براي استفاده توابع در main كافي است اسم تابع را بياوريد و به جاي پارامترهاي آن ورودي هاي خود را قرار دهيد. مثال:
# include 
using namespace std;

void f(int a){
cout<}//end f

int main(){
for (int i=0;i<20;i++)
f(i);

f(1389);
int b=9;
f(b);
system("pause");
return 0;
}//end programme
تحليل مثال: ابتدا يك تابع تعريف شده كه عدد ورودي خود را چاپ مي كند. در main برنامه در حلقه for اولي اعداد 0 تا 19 را چاپ مي كند. سپس عدد 1389 را چاپ مي كند و در آخر هم b يا همان مقدار 9‌ را چاپ مي نمايد.

 

فراخواني تابع با اشاره گر:

در استفاده تابع وقتي شما يك ورودي به آن مي دهيد، كامپيوتر يك حافظه جدا براي متغيري كه در تعريف تابع آورده ايم ايجاد مي كند و سپس مقدار آن را برابر مقدار ورودي كه شما به آن داده ايد مي كند و در انتها بعد از انجام دستورات در تابع حافظه اي كه به آن داده را از بين مي برد. بنابراين توابع در ورودي خود تأثير نمي گذارند.

گاهي نياز است يك تابع مقدار ورودي خود را تغيير دهد. شايد بگوييد براي اين كار مي توانيم مقدار خروجي تابع را پس از فراخواني تابع با يك مقدار برابر همان مقدار قرار دهيم تا مقدار ورودي نيز تغيير كند. اين ايده درست است به شرط اينكه بخواهيم تنها يك متغير را دستخوش تغيير كنيم. وقتي تعداد ورودي ها بيش از يكي شود ديگر اين كار ممكن نيست. براي متوجه شدن بهتر موضوع به مثال زير توجه كنيد:

# include
using namespace std;

int f (int a){
a*=2;
cout}// end f

int main(){
int i=3;
f(i);
cout}//end programme

تحليح برنامه: ابتدا يك تابع تعريف كرده ايم كه يك عدد مي گيرد و آن را دو برابر مي كند،‌سپس مقدار آن را چاپ مي كند و در نهايت خروجي تابع 2 برابر ورودي مي شود. در main برنامه يك متغير به اسم i‌با مقدار اوليه 3 تعريف كرده ايم. سپس آن را وارد تابع f مي كنيم. بنابراين مقدار 6 چاپ مي شود. در خط بعدي گفته ايم كه i را چاپ كن. به خاطر اينكه در main برنامه مقدار آن عوض نشده i با همان مقدار اوليه يعني 3 چاپ مي شود. اين مثال بيان گر اين بود كه يك متغير خودش در تابع نقش بازي نمي كند بلكه يك جانشين درست مي كند و آن جانشين است كه دستخوش تغييرات مي شود نه خود متغير اصلي.

براي اينكه مقدار متغير در تابع عوض شود دو راه حل وجود دارد 1. استفاده از اشاره گر ها 2. استفاده از پارامتر مرجع.

اين دو راه حل، مباحث جديدي نيستند. تنها براي يادآوري و اهميت موضوع به بيان آن پرداخته ايم. براي استفاده از اشاره گر ها بايد پارامتر ورودي را از جنس اشاره گر تعريف كنيم و هرجا كه قرار است تغييري روي پارامتر ورودي اعمال شود، بگوييم تغيير روي محتواي خانه اي از حافظه كه اشاره گر به آن اشاره دارد اعمال شود. در هنگام استفاده از تابع نيز به جاي اينكه مقدار متغير را به عنوان ورودي به تابع بدهيم آدرس آن را به تابع بدهيم تا اشاره گر از آن استفاده كند. به همين راحتي!

پارگراف بالا را در دوجمله خلاصه مي كنيم:

جمله اول)‌در هنگام تعريف تابع و معرفي پارامترهاي ورودي از a*‌استفاده شود.

جمله دوم) در هنگام استفاده از تابع يا همان فراخواني از a& استفاده شود.

مثال بالا را با تغيير در متغير به صورت زير مي نويسيم:

# include
using namespace std;

int f (int *a){
(*a)*=2;
cout<<(*a);
return (*a);
}// end f

int main(){
int i=3;
f(&i);
cout}//end programme

در این مثال هر دو دستور چاپ مقدار 6 را چاپ می نماید.


فراخواني تابع با ارجاع
كاربرد فراخواني با ارجاع هم دقيقاً مثل فراخواني با اشاره گر مي باشد. توضيح آن نيز به اين صورت است كه در پارامتر مرجع گفتيم هر اتفاقي كه براي پارامتر مرجع بيفتد مثل اين است كه براي متغير اوليه افتاده است. در اين جا از اين خصوصيت استفاده مي كنيم.
دو جمله خلاصه به اين صورت است:
جمله اول) در هنگام تعريف تنها در پارامتر ورودي مثل تعريف پارامتر مرجع از a&‌استفاده شود.
جمله دوم) در هنگام استفاده يا فراخواني از مقدار متغير يعني a استفاده شود.
بنابراين مثال بالا به شكل زير در مي آيد.
#  include
using namespace std;

int f (int &a){
a*=2;
cout}// end f

int main(){
int i=3;
f(i);
cout}//end programme

 

براي تمرين بيشتر مي توانيد برنامه هايي كه تاكنون نوشتيد را به وسيله توابع بنويسيد.

در صورت داشتن هر گونه سوال و یا اشکال  مي توانيد آن را از طریق  افزودن نظر در همین بخش عنوان نمایید.

آخرین بروز رسانی مطلب در شنبه ، 25 خرداد 1392 ، 01:49  

افزودن نظر

دوست عزیز و کاربر گرامی
نظرات بعد از بررسی در سایت درج خواهند شد.
مطمئنا از شنیدن انتقادهای شما خوشحال خواهیم شد.
دلیل فیلتر کردن نظرات صرفا جلوگیری از نظرات مغایر با اسلام و جمهوری اسلامی ایران می باشد. امیدواریم ما را به خاطر این کار درک نمایید. با تشکر






کد امنیتی
بازنشانی