תכנות תרגול 11 שבוע : 7.6.06. מבנים מטרת המבנים היא לאפשר...

Preview:

Citation preview

1111 תכנות תרגולתכנות תרגול

::שבועשבוע

7.6.067.6.06

מבניםמבנים

מטרת המבנים היא לאפשר למתכנת להגדיר מטרת המבנים היא לאפשר למתכנת להגדיר •טיפוסי משתנים חדשים אשר מתאימים טיפוסי משתנים חדשים אשר מתאימים

ספציפית לבעיה שאותה התוכנית פותרת. ספציפית לבעיה שאותה התוכנית פותרת.

היא לאפשר למתכנת היא לאפשר למתכנת typedeftypedefמטרת המילה מטרת המילה •לתת שמות חדשים לטיפוסי משתנים קיימים. לתת שמות חדשים לטיפוסי משתנים קיימים.

Syntax Syntax מבניםמבניםstruct complex {struct complex {

double real;double real;

double image;double image;

};};int main()int main()

{{

struct complex c;struct complex c;

struct complex* pc;struct complex* pc;

c.real = 5;c.real = 5;

c.image = 7;c.image = 7;

pc = &c;pc = &c;

pc->real = 3;pc->real = 3;

pc->image = 4;pc->image = 4;

}}

real

image

5

7

c 6024

pc6024

3

4

Syntax Syntax מבניםמבניםstruct complex {struct complex {

double real;double real;

double image;double image;

};};

נשתמש בנקודה נשתמש בנקודה cc של של membersmembers לגישה ל לגישה ל

נשתמש ב >- נשתמש ב >-pcpc של של membersmembersלגישה ל לגישה ל

תרגילתרגיל

כתוב פונקציה המקבלת שני מספרים מרוכבים כתוב פונקציה המקבלת שני מספרים מרוכבים •ומחברת ביניהם ומחזירה את הסכוםומחברת ביניהם ומחזירה את הסכום

כתוב פונקציה המחשבת את הערך המוחלט של כתוב פונקציה המחשבת את הערך המוחלט של •מספר מרוכב ומחזירה את הערך הזהמספר מרוכב ומחזירה את הערך הזה

double AbsComplex(struct complex a)double AbsComplex(struct complex a)

{{

return a.im * a.im + a.real * a.real;return a.im * a.im + a.real * a.real;

}}

struct complex Add(struct complex a, struct struct complex Add(struct complex a, struct complex b)complex b)

{{

struct complex s;struct complex s;

s.im = a.im + b.im;s.im = a.im + b.im;

s.real = a.real + b .real;s.real = a.real + b .real;

return s;return s;

}} שימוש בפונקציותשימוש בפונקציות

x = Add(x,y);x = Add(x,y);

ab = AbsComplex(x);ab = AbsComplex(x);

!העברה לפי ערך

typedeftypedef מבנים ושימוש ב-מבנים ושימוש ב-struct complex {struct complex {

double real;double real;

double image;double image;

};};

int main()int main()

{{

struct complex struct complex c={5,7};c={5,7};

struct complex* pc;struct complex* pc;

}}

struct complex {struct complex {

double real;double real;

double image;double image;

};};

typedef struct complex complextypedef struct complex complex_t;_t;

int main()int main()

{{

complex_t c={5,7};complex_t c={5,7};

complex_t* pc;complex_t* pc;

}}

typedef struct complex complextypedef struct complex complex_t;_t;

טיפוס קיים שם חדש לטיפוס קיים

double AbsComplex(double AbsComplex(complex_tcomplex_t a) a)

{{

return a.im * a.im + a.real * a.real;return a.im * a.im + a.real * a.real;

}}

complex_t Add(complex_t Add(complex_tcomplex_t a, a, complex_tcomplex_t b) b)

{{

complex_tcomplex_t s; s;

s.im = a.im + b.im;s.im = a.im + b.im;

s.real = a.real + b .real;s.real = a.real + b .real;

return s;return s;

}}

double AbsComplex(double AbsComplex(complex_t* complex_t* pa)pa)

{{

return pa->im * pa->im + pa->real * pa->real;return pa->im * pa->im + pa->real * pa->real;

}}

complex_t Add(complex_t Add(complex_t*complex_t* pa, pa, complex_t*complex_t* pb) pb)

{{

complex_tcomplex_t s; s;

s.im = pa->im + pb->im;s.im = pa->im + pb->im;

s.real = pa->real + pb->real;s.real = pa->real + pb->real;

return s;return s;

}}

מערכים ומבניםמערכים ומבנים

מאחר ומבנים מגדירים סוג חדש של משתנים מאחר ומבנים מגדירים סוג חדש של משתנים •הרי הרי

שכמו לסוגים רגילים נרצה ליצור מערכים עבור שכמו לסוגים רגילים נרצה ליצור מערכים עבור סוגים סוגים

