עבור לתוכן

שאלה ב C

Featured Replies

פורסם

בשפת C

הגדרתי שני structures:

typedef struct {

int x;

int y;

} a;

typdef struct {

int x;

float y;

int z;

} b;

אני רוצה לכתוב פונקציה שתבצע פעולה זהה על המבנים אבל אני צריך לשכפל אותה בגלל שוני ה TYPE

לדוגמא :

int foo_a(a* s)

{

return (int)(s->x +s->y);

}

int foo_b(b* s)

{

return (int)(s->x +s->y);

}

איך אפשר לאחד לפונקציה אחת ?

שנראית בערך כך:

int foo(void *s)

{

return (int)(s->x + s->y);

}

פורסם

שים את הקוד בתוך תווית קוד (#), ע"מ שנוכל לענות לך על השאלה.

פורסם

אם מותר לך לעבוד בC++, התשובה ברורה מאלייה:

ירושה או templates

אם אתה מוגבל לC, אפשר לבצע את הדבר הבא (זה נראה כמו OOP עקום בהתחלה, אבל זה יכול לעבוד נהדר - הקרנל של לינוקס וכל הדרייברים כתובים ככה לדוגמא):


typedef struct
{
int x;
int y;
}Base;


typedef struct
{
Base b;
float f;
} Extended;

ומכאן אתה פשוט מעביר את b מתי שצריך.

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

פורסם

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

אם לא הבנת את המשפט, אל תעשה אותו. אם הבנת אותו, אתה יודע לא לעשות את זה.

לפעמים כאשר כותבים ספריות ופלטפורמות ב-C, מקרואים זו הדרך הטובה ביותר.

פורסם
  • מחבר

תודה ,

1. אני מוגבל רק ל C

2. הפתרון של EXTENDED לא מתאים .הדוגמא היא רק דוגמא המבנים הרבה יותר מסובכים ושונים רק המשמעות של המשתנים אותה משמעות ולכן אני רוצה לשלוח אותם לפונקציה אחת .

3. לא הבנתי את הקשר של המקרו לבעייה .

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

פורסם

תודה ,

1. אני מוגבל רק ל C

2. הפתרון של EXTENDED לא מתאים .הדוגמא היא רק דוגמא המבנים הרבה יותר מסובכים ושונים רק המשמעות של המשתנים אותה משמעות ולכן אני רוצה לשלוח אותם לפונקציה אחת .

3. לא הבנתי את הקשר של המקרו לבעייה .

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

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

2 - אם המבנים שונים אבל יש להם אותה משמעות, זה בהחלט פוטנציאל למה שהראה לך moonblade.

בכל מקרה הדבר תלוי באיך המבנים מאורגנים - או יותר נכון לומר צריך לארגן את המבנים ואז אפשר לעשות את הדברים הדרושים.


typedef struct
{
int salary;
int months;
int bonus;
int employee_id;
} EmployeeRecord;

typedef struct
{
EmployeeRecord employee_data;
int has_secretary;
int num_subordinates;
} Manager;

typedef struct
{
EmployeeRecord employee_data;
int num_computers;
} Programmer;

int GetSalary(const EmployeeRecord* er)
{
if (er == NULL) return 0;
return er->salary * er->months + er->bonus;
}

int main()
{
Manager m;
Programmer p;

... /* some code */

printf("manager gets %d\n", GetSalary(&m.employee_data);
printf("programmer gets %d\n", GetSalary(&p.employee_data);

... /* some code */

return 0;
}

זו לא בהכרח הדרך הטובה ביותר, אבל זו דרך אחת פשוטה ובטוחה יחסית לתוכניות פשוטות.

פורסם

שני טיפוסים שתי פונקציות.

אין קיצורי דרך.

זו גם הדרך הנכונה.

גם ב++C ועם templates לבסוף נוצרות שתי פונקציות.

פורסם

כמו שהראה moonblade אפשר לעשות ירושה ב-C וכך לכתוב פונקציה אחת. לא בהכרח מומלץ להכל, אבל יש הרבה דברים שכתובים ככה:


typedef struct
{
int x;
int y;
} Base;

#define UPCAST_TO_BASE_PTR(x) (&((x).base))
#define INHERIT_BASE Base base

typedef struct
{
INHERIT_BASE;
char c;
float f;
} DerivedA;

typedef struct
{
INHERIT_BASE;
int z;
int w;
} DerivedB;

int BaseGetSum(const Base* base)
{
assert(base != NULL);
return base->x + base->y;
}

int main()
{
DerivedA a;
DerivedB b;
...
int sum_a = GetSum( UPCAST_TO_BASE_PTR(a) );
int sum_b = GetSum( UPCAST_TO_BASE_PTR(b) );
...
}

בעזרת קצת יותר השקעה אפשר להגיע לתוצאות טובות יותר, קלות יותר לשימוש, ובטוחות יותר.

פורסם
  • מחבר

תודה על כל העזרה ,

אבל השתכנעתי שכנראה לשכפל את הפונקציה היא הדרך הטובה ביותר - כך הקוד נישאר מובן ופחות באגים בהמשך

פורסם

כנראה קיבלת את ההחלטה הנכונה.

הסיבוך מהשטן, הפשטות מהרחמן.

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים