1 / 22

תכנות בשפת C תרגול 9 typedef, struct, רשימות מקושרות

תכנות בשפת C תרגול 9 typedef, struct, רשימות מקושרות. typedef אופרטור ה-. ניתן להגדיר טיפוס חדש על ידי פקודת typedef שתבניתה היא: typedef existing_type new_type ; המהדר יחליף את הטיפוס existing_type בטיפוס החדש new_type . לדוגמה: typedef int* pint; pint p,q; int* r; r = p;

graham
Download Presentation

תכנות בשפת C תרגול 9 typedef, struct, רשימות מקושרות

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. תכנות בשפת C תרגול 9 typedef, struct, רשימות מקושרות

  2. typedefאופרטור ה- • ניתן להגדיר טיפוס חדש על ידי פקודת typedef שתבניתה היא: typedef existing_type new_type ; • המהדר יחליף את הטיפוסexisting_type בטיפוס החדש new_type. לדוגמה: typedef int* pint; pint p,q; int* r; r = p; • השימוש ב-typedef מאפשר להפוך את הקוד לקריא יותר מבחינת ההקשר.

  3. struct- מבנה • טיפוס המאגד עצמים מטיפוסים שונים (או זהים) בתוך רשומה אחת. תחביר: • struct name_of_struct {    field1; field2; etc.}; • דומה למערך בכך ששניהם יכולים לאגד מספר נתונים , אך במבנה יש חופש בבחירת טיפוסי הנתונים: • struct address{    char city[20];    char street[20];    int num_house;    long code_area;}; אין מניעה שאחד השדות יהיה בעצמו מבנה

  4. תחבירstruct • ע"מ להכריז על משתנה מסוג מבנהaddress יש לכתוב: struct address x; • איתחול: struct address add = {"migdal Haemek", "Harazim", 5, 23028}; • ניתן להשתמש ב- typedef כדי להקל על שימוש ב- struct : typedef struct some_name {char alias[20];char username [20];char password[10];int numberOfFriends; } facebook_record; אפשר להחליף כל מופע של facebook_recordבקוד ב- struct some_name , ולהיפך

  5. תחבירstruct(המשך) • דרך אחרת: struct some_name {char alias[20];char username [20];char password[10]; int numberOfFriends; }; typedef struct some_name facebook_record; • struct ניתן לשימוש כפרמטר לפו' או כערך החזרה של פו', ממש כמו כל טיפוס אחר. • ניתן להגדיר מצביע למבנה: facebook_record* p;ניתן להגדיר מערך של רשומות: facebook_record records[10];

  6. גישה לשדות ב- struct • כדי לגשת לשדות, קיימים שני אופרטורים: נקודה (.) וחץ (->) . • אופרטור הנקודה מאפשר גישה לשדות בתוך משתנה מטיפוס המבנה. facebook_record d; strcpy(d.username, “david hasholet”); d.numberOfFriends = 501; • אופרטור החץ מאפשר גישה לשדות בתוך משתנה מטיפוס מצביע למבנה. facebook_record* d = (facebook_record*)malloc( sizeof(facebook_record) ); strcpy(d->username, “david hasholet”); d->numberOfFriends = 501; • שימו לב ש: d->numberOfFriends = 501; שקול ל-(*d).numberoffriends=501;

  7. תחבירstruct(המשך) • מבנה מקונן:שדות המבנה יכולים להיות בעצמם מבנה לדוגמא: struct address {    char city[15];   char street[15]; }; struct citizen{   struct address add;   long id; }; • נניח כי אנו מצהירים על משתנה מסוג citizen: struct citizen ctzn; • כדי לגשת לשדה id נרשום: ctzn.id • כדי לגשת לשדה city נרשום ctzn.add.city – כלומר, ראשית ניגש לשדה add שהוא גם מטיפוס מבנה וממנו ניגש לשדות שלו שוב על ידי אופרטור הנקודה. • הערה: ניתן לבנות מבנים בעלי קינון מדרגה גבוהה יותר (כלומר שדה של שדה של מבנה וכו').

  8. תרגיל 1 • להלן הגדרה עבור מבנה המממש מערך דינאמי שניתן להוסיף לו מס' בלתי מוגבל של ערכים: typedef struct dyn { int *data; int len; int used; } DynArr; • נתונה פונקציה void dynamicInsert(DynArr* arr, int val)שמכניסה מספר שלם למקום הפנוי הבא במערך. • אם המערך מלא, הפונקציה "מכפילה" פי 2 את גודל המערךומוסיפה את הערך החדש, תוך שמירה על הערכים הישנים. המערך מוצבע ע"י השדה dataהשדה len הוא אורך המערךused הוא אינדקס התא האחרון שבשימוש

  9. תרגיל 1 (המשך) voiddynamicInsert(DynArr* arr, intval) { int *newarr; inti; if (?? 1 ??) { newarr = ?? 2 ??; for (i=0; i <= arr->used ; i++) ?? 3 ??; free(?? 4 ??); arr->data = ?? 5 ??; arr->len = ?? 6 ??; { arr->data[?? 7 ??] = val; } typedefstruct dyn { int *data;int len; int used; } DynArr;

  10. תרגיל 1 (פתרון) void dynamicInsert(DynArr* arr, int val) { int *newarr; int i; if (arr->len-1 <= arr->used) { newarr = (int *)malloc(2*(arr->len)*sizeof(int)); for (i=0; i <= arr->used ; i++) newarr[i]=arr->data[i]; free(arr->data); arr->data = newarr; arr->len = 2*(arr->len); } arr->data[++(arr->used)] = val; } typedefstruct dyn { int *data;int len; int used; } DynArr;

  11. תרגיל 1 (שימוש בפתרון) void main() { DynArr a; inti=0; a.len=4; a.used=3; if(!(a.data=(int *)malloc(4*sizeof(int)))){ printf("Problem allocating memory, please try again!!!\n"); return; } for(;i<=a.used;++i)//Fill the array with the sqare of the indices: *(a.data+i)=i*i;  printf("Array BEFORE dynamic insertion:\n"); for(i=0;i<=a.used;++i)//Print the array before dynamic insertion: printf("%d\t",a.data[i]); printf("\n"); typedefstruct dyn { int *data;int len; int used; } DynArr;

  12. תרגיל 1 (שימוש בפתרון - המשך) dynamicInsert(&a, 16); printf("Array AFTER dynamic insertion:\n"); for(i=0;i<=a.used;++i) //Print the array after dynamic insertion: printf("%d\t",a.data[i]); printf("\n"); free(a.data); } typedefstruct dyn { int *data;int len; int used; } DynArr;

  13. תרגיל 2 (א) struct record { char name[20]; intserial_num; }; void readRecord(struct record r) { scanf("%s", r.name); scanf("%d", &r.serial_num); } void main() { struct record r; r.serial_num = 123; strcpy(r.name, "abc"); readRecord(r); printf("name: %s, serial: %d\n",r.name, r.serial_num); } מה תדפיס התוכנית הבאה ? name: abc, serial: 123

  14. תרגיל 2 (ב) struct record { char name[20]; int serial_num; }; void readRecord(struct record *r) { scanf("%s", r->name); scanf("%d", &(r->serial_num)); } void main() { record r; readRecord(&r); printf("name: %s, serial: %d\n",r.name, r.serial_num); } מה תדפיס התוכנית הבאה ? מה שיוזן כקלט על ידי המשתמש

  15. רשימה מקושרת – הגדרה ותכונות • רשימה מקושרת – שרשרת של רשומות. כל רשומה מכילה מצביע לרשומה הבאה או NULL (עבור הרשומה האחרונה). • בניגוד למערך, אין גישה מיידית לכל איבר, אלא על-ידי סריקה של הרשימה עד שמגיעים לאיבר המבוקש; היתרון לעומת מערך – הוספה ומחיקה יעילה של איברים. • לדוגמה: structdbase_rec { char *record; /* --> data field */ structdbase_rec *next; /* --> next field */ }; typedefstructdbase_rec dbase; • בדרך כלל מגדירים פונקציות להוספה, מחיקה וסריקה של רשימה בהתאם לצרכי המתכנת.

  16. שאלה 1 • להלן הגדרה: typedefstruct node { int val; struct node *next; } node; • עבור רשימה משורשרת השלם את החלק החסר בקוד הבא כך שהפונקציה תשאיר מהרשימה רק את החוליות שבונות רשימה בסדר עולה ממש (לפי השדה val). • לדוגמה, אחרי הקריאה ל- void upper_list(node* first) הרשימה העליונה תהפוך לתחתונה:

  17. שאלה 1 (המשך) • השלימו את קטע הקוד הבא: void upper_list(node* first){ node *temp; if( ?? 1 ?? ) return; while(?? 2 ??){ if( ?? 3 ??>= ?? 4 ??){ temp = ?? 5 ??; ?? 6 ?? ; free(temp) ; } else ?? 7 ?? ; } }

  18. שאלה 1 (פתרון) voidupper_list(node* first) { node *temp; if( !first ) return; while(first->next){ if( first->val>=first->next->val){ temp = first->next; first->next=first->next->next ; free(temp) ; } else first=first->next; } }

  19. שאלה 2 • בהתיחס להגדרת הצומת משאלה מס' 1, השלם את החלק החסר בקוד הבא כך שהפונקציה תשכפל כל צומת מס' פעמים השווה לערכו של משתנה ה- val שלו ואז תוסיף את הצמתים החדשים לרשימה ישר אחרי הצומת ממנו הם שוכפלו. void multiply(node* head){ node *temp; inti; while(head) { temp = head -> next; for(i=0; i< ?? 1 ??; i++) { head->next = ?? 2 ?? ; ?? 3 ?? = head -> val; head = ?? 4 ?? ; } ?? 5 ?? = ?? 6 ?? ; head = ?? 7 ??; } } לדוגמה, אחרי הביצוע של הפונקציה הנ"ל הרשימה העליונה תהפוך לתחתונה:

  20. שאלה 2 (פתרון) void multiply(node* head) { node *temp; inti; while(head) { temp = head -> next; for(i=0;i<head->val-1; i++) { head->next = (node*)malloc(sizeof(node)); head->next->val = head -> val; head = head->next ; } head->next = temp ; head = temp; } }

  21. שאלה 3 בהתייחס להגדרת הצומת משאלה מס' 1, השלם את החלק החסר בקוד הבא כך שהפונקציה תמחק את כל המופעים הכפולים של ערכים ברשימה מקושרת ממוינת (ותשאיר רק אחד מהם). void trim(node* lst){ node *aux; while( ?? 1 ?? && ?? 2 ??){ if(lst->val == ?? 3 ??){ aux = ?? 4 ?? ; lst->next = ?? 5 ?? ; free( ?? 6 ?? ); } else lst = ?? 7 ?? ; } }

  22. שאלה 3 (פתרון) void trim(node* lst) { node *aux; while(lst!=NULL && lst->next!=NULL){ if(lst->val == lst->next->val){ aux = lst->next ; lst->next = lst->next->next ; free(aux); } else lst = lst->next ; } }

More Related