realאלואלו 5

7image

2

1

7

2

1

8

complex_t arr[SIZE]={{5,7},{2,1},{7,2},{1,8}}

arr

תרגילתרגיל

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

ומחזירה את האינדקס של האיבר בעל הערך ומחזירה את האינדקס של האיבר בעל הערך המוחלט המוחלט

המקסימאליהמקסימאלי

פתרוןפתרוןint MaxAbs(complex_t *arr,int n)int MaxAbs(complex_t *arr,int n){{

int i,maxIn;int i,maxIn;double maxAbs=double maxAbs=-1-1;;for (i=0;i<n;i++)for (i=0;i<n;i++)

if (maxAbs < AbsComplex(arr[i]))if (maxAbs < AbsComplex(arr[i])){{

maxAbs = AbsComplex(arr[i]);maxAbs = AbsComplex(arr[i]);maxIn = i;maxIn = i;

}}return maxIn;return maxIn;

}}

שימוש של מבנה בתוך מבנהשימוש של מבנה בתוך מבנה של של membermemberמבנה שהגדרנו יכול לשמש אותנו גם כ-מבנה שהגדרנו יכול לשמש אותנו גם כ-

מבנה מבנה אחר. למשל מבנה של נקודה יכול לשמש אותנו בבואנו אחר. למשל מבנה של נקודה יכול לשמש אותנו בבואנו

}struct pointלהגדיר מבנה של משולש.להגדיר מבנה של משולש.double x;double y;

};typedef struct point point_t;

struct triangle {point_t x;point_t y;point_t z;

};

הקצאת זיכרון דינאמיתהקצאת זיכרון דינאמית

הזיכרון המקסימאלי ששימש את התוכנית שלנו עד היום היה הזיכרון המקסימאלי ששימש את התוכנית שלנו עד היום היה קבוע מראש.קבוע מראש.

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

לשינוי לשינוי במהלך ריצת התוכנית!במהלך ריצת התוכנית!

בעיות אפשריות:בעיות אפשריות: לשמור את ציוני כל הסטודנטים לשמור את ציוני כל הסטודנטים 100100אם הגדרנו מערך בגודל אם הגדרנו מערך בגודל

וכעת מגיע סטודנט נוסף מה נעשה? וכעת מגיע סטודנט נוסף מה נעשה?

התוכנית כבר כתובה ולא ניתן לשנות את גודל המערך!התוכנית כבר כתובה ולא ניתן לשנות את גודל המערך!

הקצאת זיכרון דינאמיתהקצאת זיכרון דינאמיתCC מאפשרת לנו להקצות זיכרון תוך כדי ריצת התוכנית וכך מאפשרת לנו להקצות זיכרון תוך כדי ריצת התוכנית וכך

להגדיר מערכים ומבנים אחרים בצורה דינאמית להגדיר מערכים ומבנים אחרים בצורה דינאמית

int main(){ int a[10]; a[6] = 7;}

10 ints

int main(){ int *a; a = (int*) malloc(sizeof(int) * 10); a[6] = 7;}

a

10 ints

6024

6024

שחרור זיכרון שהוקצה דינאמיתשחרור זיכרון שהוקצה דינאמית

כל שטח זיכרון שהוקצה ע"י המתכנת צריך להיות כל שטח זיכרון שהוקצה ע"י המתכנת צריך להיות •משוחרר בסיום השימוש בו. לכן חייבים תמיד להחזיק משוחרר בסיום השימוש בו. לכן חייבים תמיד להחזיק

את כתובת האזור שהוקצה על מנת שנוכל לשחרר אותו את כתובת האזור שהוקצה על מנת שנוכל לשחרר אותו בסיום השימוש.בסיום השימוש.

int main(){ int *a; a = (int*) malloc(sizeof(int) * 10); a[6] = 7; free(a);}

a

6024

6024

stdlib.hstdlib.h הפונקציות נמצאות ב- הפונקציות נמצאות ב-

• void *malloc(size_t size);void *malloc(size_t size);– Allocate size bytes. Successful call return base Allocate size bytes. Successful call return base

address; otherwise NULL is returned.address; otherwise NULL is returned.• void *calloc(size_t n,size_t size_el)void *calloc(size_t n,size_t size_el)

– Allocate an array on n elements each in size of Allocate an array on n elements each in size of size_el. Each bit is initialized to zero. Successful size_el. Each bit is initialized to zero. Successful call return base address; otherwise NULL is call return base address; otherwise NULL is returned.returned.

• void free(void *ptr)void free(void *ptr)– Deallocate the memory pointed by ptr which Deallocate the memory pointed by ptr which

must be a base address of previously allocated must be a base address of previously allocated memorymemory

• void *realloc(void *,size_t size)void *realloc(void *,size_t size)– Reallocate a memory block of size size. Reallocate a memory block of size size.

