در این جلسه توابع در زبان C را همراه با مثال یادمیگریم. اول از همه باید بدونیم تابع چیست؟ توابع در برنامه نویسی یک بلوک کد با قابلیت استفاده مجدد است که تست و درک برنامه را آسان کرده و بدون تغییر برنامه فراخواننده، به راحتی می توان آنها را ویرایش کرد. توابع به منظور تقسیم بندی کدها و ماجوله سازی برنامه برای نتایج بهتر و موثرتر استفاده می شوند. به طور خلاصه، برنامههای بزرگتر به زیربرنامههای متعددی تقسیم شده که تابع نامیده می شوند.
وقتی یک برنامه بزرگ را به توابع متعدد تقسیم می کنید، مدیریت هر تابع به صورت مجزا آسان خواهد گردید. هروقت که خطایی در برنامه رخ دهد، به راحتی تابع معیوب را بررسی کرده و خطاهای آن را تصحیح می کنید. به هنگام نیاز، به راحتی می توانید توابع را فراخوانی کرده که این به صورت خودکار به صرفه جویی در زمان و فضا منجر خواهد شد.
در این مبحث خواهید آموخت:
- تابع چیست؟
- توابع کتابخانهای در برابر توابع تعریف شده توسط کاربر
- تعریف تابع
- فراخوانی تابع
- آرگومان های تابع
- دامنه متغیر
- متغیرهای ایستا
- توابع بازگشتی
- توابع درون خطی
توابع کتابخانه ای در برابر توابع تعریف شده توسط کاربر
هر برنامه زبان C حداقل دارای یک تابع بوده که همان تابع main است، اما یک برنامه می تواند شامل هر تعداد تابعی باشد. تابع ()main نقظه آغاز یک برنامه است.
در برنامه نویسی C، توابع به دو دسته تقسیم می شوند:
- توابع کتابخانه ای
- توابع تعریف شده توسط کاربر
تفاوت بین توابع کتابخانه ای و توابع تعریف شده توسط کاربر این است که برای یک تابع کتابخانه ای نیازی به کدنویسی نداریم. این توابع از قبل در هدرفایلی موجود بوده که ما همواره آن را در ابتدای برنامه ضمیمه می کنیم. تنها کافی است نام تابع را نوشته و با یک دستور زبان مناسب بکار گیریم. Printf و scanf مثالهایی از توابع کتابخانه ای هستند.
در حالی که تابع تعریف شده توسط کاربر، تابعی است که بدنه آن را نوشته و موقع نیاز به انجام عملیات در برنامه خود، آن را فراخوانی می کنیم.
در برنامه نویسی زبان C توابع به سه کار تقسیم می شوند:
- اعلان تابع
- تعریف تابع
- فراخوانی تابع
اعلان تابع
اعلان تابع به معنی نوشتن یک نام برای یک برنامه است. این کار برای استفاده از تابع در کدها ضروری است. در اعلان یک تابع، همانند اعلان یک متغیر، تنها نامی برای تابع مورد استفاده در برنامه مان می نویسیم. تا زمانی که تابع را اعلان نکنیم، نمی توان از آن در برنامه استفاده کرد. اعلان تابع همچنین با عنوان “نمونه اولیه تابع”( Function prototype) خوانده می شود.
اعلان تابع(نمونه اولیه) معمولاً در بالای تابع ()main نوشته می شود و شکل عمومی زیر را دارند:
return_data_type function_name (data_type arguments);
- return_data_type: نوع داده ای که تابع به عبارات فراخواننده برمی گرداند.
- Function_type: پرانتز باز و بسته پس از آن می آید.
- Arguments: نام آرگومانها همراه با نوع داده های مربوطه که به صورت اختیاری درون پرانتزها قرار می گیرند.
برنامه زیر را که در آن، نحوه اعلان تابع cube برای محاسبه مکعب یک متغیر صحیح نشان داده شده است را ملاحظه کنید.
#include <stdio.h> /*Function declaration*/ int add(int a,b); /*End of Function declaration*/ int main() {
توجه داشته باشید که یک تابع لزوماً مقداری را برنمی گرداند. در این حالت،از کلیدواژه void استفاده می شود.
برای مثال، اعلان تابع output_message نماینگر این است که تابع هیچ مقداری برنمی گرداند:
void output_message()
تعریف تابع
تعریف تابع به معنای نوشتن بدنه آن است. بدنه یک تابع شامل دستوراتی است که قرار است یک وظیفه مشخص را انجام دهند. بدنه تابع می تواند حاوی یک دستور یا بلوکی از دستورات باشد. بدنه تابع بخش اجباری تابع است.
int add(int a,int b) //function body { int c; c=a+b; return c; }
فراخوانی تابع
فراخوانی تابع به معنی صدا کردن آن در زمانهایی است که برنامه به آن نیاز دارد. هرزمان که یک تابع را فراخوانی می کنیم، دستوراتی که برای انجام آنها طراحی شده بود را اجرا می کند. فراخوانی یک تابع بخش اختیاری یک برنامه است.
result = add(4,5);
در زیر کد کامل آورده شده است:
#include <stdio.h> int add(int a, int b); //function declaration int main() { int a=10,b=20; int c=add(10,20); //function call printf("Addition:%d\n",c); getch(); } int add(int a,int b) //function body { int c; c=a+b; return c; }
خروجی:
Addition:30
آرگومان های تابع
آرکومان های تابع برای دریافت مقادیر مورد نیاز فراخوان تابع بکار می روند. آرگومانها از نظر مکانی باید تطابق داشته باشند؛ آرگومان اول در جای پارامتر اول، آرگومان دوم در پارمتر دوم و… قرار داده میشوند.
به صورت پیش فرض، آرگومان ها به صورت مقداری(pass by value) به تابع ارسال می شوند، بدین معنی که یک کپی از داده به تابع فراخوانده شده ارسال می شود. متغیر واقعی ارسال تغییری نخواهد کرد.
برنامه زیر را ملاحظه کنید که در آن پارمترها به صورت مقداری ارسال می شوند:
int add (int x, int y); int main() { int a, b, result; a = 5; b = 10; result = add(a, b); printf("%d + %d\ = %d\n", a, b, result); return 0;} int add (int x, int y) { x += y; return(x);}
خروجی برنامه خواهد بود:
5 + 10 = 15
توجه داشته باشید که متغیرهای a و b ارسال شده به تابع add تغییر نخواهند کرد زیرا مقادیر آنها به پارامتر x ارسال شده است.
دامنه متغیر
دامنه متغیر، میزان رویت پذیری متغیرها درون کدهای برنامه می باشد.
در زبان C، متغیرهایی که درون یک تابع اعلان می شوند برای آن بلوک کد محلی به حساب آمده و نمی توان خارج از تابع به آنها رجوع کرد. اگرچه، متغیرهایی که خارج از تابع تعریف می شوند سراسری بوده و در سرتاسر برنامه قابل دسترسی هستند. ثابت های اعلان شده با #define در بالای برنامه، در سرتاسر برنامه قابل دسترسی هستند. در برنامه زیر، مقدار یک متغیر سرتاسری هم از درون تابع main و هم از درون تابع تعریف شده توسط کاربر چاپ شده است:
#include <stdio.h> int global = 1348; void test(); int main() { printf("from the main function : global =%d \n", global); test () ; return 0;} void test (){ printf("from user defined function : global =%d \n", global);}
نتیجه:
from the main function : global =1348 from user defined function : global =1348
راجع به جزئیات برنامه صحبت خواهیم کرد:
- یک متغیر صحیح سراسری با مقدار اولیه 1348 اعلان می کنیم.
- تابع ()test که هیچ آرگومانی دریافت نکرده و مقداری نیز برنمی گرداند را اعلان و تعریف می کنیم. این تابع تنها مقدار متغیر سراسری را چاپ می کند تا نشان دهد که متغرهای سراسری در همه جای برنامه قابل دسترسی هستند.
- متغیر سراسری را از درون تابع main چاپ می کنیم.
- تابع test را به منظور چاپ متغیر سراسری فراخوانی می کنیم.
در زبان C، زمانی که آرگومان ها به پارمترهای تابع ارسال می شوند، پارمترها به منزله متغیرهای محلی عمل کرده و هنگام خروج از تابع از بین می روند.
برای استفاده از متغیرهای سراسری باید دقت به خرج داد زیرا ممکن است منجر بروز خطا شده ،چون محتوای آن ها را می توان از هرجای برنامه تغییر داد. این متغیرها حتما قبل از استفاده باید مقداردهی اولیه شوند.
متغیرهای ایستا
متغیرهای ایستا دامنه محلی دارند. اما هنگام خروج از تابع محو نمی شوند. بنابراین، متغیر ایستا مقدار خود را تا همیشه نگه داشته و هنگام ورود مجدد به تابع می توان به آنها دسترسی پیدا کرد. متغیر ایستا هنگام اعلان مقداردهی اولیه شده و با پیشوند static نوشته می شود.
برنامه زیر از متغیر ایستا بهره می برد:
#include <stdio.h> void say_hi(); int main() { int i; for (i = 0; i < 5; i++) { say_hi();} return 0;} void say_hi() { static int calls_number = 1; printf("Hi number %d\n", calls_number); calls_number ++; }
برنامه خروجی زیر را نشان می دهد:
Hi number 1 Hi number 2 Hi number 3 Hi number 4 Hi number 5
توابع بازگشتی در زبان C
فاکتوریل یک عدد را درنظر بگیرید که به شکل 6! = 6 * 5 * 4 * 3 * 2 * 1 محاسبه می شود.
محاسبه با انجام متوالی عبارت (fact * (fact – 1 تا زمان برابر شدن fact با مقدار 1 ادامه می یابد.
یک تابع بازگشتی تابعی است که خودش را به صورت مداوم صدا زده و لز یک شرط برای پایان دادن به فراخوانی بازگشتی بهره می گیرد.. در مورد محاسبه فاکتوریل عدد، شرط خروج این است که fact برابر 1 گردد. عملیات بازگشتی به فراخوانی “پشته سازی” (stacking) تا زمان true شدن شرط خروجی ادامه م یدهد.
برای مثال:
#include <stdio.h> int factorial(int number); int main() { int x = 6; printf("The factorial of %d is %d\n", x, factorial(x)); return 0;} int factorial(int number) { if (number == 1) return (1); /* exiting condition */ else return (number * factorial(number - 1)); }
برنامه خروجی زیر را نمایش می دهد:
The factorial of 6 is 720
درباره جزئیات برنامه بحث خواهیم کرد:
- تابع بازگشتی خود را اعلان کرده که یک پارمتر integer دریافت کرده و مقدار فاکتوریل این پارامتر را برمی گرداند. این تابع خودش را فراخوانی کرده و عدد را تا هنگام خروج یا تا رسیدن به شرط پایه ای کاهش می دهد. وقتی که شرط برقرار گردید، اعداد تولید شده قبلی درهم ضرب شده و فاکتوریل نهایی برگردانده می شود.
- یک متغیر Integer با مقدار “6” را اعلان و مقداردهی اولیه کرده و فاکتوریل آن را با فراخوانی تابع فاکتوریل چاپ می کنیم.
نمودار زیر را برای درک بهتر سازوکار بازگشتی ملاحظه کنید، این نمودار شامل فراخوانایی تابع توسط خودش تا زمان رسیدن به کیس پایه ای و یا برقرارشدن شرط توقف می باشد، و پس از آن مقادیر قبلی جمع آوری می شوند:
توابع درون خطی(Inline Function)
توابع برای ذخیره دستورات پرکاربرد استفاده می شوند. توابع برای ماجوله سازی برنامه بکار می روند.
هربار که یک تابع فراخوانی می شود، اشاره گر دستور(instruction pointer) به محل تعریف تابع پرش می کند. بعد از اجرای تابع، اشاره گر دستور به دستوری بازگشت می کند که از آن جا به تعریف تابع پرش کرده بود.
هنگام استفاده از توابع، به یک سر اشاره گر(pointer head) اضافی برای پرش به تعریف تابع و بازگشتن به دستور نیاز داریم. برای عدم نیاز به چنین سراشاره گری، از توابع درون خطی استفاده می کنیم.
در یک تابع درون خطی، یک کد برنامه واقعی مستقیماً جایگزین فراخوانایی تابع می شود. اشاره گر به هیچ بلوکی پرش نمی کند و همه عملیات درون تابع درون خطی انجام می شوند.
توابع درون خطی بیشتر برای محاسبات کوچک بکار می روند. این توابع برای انجام محاسبات بزرگ مناسب نیستند.
یک تابع درون خطی شبیه یک تابع معمولی بوده با این تفاوت که کلیدواژه inline قبل از نام تابع گذاشته می شود. توابع درون خطی با دستور زبان زیر ساخته می شوند:
inline function_name () { //function definition }
اجازه دهید برنامه ای برای پیاده سازی یک تابع درون خطی بنویسیم:
inline int add(int a, int b) //inline function declaration { return(a+b); } int main() { int c=add(10,20); printf("Addition:%d\n",c); getch(); }
خروجی:
Addition: 30
برنامه فوق استفاده از یک تابع درون خطی برای جمع دو عدد را نشان می دهد. همانطور که می بینیم، حاصل جمع دو عدد را درون تابع درون خطی بدون نوشتن هیچ خط اضافه ای بازگردانده ایم. هنگام فراخوانی تابع تنها مقادیری که عمل جمع را باید روی آنها انجام دهیم را ارسال کرده ایم.
خلاصه توابع در زبان C
- هر تابع یک برنامه کوچک یا یک زیربرنامه است.
- توابع برای ماجوله کردن برنامه بکار می روند.
- انواع توابع، توابع کتابخانه ای و توابع تعریف شده توسط کاربر هستند.
- یک تابع شامل اعلان، بدنه تابع، و بخش فرخوانی تابع می باشد.
- اعلان تابع و بدنه تابع بخش های ضروری تابع هستند.
- فراخوانی تابع در یک برنامه اختیاری است.
- برنامه های C حداقل یک تابع دارند. این تابع تابع ()main می باشد.
- هر تابع دارای یک نام، نوع داده مقدار بازگشتی یا void و پارامترها می باشد.
- هر تابع باید در برنامه C اعلان و تعریف شود.
- توجه داشته باشید که متغیرهای معمولی در یک تابع C هنگام خروج از تابع از بین می روند.
- آرگومان های ارسال شده به تابع تغییر نخواهند کر زیرا آنها را به صورت مقداری و نه به صورت آدرسی ارسال شده اند.
- دامنه متغیر به میزان رویت پذیری متغیرها در برنامه گفته می شود.
- در برنامه نویسی زبان C متغیرهای سراسری و متغیرهای محلی داریم.
- توابع در زبان C خیلی کاربری هستن و در ادامه در درس زبان ++C بیشتر با کاربردهای پیشرفته آن آشنا خواهیم شد.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.
خیلی خوب بود ممنون.
بسیار روان و کاربردی.خیلی ممنون