typedef, struct, ¥ ® © ¹prog121/wiki.files/Tirgul9.pdfª ¹ ® ® ® ¤ © « ¸ ² ¬ ¡ '...

Preview:

Citation preview

Cתכנות בשפת 9תרגול

typedef, struct, רשימות מקושרות

ניתן להגדיר טיפוס חדש על ידי פקודתtypedef שתבניתה היא:

typedef existing_type new_type ;

המהדר יחליף את הטיפוסexisting_type בטיפוס החדשnew_type .

:לדוגמה

typedef int* pint;

pint p,q;

int* r;

r = p;

השימוש ב-typedef מאפשר להפוך את הקוד לקריא יותר מבחינת

.ההקשר

typedef -אופרטור ה

בתוך רשומה אחת( או זהים)טיפוס המאגד עצמים מטיפוסים שונים .

:תחביר 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;

struct תחביר

facebook_recordאפשר להחליף כל מופע של ולהיפך, struct some_name -בקוד ב

דרך אחרת: 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]: ניתן להגדיר מערך של רשומות

(המשך) 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;

;numberoffriends=501.(d*)-שקול ל

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 שהוא גם מטיפוס מבנה

.וממנו ניגש לשדות שלו שוב על ידי אופרטור הנקודה

(.'כלומר שדה של שדה של מבנה וכו)ניתן לבנות מבנים בעלי קינון מדרגה גבוהה יותר : הערה

(המשך) struct תחביר

להלן הגדרה עבור מבנה המממש מערך דינאמי :בלתי מוגבל של ערכים' שניתן להוסיף לו מס

typedef struct dyn

{

int *data;

int len;

int used;

} DynArr;

נתונה פונקציהvoid dynamicInsert(DynArr* arr, int val)

. שמכניסה מספר שלם למקום הפנוי הבא במערך

את גודל המערך 2פי " מכפילה"הפונקציה , אם המערך מלא

.תוך שמירה על הערכים הישנים, ומוסיפה את הערך החדש

1תרגיל

dataי השדה "המערך מוצבע ע

הוא אורך המערך lenהשדה

used הוא אינדקס התא האחרון שבשימוש

void dynamicInsert(DynArr* arr, int val)

{

int *newarr;

int i;

if (?? 1 ??)

{

newarr = ?? 2 ??;

for (i=0; i <= arr->used ; i++)

?? 3 ??;

free(?? 4 ??);

arr->data = ?? 5 ??;

arr->len = ?? 6 ??;

{

arr->data[?? 7 ??] = val;

}

(המשך) 1תרגיל

typedef struct dyn

{ int *data; int len; int used; } DynArr;

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;

}

(פתרון) 1תרגיל

typedef struct dyn

{ int *data; int len; int used; } DynArr;

void main()

{

DynArr a; int i=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");

(שימוש בפתרון) 1תרגיל

typedef struct dyn

{ int *data; int len; int used; } DynArr;

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);

}

(המשך -שימוש בפתרון ) 1תרגיל

typedef struct dyn

{ int *data; int len; int used; } DynArr;

struct record

{

char name[20];

int serial_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);

}

(א) 2תרגיל

?מה תדפיס התוכנית הבאה

name: abc, serial: 123

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);

}

(ב) 2תרגיל

?מה תדפיס התוכנית הבאה

מה שיוזן כקלט על ידי המשתמש

הגדרה ותכונות –רשימה מקושרת כל רשומה מכילה מצביע לרשומה הבאה או . שרשרת של רשומות –רשימה מקושרתNULL

(.עבור הרשומה האחרונה)ידי סריקה של הרשימה עד שמגיעים -אלא על, אין גישה מיידית לכל איבר, בניגוד למערך

.הוספה ומחיקה יעילה של איברים –היתרון לעומת מערך ; לאיבר המבוקשלדוגמה:

struct dbase_rec { char *record; /* --> data field */ struct dbase_rec *next; /* --> next field */ };

typedef struct dbase_rec dbase;

מחיקה וסריקה של רשימה בהתאם לצרכי המתכנת, בדרך כלל מגדירים פונקציות להוספה.

1שאלה

להלן הגדרה: typedef struct node { int val; struct node *next; } node;

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

.(val השדה לפי) ממש עולה בסדראחרי הקריאה ל, לדוגמה- void upper_list(node* first) הרשימה

:העליונה תהפוך לתחתונה

(המשך) 1שאלה

השלימו את קטע הקוד הבא:

void upper_list(node* first) { node *temp; if( ?? 1 ?? ) return; while(?? 2 ??){ if( ?? 3 ??>= ?? 4 ??){ temp = ?? 5 ??; ?? 6 ?? ; free(temp) ; } else ?? 7 ?? ; } }

(פתרון) 1שאלה void upper_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; } }

2שאלה השלם את החלק החסר בקוד הבא כך , 1' להגדרת הצומת משאלה מס בהתיחס

שלו ואז val -פעמים השווה לערכו של משתנה ה' שהפונקציה תשכפל כל צומת מס .תוסיף את הצמתים החדשים לרשימה ישר אחרי הצומת ממנו הם שוכפלו

void multiply(node* head) { node *temp; int i; while(head) { temp = head -> next; for(i=0; i< ?? 1 ??; i++) { head->next = ?? 2 ?? ; ?? 3 ?? = head -> val; head = ?? 4 ?? ; } ?? 5 ?? = ?? 6 ?? ; head = ?? 7 ??; } }

ל "אחרי הביצוע של הפונקציה הנ, לדוגמה:הרשימה העליונה תהפוך לתחתונה

(פתרון) 2שאלה void multiply(node* head) { node *temp; int i; 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; } }

3שאלה

void trim(node* lst) { node *aux; while( ?? 1 ?? && ?? 2 ??){

if(lst->val == ?? 3 ??){ aux = ?? 4 ?? ; lst->next = ?? 5 ?? ; free( ?? 6 ?? ); }

else lst = ?? 7 ?? ;

} }

החסר החלק את השלם ,1 'מס משאלה הצומת להגדרת בהתייחס

של הכפולים המופעים כל את תמחק שהפונקציה כך הבא בקוד

.(מהם אחד רק ותשאיר) ממוינת מקושרת ברשימה ערכים

(פתרון) 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 ; } }

Recommended