רשימות מקושרותרשימות מקושרות

ישנו מבנה נתונים אשר מאפשרישנו מבנה נתונים אשר מאפשר•לנו לבצע את הוספת האיברים בצורהלנו לבצע את הוספת האיברים בצורה

נוחה יותר. מבנה זה נקרא רשימה מקושרת. נוחה יותר. מבנה זה נקרא רשימה מקושרת.

איבר

מידע

מצביע לאיבר

מצביע לראש

הרשימה

איבר

מידע

מצביע לאיבר

איבר

מידע

מצביע לאיבר

איבר

מידע

מצביע לאיבר

איבר

מידע

מצביע לאיבר

5 7 1 8

struct list {struct list { int data;int data; struct list *next;struct list *next;};};

typedef strcut list typedef strcut list Item;Item;

מידע

מצביע לאיבר

:פעולות על הרשימה

יצירה והריסה של רשימה•ספירת מספר האיברים ברשימה•חיבור שתי רשימות•מחיקה/הוספה של איבר לרשימה•הדפסת רשימה•

CCרשימות מקושרות ב-רשימות מקושרות ב-

נחזיק מצביע אשר יהיה מצביע לראש נחזיק מצביע אשר יהיה מצביע לראש ..--mainmainהרשימה וישב בהרשימה וישב ב

תהיה לנו פונקצית הוספה אשר תוסיף תהיה לנו פונקצית הוספה אשר תוסיףאיברים לרשימה בסוף הרשימה. איברים לרשימה בסוף הרשימה.

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

בסוף הרשימה.בסוף הרשימה.

איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

7

איבר

מידע

מצביע לאיבר

5

CCרשימות מקושרות ב-רשימות מקושרות ב-int main()int main()

{{

Item *L_head = NULL;Item *L_head = NULL;

L_head = Add(L_head,5);L_head = Add(L_head,5);

L_head = Add(L_head,3);L_head = Add(L_head,3);

L_head = Add(L_head,7);L_head = Add(L_head,7);

}}מצביע לראש

הרשימה

Item* Add(Item* L_head, int value)Item* Add(Item* L_head, int value){{ Item* L_tail = L_head;Item* L_tail = L_head; Item* I_new = malloc(sizeof (Item));Item* I_new = malloc(sizeof (Item)); I_new->value = value;I_new->value = value; I_new->next = NULL;I_new->next = NULL;

if (L_tail == NULL) if (L_tail == NULL) return I_new;return I_new;

while (L_tail->next != NULL)while (L_tail->next != NULL) L_tail=L_tail->next;L_tail=L_tail->next; L_tail->next = I_new;L_tail->next = I_new; return L_head;return L_head;} }

איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

7

איבר

מידע

מצביע לאיבר

5

CCרשימות מקושרות ב-רשימות מקושרות ב-int main()int main()

{{

Item *L_head = NULL;Item *L_head = NULL;

… …

L_head = Delete(L_head,3);L_head = Delete(L_head,3);

}}

מצביע לראש

הרשימה

Item *Delete(Item * head,int value)Item *Delete(Item * head,int value){{

Item* curr = head;Item* curr = head;Item* prev = head;Item* prev = head;if (curr->value == value)if (curr->value == value){{

curr = curr->next;curr = curr->next;free(head);free(head);return curr;return curr;

}}

האיבר למחיקההוא הראשון

while (curr != NULL)while (curr != NULL){{

if (curr->value == value)if (curr->value == value){{

prev->next = curr->next;prev->next = curr->next;free(curr);free(curr);return head;return head;

}}prev = curr;prev = curr;curr = curr->next;curr = curr->next;

}}return head;return head;

}}

חיפוש ומחיקתאיבר

void PrintList(Item *head){

if (head == NULL){

printf("\n");return;

}else{

printf("%d ",head-<data);PrintList(head-<next);return;

}}

הדפסת רשימה

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

int Count(Item * L){

int counter=0;while (L != NULL){

counter++;L=L->next;

}return counter;

}int CountR(Item * L){

if (L == NULL)return 0;

return 1 + CountR(L->next);}

כתוב פונקציה המקבלת מצביעים לשתי כתוב פונקציה המקבלת מצביעים לשתי •רשימות מקושרות ומחברת אותן. רשימות מקושרות ומחברת אותן.

איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

7

איבר

מידע

מצביע לאיבר

5

1רשימה איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

5

2רשימה

איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

7

איבר

מידע

מצביע לאיבר

5

איבר

מידע

מצביע לאיבר

3

איבר

מידע

מצביע לאיבר

5

Item* Meld(Item* L1,Item* L2){

Item* L1_head = L1;if (L1 == NULL)

return L2;if (L2 == NULL)

return L1;while (L1->next != NULL) L1=L1->next;L1->next = L2;return L1_head;

}

Recommended