220 likes | 438 Views
תכנות בשפת C תרגול 9 typedef, struct, מערכים דינמיים דו-ממדיים ומצביעים. typedef אופרטור ה-. ניתן להגדיר טיפוס חדש על ידי פקודת typedef שתבניתה היא: typedef existing_type new_type ; המהדר יחליף את הטיפוס existing_type בטיפוס החדש new_type . לדוגמה: typedef int* pint;
E N D
תכנות בשפת 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; • השימוש ב-typedef מאפשר להפוך את הקוד לקריא יותר מבחינת ההקשר.
struct- מבנה • טיפוס המאגד עצמים מטיפוסים שונים (או זהים) בתוך רשומה אחת. תחביר: • struct name_of_struct { field1; field2; etc.}; • דומה למערך בכך ששניהם יכולים לאגד מספר נתונים , אך במבנה יש חופש בבחירת טיפוסי הנתונים: • struct address{ char city[20]; char street[20]; int num_house; long code_area;}; אין מניעה שאחד השדות יהיה בעצמו מבנה
תחביר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 , ולהיפך
תחבירstruct(המשך) • דרך אחרת: struct some_name {char alias[20];char username [20];char password[10]; int numberOfFriends; }; typedef some_name facebook_record; • struct ניתן לשימוש כפרמטר לפו' או כערך החזרה של פו', ממש כמו כל טיפוס אחר. • ניתן להגדיר מצביע למבנה: facebook_record* p;ניתן להגדיר מערך של רשומות: facebook_record records[10];
גישה לשדות ב- 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;
תרגיל 1 • להלן הגדרה עבור מבנה המממש מערך דינאמי שניתן להוסיף לו מס' בלתי מוגבל של ערכים: typedef struct dyn { int *data; int len; int used; } DynArr; • נתונה פונקציה void dynamicInsert(DynArr* arr, int val)שמכניסה מספר שלם למקום הפנוי הבא במערך. • אם המערך מלא, הפונקציה "מכפילה" פי 2 את גודל המערךומוסיפה את הערך החדש, תוך שמירה על הערכים הישנים. המערך מוצבע ע"י השדה dataהשדה len הוא אורך המערךused הוא אינדקס התא האחרון שבשימוש
תרגיל 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;
תרגיל 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;
תרגיל 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;
תרגיל 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;
תרגיל 2 סמן את כל התשובות הנכונות: • פונקציה יכולה להחזיר יותר מערך אחד. • ניתן להגדיר בפונקציה שני משתנים בעלי אותו שם אבל מטיפוסים שונים. • ניתן לכתוב פונקציה עם פרמטר אחד שמקבלת כארגומנט אקטואלי (פרמטר) משתנה מסוג int ומשנה את תוכנו. • קיים טיפוס מהסוג: int *** . • ניתן להגדיר שדה מטיפוס struct myStruct בתוך טיפוסstruct myStruct . • ניתן להגדיר שדה מטיפוס * struct myStruct בתוך טיפוסstruct myStruct .
תרגיל 2 (פתרון) סמן את כל התשובות הנכונות: • פונקציה יכולה להחזיר יותר מערך אחד. • ניתן להגדיר בפונקציה שני משתנים בעלי אותו שם אבל מטיפוסים שונים. • ניתן לכתוב פונקציה עם פרמטר אחד שמקבלת כארגומנט אקטואלי (פרמטר) משתנה מסוג int ומשנה את תוכנו. • קיים טיפוס מהסוג: int ***. • ניתן להגדיר שדה מטיפוס struct myStruct בתוך טיפוסstruct myStruct . • ניתן להגדיר שדה מטיפוס * struct myStruct בתוך טיפוסstruct myStruct .
תרגיל 3 (א) struct record { char name[20]; int serial_num; }; void readRecord(struct record r) { scanf("%s", r.name); scanf("%s", r.serial_num); } void main() { record r; readRecord(r); printf("name: %s, serial: %d",r.name, r.serial_num); } מה תדפיס התוכנית הבאה ?
תרגיל 3 (ב) struct record { char name[20]; int serial_num; }; void readRecord(struct record *r) { scanf("%s", r->name); scanf("%s", r->serial_num); } void main() { record r; readRecord(&r); printf("name: %s, serial: %d",r.name, r.serial_num); } מה תדפיס התוכנית הבאה ?
תרגיל 4 (א) מכפלה סקלרית בין שני וקטורים ו- מסומנת ע"י ומוגדרת באופן הבא: • כתבו פונקציה רקורסיביתint recScalarProd(int *a, int *b, int len)המחזירה את ערך המכפלה הסקלארית בין ווקטורים a ו-b, שאורכם len. int recScalarProd(int *a, int *b, int len) { if(len==1) return (*a)*(*b); return (*a)*(*b)+ recScalarProd(a+1,b+1, len-1); }
תרגיל 4 (ב) • לפנינו כפל של מטריצה מסדר 2x4במטריצה מסדר 4x3.בתמונה מודגש כיצד מחושב האיבר (AB)12
תרגיל 4 (ב) - המשך • כתבו פונקציה בעלת חתימה: int ** multMat(int **A, int **B, int n, int m, int p)המחזירה את כפל המטריצות A ו-B, או NULL(במידה ואירעה שגיאה) ומשתמשת ב- recScalarProd
תרגיל 4 (ב) – פתרון (i) int ** multMat(int **A, int **B, int n, int m, int p) { int i,j,k;int *temp;int **res; // Allocate temp array. if(!(temp=(int *)malloc(m*sizeof(int)))) { printf("Error allocating memory!\n"); return NULL; } // Allocate main array. if(!(res=(int **)malloc(n*sizeof(int *)))) { printf("Error allocating memory!\n"); return NULL; }
תרגיל 4 (ב) – פתרון (ii) for(i=0;i<n;++i) { // Allocate i’th row array. if(!(res[i]=(int *)malloc(p*sizeof(int)))) { printf("Error allocating memory!\n"); return NULL; } for(j=0;j<p;++j) { for(k=0;k<m;++k) // Moving j’th column of B to array of integers. temp[k]=B[k][j]; res[i][j]= recScalarProd(A[i],temp,m); } } return res; }
תרגיל 5 • מה תדפיס התכנית הבאה: void what(char *str1, char *str2, char *str3){ if(*str1 >= '0' && *str1 <= '9') *str3 = ' '; else *str3 = *str1; if(!*str3) return; what(str2, str1+1, str3+1); } void main(){ char mystery1[]="4ob5rntt6e.7that!", mystery2[]="t8eo8o0ob..", mystery3[]="abcdefghijklmnopqrstuvwxyz0123456789"; what(mystery1, mystery2, mystery3); puts(mystery3); } פתרון: to be or not to be…
תרגיל 6 char *search(char *str1,char *str2){ inti, j, k, length; char *temp, *aux=NULL; for(i=length=0;*(str1+i);i++) for(j=0;*(str2+j);j++){ for(k=0;*(str1+i+k)&& *(str1+i+k)==*(str2+j+k);k++); if(k>length){ length=k; aux=str1+i; } } if(aux) if(temp=(char *)malloc(length+1)){ for(i=0;i<length;i++) *(temp+i)=*(aux+i); *(temp+i)='\0'; return temp; } return NULL; } מה עושה הפו' הבאה? פתרון:הפו' מחזירה את תת-המחרוזת הגדולה ביותר שמשותפת לשתי המחרוזות