در زبان C، تابع (Function) در واقع همون چیزیه که در زبانهای دیگه مثل Fortran بهش subroutine یا function میگن، و در Pascal هم بهش procedure یا function گفته میشه.
تابع یه روش خیلی کاربردیه برای اینکه یه بخش از محاسبات یا منطق برنامه رو جدا کنیم و در قالب یه تکهی مستقل بنویسیم. اینطوری میتونیم اون بخش رو هرجا لازم بود صدا بزنیم (فراخوانی کنیم) بدون اینکه دوباره کل منطق رو بنویسیم.
به کمک توابع، ما فقط لازم داریم بدونیم چی کار میکنن، نه اینکه چطور اون کار رو انجام میدن.
همین ویژگی باعث میشه کدهامون هم قابلدرکتر بشن و هم تمیزتر.
در زبان C، استفاده از تابعها هم راحت و هم کاراست. خیلی وقتها میتونی یه تابع خیلی کوتاه بنویسی که فقط یه جا استفاده میشه، ولی باعث میشه کدت خواناتر بشه.
نوشتن اولین تابع خودمون
تا حالا ما فقط از توابع آمادهی C مثل printf، getchar و putchar استفاده کردیم. حالا وقتشه خودمون یه تابع بنویسیم.
چون زبان C عملگر توان (مثل ** در Fortran) نداره، میخوایم خودمون تابعی به اسم power(m, n) بنویسیم که عدد m رو به توان n برسونه.
مثلاً خروجی power(2, 5) باید بشه 32.
البته این تابع خیلی سادهست و فقط برای عددهای صحیح مثبت کار میکنه، ولی برای درک ساختار تابع کاملاً کافیه.
(در کتابخونه استاندارد تابع آمادهی pow(x, y) وجود داره که این کار رو بهصورت کاملتر انجام میده.)
کد کامل تابع power
#include <stdio.h>
int power(int m, int n); /* اعلام تابع (prototype) */
/* تست تابع power */
int main(void)
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2, i), power(-3, i));
return 0;
}
/* power: عدد base رو به توان n میرسونه (n >= 0) */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
توضیح کد بالا
در این برنامه، تابع power دو بار درون main صدا زده میشه.
در هر بار، دوتا آرگومان (مثلاً 2 و i) بهش داده میشه، و خودش یه مقدار از نوع عدد صحیح (int) برمیگردونه.
داخل main، این دو تابع در تابع printf قرار گرفتن، یعنی خروجی تابع مستقیماً چاپ میشه.
ساختار کلی تعریف تابع در C
ساختار کلی یه تابع در C اینطوریه:
return-type function-name(parameter declarations, if any)
{
declarations
statements
}
یعنی هر تابع، نوع خروجی داره (مثلاً int یا void)، بعد اسم تابع میاد، بعد از اون داخل پرانتزها لیست پارامترها (در صورت وجود).
prototype (اعلان تابع)
قبل از main ما نوشتیم:
int power(int m, int n);
به این قسمت میگن اعلان تابع (Function Prototype).
این یعنی تابعی به اسم power وجود داره که دوتا عدد صحیح (int) میگیره و یه عدد صحیح برمیگردونه.
پراپتوتایپ به کامپایلر کمک میکنه تا موقع کامپایل مطمئن بشه تابع درست صدا زده شده (از نظر تعداد و نوع آرگومانها).
در واقع، این یه قرارداد بین ما و کامپایلره.
مثلاً میتونستیم بنویسیم:
int power(int, int);
که همون معنی رو داره، فقط بدون نام پارامترها. ولی نوشتن نامها باعث میشه کد خواناتر بشه.
محدوده متغیرها (Scope)
یه نکتهی مهم اینه که هر تابع محدودهی خودش رو داره.
یعنی:
-
پارامترهای تابع فقط داخل همون تابع شناخته میشن.
-
متغیرهایی مثل i و p در تابع power ربطی به i داخل main ندارن.
هرکدوم از این iها مستقل هستن و داخل محدودهی خودشون تعریف شدن.
دستور return
تابع power در نهایت با دستور return p; مقدار محاسبهشده رو برمیگردونه.
هر تابع میتونه مقدار دلخواهی برگردونه (بسته به نوع خروجیاش).
حتی بعضی توابع میتونن هیچ مقداری برنگردونن (در اون صورت نوع تابع void میشه).
اگه تابعی بدون return به انتها برسه (به } آخر برسه)، برنامه بهصورت خودکار به تابع فراخواننده برمیگرده. ولی برای وضوح و اطمینان، همیشه بهتره return بنویسیم.
تابع main هم یک تابع است!
تابع main هم درست مثل بقیه توابعه.
اون هم میتونه یه مقدار int برگردونه، که این مقدار معمولاً برای اعلام وضعیت پایان برنامه به سیستمعامله.
بهصورت قراردادی:
-
مقدار 0 یعنی برنامه با موفقیت اجرا شده.
-
هر مقدار غیرصفر یعنی یه خطا یا وضعیت خاص پیش اومده.
به همین دلیل بهتره همیشه در آخر main بنویسیم:
return 0;
نسخهی قدیمی (Old-style) تعریف تابعها
در نسخههای اولیهی زبان C (قبل از استاندارد ANSI C)، تعریف تابعها یه شکل دیگه بود.
مثلاً تابع power رو اینطوری مینوشتن:
/* power: raise base to n-th power; n >= 0 */
/* (old-style version) */
power(base, n)
int base, n;
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
در این سبک قدیمی:
-
نوع پارامترها بعد از پرانتز و قبل از { نوشته میشد.
-
پارامترهایی که نوع نداشتن، بهصورت پیشفرض int در نظر گرفته میشدن.
-
پراپتوتایپها (مثل int power(int, int);) وجود نداشتن، بنابراین کامپایلر نمیتونست بررسی کنه که آیا تابع درست صدا زده شده یا نه.
استاندارد جدید C (ANSI C) با معرفی پراپتوتایپها این مشکل رو حل کرد و الان تقریباً همه از همین روش جدید استفاده میکنن.
خروجی برنامه power
اگر کد بالا رو اجرا کنید، خروجی بهصورت زیره:
0 1 1
1 2 -3
2 4 9
3 8 -27
4 16 81
5 32 -243
6 64 729
7 128 -2187
8 256 6561
9 512 -19683
در هر خط، مقدار i، 2^i و (-3)^i چاپ میشه.
تمرین ۱-۱۵
برنامهی تبدیل دما از بخش ۱.۲ رو طوری بازنویسی کنید که عمل تبدیل دما توسط تابع انجام بشه.
یعنی تابعی بنویسید که دمای فارنهایت رو بگیره و معادل سلسیوسش رو برگردونه.