C/C++ מדריכי
C הקדמה לתכנות ב
C++ הקדמה להיררכית מחלקות ב הצגה מזורזת :C++ הבנת דף הבית

שיעור 6: פונקציות

רוב השפות מאפשרות לך ליצור פרוצדורות או פונקציות, או שתיהן. C מאפשרת רק פונקציות, אם כי ניתן ליצור פרוצדורות על ידי כתיבת פונקציות שלא מחזירות ערך. פונקציות C יכולות לקבל מספר לא מוגבל של פרמטרים. כפי שמוזכר בהקדמה, הן לא יכולות להיות מקוננות. באופן כללי, ל C לא אכפת באיזה סדר תשים את הפונקציות בתוכנית.

כבר דיברנו מעט על פונקציות. פונקצית ה rand בשיעור 4 היא בערך הכי פשוטה שפונקציה יכולה להיות. היא לא מקבלת פרמטרים ומחזירה מספר שלם.

int rand() 
/* from K&R - produces a random number between 0 and 32767.*/ 
{ 
    rand_seed = rand_seed * 1103515245 +12345; 
    return (unsigned int)(rand_seed / 65536) % 32768; 
}

השורה ()int rand מצהירה על פונקצית ה rand ליתר התוכנית ומציינת שהפונקציה לא תקבל פרמטרים ותחזיר מספר שלם. לפונקציה זו אין משתנים מקומיים, אבל אם היא הייתה זקוקה למשתנים גלובליים, הם היו נכנסים מייד אחרי ה } הפותחות. (C למעשה מאפשרת לך להצהיר על משתנים לאחר כל }. משתנים אלו נעלמים ברגע שמגיעים ל { התואמים. כל עוד הם קיימים, הם ממוקמים במחסנית המערכת.) שים לב שאין כל ; אחרי ה () בשורה הראשונה. אם בטעות תשים נקודה פסיק, תקבל רשימה מדורגת ענקית של הודעות שגיאה שאין בהם כל היגיון. יש לציין גם שלמרות שאין פרמטרים, חייבים להשתמש ב (). הם אומרים למהדר שאתה מצהיר על פונקציה ולא על סתם int.

פקודת ה return חשובה לכל פונקציה שמחזירה תוצאה. היא נותנת לפונקציה את הערך להחזיר וגורמת לה לצאת מייד. פירושו של דבר שאתה יכול לשים פקודות return רבות בפונקציה כדי לתת לה נקודות יציאה רבות. אם לא שמים פקודת return בפונקציה, הפונקציה חוזרת כאשר היא מגיעה ל { ונותנת זבל (מהדרים רבים יזהירו אותך אם לא תחזיר ערך). ב C, פונקציה יכולה להחזיר ערך מכל סוג שהוא.

ישנן מספר דרכים נכונות לקרוא לפונקצית ה rand - לדוגמא: ;()x=rand. ה x מקבל את הערך שמוחזר על ידי ה rand בפקודה זו. שים לב שאתה חייב להשתמש ב () בקריאה לפונקציה, אפילו אם לא מועברים פרמטרים. אחרת, x מקבל את כתובת הזיכרון של פונקצית ה rand, שזה בדרך כלל לא מה שרצית. ניתן גם לקרוא ל rand בדרך זו:

if (rand() > 100)

או בדרך זו:

rand();

במקרה השני, הערך המוחזר על ידי ה rand נזרק. ייתכן שלעולם לא תרצה לעשות זאת עם rand, אבל פונקציות רבות מחזירות איזשהו קוד שגיאה באמצעות שם הפונקציה, ואם אינך מוטרד מקוד השגיאה (למשל, בגלל שאתה יודע ששגיאה היא בלתי אפשרית) אתה יכול להשליך אותו בדרך זו.

יוצרים פרוצדורות (במובן של פסקל) על ידי נתינת טיפוס החזרה של void לפונקציה. לדוגמא:

void print_header()  
{     
    printf("Program Number 1\n");     
    printf("by Marshall Brain\n");     
    printf("Version 1.0, released 12/26/91\n");  
} 

פונקציה זו לא מחזירה ערך, לכן היא פרוצדורה. ניתן לקרוא לה באמצעות הפקודה הבאה:

print_header();

יש לכלול את ה () בקריאה. אחרת, לא מתבצעת קריאה לפונקציה, למרות שבמערכות רבות המהדר לא יתריע על שגיאות.

פונקציות C יכולות לקבל פרמטרים מכל סוג שהוא. לדוגמא:

int fact(int i)  
{    
    int j,k; 
    
    j=1; 
    for (k=2; k<=i; k++) 
        j=j*k;    
    return j;  
} 

מחזיר עצרת של i, שמועבר כפרמטר של int. מפרידים בין פרמטרים שונים באמצעות פסיקים:

int add (int i, int j)  
{    
    return i+j;  
}

C התפתחה עם השנים. לעיתים קרובות תראה פונקציות כמו פונקצית החיבור שכתובה "בסגנון הישן", כמוצג להלן:

int add(i,j)  
    int i;  
    int j;  
{    
    return i+j;  
} 

חשוב מאוד להיות מסוגל לקרוא קוד שכתוב בסגנון הישן יותר. אין כל הבדל בדרך שבה הוא מתבצע, זוהי רק כתיבה שונה. יש להשתמש ב"סגנון החדש", (מוכר כ "ANSI C") כאשר הטיפוס מוצהר כחלק מרשימת הפרמטרים, אלא אם כן אתה יודע שתשלח את הקוד למישהו שיש לו גישה רק למהדר מ"הסגנון הישן" (non-ANSI).

כיום זה נחשב לנוהג טוב להשתמש באבות טיפוס לפונקציות בכל הפונקציות בתוכנית שלך. אב טיפוס מצהיר על שם הפונקציה, הפרמטרים שלה, וטיפוס ההחזרה שלה לשאר התוכנית באופן דומה להצהרת forward בפסקל. כדי להבין מדוע אבות טיפוס לפונקציות הם שימושיים, הדפס והרץ את הקוד הבא:

#include <stdio.h> 
 
void main()  
{    
    printf("%d\n",add(3));  
} 
 
int add(int i, int j)  
{    
    return i+j;  
} 

קוד זה עובר הידור מבלי לתת לך אזהרות, למרות ש add מצפה לשני פרמטרים אבל מקבלת רק אחד, כיוון ש C לא בודקת התאמת פרמטרים לא בסוג ולא במספר. אפשר לבזבז כמות עצומה של זמן על איתור באגים בקוד שבו אתה פשוט מעביר פרמטר אחד יותר מידי או פחות מידי. הקוד הנ"ל עובר הידור כראוי, אבל הוא מייצר את התשובה הלא נכונה.

כדי לפתור את הבעיה הזו, C מאפשרת לך למקם אבות טיפוס לפונקציות בהתחלה של (למעשה, בכל מקום ב) תוכנית. אם תעשה כך, C תבדוק את הטיפוסים ותספור את כל רשימות הפרמטרים. נסה להדר את הקוד שלהלן:

#include <stdio.h> 
 
int add (int,int); /* function prototype for add */ 
 
void main()  
{    
    printf("%d\n",add(3));  
} 
 
int add(int i, int j)  
{    
    return i+j;  
} 

אב הטיפוס גורם למהדר לאותת על שגיאה בפקודת ה printf.

שים אב טיפוס של כל פונקציה בהתחלת התוכנית שלך. הם יכולים לחסוך לך המון זמן של איתור באגים, והם גם פותרים את הבעיה שנוצרת לך כאשר אתה מהדר עם פונקציות שאתה משתמש בהן לפני ההצהרה עליהן. לדוגמא, הקוד הבא לא יעבור הידור:

#include <stdio.h> 
 
void main()  
{    
    printf("%d\n",add(3));  
} 
 
float add(int i, int j)  
{    
    return i+j;  
} 

למה, אתה עשוי לשאול, הוא יעבור הידור כאשר add מחזיר int אבל לא כאשר הוא מחזיר float? כיוון שברירת המחדל של C היא ערך מוחזר מטיפוס int. שימוש באב טיפוס יפתור את הבעיה הזו. מהדרים מ"סגנון ישן" (non-ANSI) מאפשרים אבות טיפוס, אבל על רשימת הפרמטרים להיות ריקה. מהדרים מהסוג הישן לא מבצעים בדיקת שגיאות על רשימות פרמטרים.




לדף הראשון

<< לדף הקודם

לדף הבא >>