לדלג לתוכן

10.5 מצביעי פונקציות תרגול

תרגול - מצביעי פונקציות ו-callbacks - function pointers

תרגול 1 - מחשבון עם dispatch table

  1. כתבו פונקציות לארבע פעולות חשבון: add, sub, mul, div. כל אחת מקבלת שני double ומחזירה double.
  2. צרו typedef בשם math_op_t למצביע פונקציה מתאים.
  3. צרו מערך math_op_t ops[4] שמכיל את ארבע הפונקציות.
  4. צרו מערך char *op_names[4] עם שמות הפעולות.
  5. כתבו תוכנית שמקבלת מהמשתמש שני מספרים ומספר פעולה (0-3), ומבצעת את הפעולה המתאימה באמצעות הdispatch table.
  6. טפלו במקרה של חילוק באפס.

תרגול 2 - apply ו-filter גנריים

  1. כתבו פונקציה void array_apply(int *arr, int n, int (*func)(int)) שמפעילה func על כל איבר במערך.
  2. כתבו פונקציה int array_filter(int *arr, int n, int *out, int (*predicate)(int)) שמעתיקה ל-out רק את האיברים שעבורם predicate מחזירה true. הפונקציה מחזירה את מספר האיברים שהועתקו.
  3. כתבו פונקציה int array_reduce(int *arr, int n, int initial, int (*combine)(int, int)) שמחזירה ערך יחיד - תוצאת הפעלת combine על כל האיברים ברצף (כמו fold/reduce בשפות פונקציונליות).
  4. השתמשו בפונקציות כדי:
  5. להכפיל כל איבר ב-3
  6. לסנן רק מספרים זוגיים
  7. לחשב סכום כל האיברים
  8. לחשב מכפלת כל האיברים

תרגול 3 - מערכת אירועים - event system

  1. הגדירו typedef בשם event_handler_t למצביע לפונקציה שמקבלת const char *event_name ו-void *data.
  2. הגדירו struct בשם event_system שמכיל מערך של עד 10 handlers ומונה.
  3. כתבו פונקציה void register_handler(event_system *sys, event_handler_t handler) שמוסיפה handler למערכת.
  4. כתבו פונקציה void fire_event(event_system *sys, const char *name, void *data) שקוראת לכל הhandlers הרשומים עם שם האירוע והdata.
  5. כתבו שלושה handlers שונים שמדפיסים הודעות שונות.
  6. רשמו אותם ושגרו אירוע - ודאו שכל שלושתם נקראים.

תרגול 4 - פולימורפיזם - צורות גיאומטריות

  1. הגדירו struct בשם shape שמכיל:
  2. const char *type - שם הצורה
  3. double (*area)(struct shape *self) - מצביע לפונקציית שטח
  4. double (*perimeter)(struct shape *self) - מצביע לפונקציית היקף
  5. void (*print)(struct shape *self) - מצביע לפונקציית הדפסה
  6. double params[4] - פרמטרים (רוחב, גובה, וכו')
  7. ממשו "מחלקות" לשלוש צורות:
  8. עיגול (circle) - params[0] = רדיוס
  9. מלבן (rectangle) - params[0] = רוחב, params[1] = גובה
  10. משולש (triangle) - params[0] = בסיס, params[1] = גובה, params[2] = צלע שניה, params[3] = צלע שלישית
  11. כתבו פונקציות "בנאי" - constructor: shape new_circle(double r), shape new_rectangle(double w, double h), shape new_triangle(...).
  12. צרו מערך של 5 צורות מסוגים שונים, ובלולאה הדפיסו את הסוג, השטח, וההיקף של כל אחת.

תרגול 5 - טעינת פלאגין - plugin loading

  1. כתבו ספרייה משותפת (shared library) שמכילה שתי פונקציות:
  2. int plugin_add(int a, int b) - מחזירה a + b
  3. const char *plugin_name(void) - מחזירה את שם הפלאגין
  4. קמפלו אותה כקובץ .so:
    gcc -shared -fPIC -o myplugin.so myplugin.c
    
  5. כתבו תוכנית ראשית שטוענת את הso בזמן ריצה עם dlopen.
  6. השתמשו ב-dlsym כדי למצוא את שתי הפונקציות.
  7. קראו להן והדפיסו את התוצאות.
  8. אל תשכחו לבדוק שגיאות עם dlerror ולקרוא ל-dlclose בסוף.