340 likes | 453 Views
מבנים. יצירת טיפוסים חדשים. כאשר פותרים בעיה כלשהי באמצעות תוכנה אז רצוי לייצר טיפוסי נתונים אשר קרובים יותר לבעיה אשר פותרים . למשל אם נכתוב תוכנה שמתעסקת בגיאומטריה נרצה טיפוס נתונים שמתאר נקודה במישור. יצירת טיפוסים חדשים.
E N D
יצירת טיפוסים חדשים • כאשר פותרים בעיה כלשהי באמצעות תוכנה אז רצוי לייצר טיפוסי נתונים אשר קרובים יותר לבעיה אשר פותרים. • למשל אם נכתוב תוכנה שמתעסקת בגיאומטריה נרצה טיפוס נתונים שמתאר נקודה במישור.
יצירת טיפוסים חדשים • שפת C מאפשרת לנו לייצר טיפוסים חדשים אשר קרובים יותר לפתרון הבעיה. • המילה השמורה המשמשת אותנו לכך היא struct.
יצירת טיפוסים חדשים • אם ברצוננו ליצור מבנה עבור נקודה במישור צריך שתי קורדינאטות X ו Y. struct point { double x; double y; }; • הגדרה זו מופיעה מחוץ לכל פונקציה. (בסמוך ל-prototypes ) • כעת בתוכנית ניתן להגדיר משתנים שזהו סוגם.
יצירת טיפוסים חדשים int main() { struct point P1,P2; } • הגדרנו שתי נקודות האחת P1 והשנייה P2. P2 P1
יצירת טיפוסים חדשים P1.x = 6; P1.y = 7; P2.x = 4; P2.y = 2; P2 P1 4 6 2 7
יצירת טיפוסים חדשים • הגדרה פורמלית: Struct שם הטיפוס החדש{ טיפוסשם השדה; ….. טיפוסשם השדה; }; הגדרת משתנה : שם משתנהשם הטיפוס החדש Struct פנייה לשדה של משתנה מטיפוס מסוים היא ע"י שם משתנה.שם השדה
יצירת טיפוסים חדשים • אתחול: • דרך נוספת לאתחל משתנה כזה היא בשורת האתחול. • struct point P = {6,7}; • X יאותחל ל-6 ו-y ל-7. באופן כללי האיבר הראשון לשדה הראשון השני לשני ....
יצירת טיפוסים חדשים • מה יקרה כתוצאה מהשורה הבאה: • P1 = P2; • ההתנהגות במקרה כזה היא פשוטה מאוד התוכן של P2 מועתק לתוך P1.(העתקה שדה שדה) • ההשוואה (==) אינה תקפה עבור מבנים • (גם פעולות חשבון אינן תקפות)
יצירת טיפוסים חדשים • נרצה לכתוב פונקציה שמחשבת מרחק בין שתי נקודות. double dist( struct point p, struct point q) { double d; d = (p.x – q.x)*(p.x – q.x) + (p.y – q.y)*(p.y – q.y); return sqrt(d); }
יצירת טיפוסים חדשים …. int main() { struct point p,q; printf(“Enter point\n”); Scanf(“%lf%lf”, &p.x,&p.y); printf(“Enter point\n”); Scanf(“%lf%lf”, &q.x,&q.y); Printf(“The dist is %f\n”, Dist(p,q)); Return 0; }
יצירת טיפוסים חדשים • כיצד עברו הנקודות לפונקציה?
יצירת טיפוסים חדשים • כיצד עברו הנקודות לפונקציה? • על ידי העתקת הערכים שלהן לפרמטרים של הפונקציה.(כמו במשתנים רגילים call by value)
מצביעים וטיפוסים חדשים struct point P={5,6}; struct point* ptr; ptr = & P ; P ptr
מצביעים וטיפוסים חדשים • כדי להגיע לאיברים של P דרך המצביע נשתמש בחץ <- • ptr->x = 3; שקול P.x = 3 • ptr->y = 7; שקול P.y = 7 • דרך אלטרנטיבית היא ע"י שימוש ב * בצורה הבאה: • (*ptr).x = 3; שקול P.x = 3 • (*ptr).y = 7; שקול P.y = 7
מצביעים וטיפוסים חדשים • אם המבנה שלנו מורכב מהרבה משתנים אז העתקת כל המבנה לתוך הפרמטרים של הפונקציה זו פעולה יקרה! • מה ניתן לעשות כדי להימנע מכך ? • עבודה עם מצביעים (תמיד ישוכפל רק המצביע )
מצביעים וטיפוסים חדשים double dist(struct point* p, struct point* q) { double d,d1,d2; d1 = p->x - q->x; d2 = p->y - q->y; d = d1*d1 + d2*d2; return sqrt(d); } איך תראה הקריאה ב-main?
טיפוסים חדשים • ראינו שפעולת ההשוואה אינה מוגדרת עבור מבנים לכן אם נרצה להשוות נצטרך לממש פונקציה המשווה שני משתנים בעלי אותו טיפוס int Equal( struct point *p, struct point *q) { return (p->x == q->x && p->y == q->y); }
טיפוסים חדשים – כתיב מקוצר • שמו של הטיפוס החדש שהגדרנו הוא struct point • נרצה לשנות את השם ל-point • נבצע זאת באמצעות פקודת ה-typedef
טיפוסים חדשים – כתיב מקוצר struct point { double x; double y; }; typedef struct point point_t; שם חדש טיפוס קיים
טיפוסים חדשים – כתיב מקוצר • כעת בכל מקום נוכל להשתמש בpoint במקום ב struct point. • לדוגמא: int Equal(point_t *p, point_t *q) { return (p->x == q->x && p->y == q->y); }
מבנה בתוך מבנה • אם נרצה להגדיר מבנה שמתאר מלבן במישור אשר מקביל לצירים. p q
מבנה בתוך מבנה ניתן להגדיר struct rect { double xl, xh; double yl, yh; }; struct rect { struct point p; struct point q; }; typedef struct rect rect_t; אך עדיף להגדיר
מבנה בתוך מבנה- אתחול • אתחול מבנה כזה אפשרי בכמה דרכים: Rect_t r = { {5,6} , {10,2} }; r.p.x = 5; r.p.y = 6; r.q.x = 10; r.q.y = 2; q p
מערך של מבנים • ניתן להגדיר מערך של נקודות. int main() { point_t point_arr[20]; … }
נרצה לכתוב פונקציה שמקבלת מערך של מלבנים ומחזירה מצביע למלבן עם האלכסון הגדול ביותר. • שם הפונקציה:MaxRect • פרמטרים: מצביע למלבן • גודל המערך • ערך שחוזר: מצביע למלבן
תכנון הפונקציה • הפונקציה תעבור על המערך ותחשב לכל מלבן את אורכו ותשווה מול המקסימום שנמצא עד עתה. • אם האלכסון הנוכחי גדול יותר מוחלף המקסימום וגם נשמר האינדקס. • בסוף מוחזר מצביע באמצעות האינדקס ששמרנו
rect_t* MaxRect(rect_t arr[ ], int size) { double max=0; int max_index=0; for (i = 0 ; i < size ; i++) { if (dist(arr[i].p, arr[i].q) > max) { max = dist(arr[i]. p, arr[i].q); max_index = i; } } return arr + max_index; }
אתחול מערכים rect arr[20] = { {{ 3,4} , {5,6}} , {{ 4,7} , {9,10}} , … }
אתחול מערכים rect arr[20] = { {{ 3,4} , {5,6}} , {{ 4,7} , {9,10}} , … }
מבנים • נרצה לכתוב מבנה המיצג סטודנט: Struct student{ int id; char name[10]; int grade; }; typedef struct student student_t;
מבנים Int main() { Student_t class[CLASS_SIZE]; …. } • נרצה לכתוב פונקציה אשר מדפיסה את שמות הנכשלים בכיתה
מבנים Int Fail(student_t class[]); { Int i, cnt = 0; for(i = 0; i < CLASS_SIZE;i++) { If (class[i].garde < 60) { printf(“%s”, class[i].name); cnt++; } } return cnt; } איך תראה פונקצית השוואה למבנה זה?