Presentation is loading. Please wait.

Presentation is loading. Please wait.

תרגול 5 דוגמא של ADT: מחסנית מצביעים לפונקציות תכנות גנרי דוגמא של ADT גנרי : מחסנית גנרית.

Similar presentations


Presentation on theme: "תרגול 5 דוגמא של ADT: מחסנית מצביעים לפונקציות תכנות גנרי דוגמא של ADT גנרי : מחסנית גנרית."— Presentation transcript:

1 תרגול 5 דוגמא של ADT: מחסנית מצביעים לפונקציות תכנות גנרי דוגמא של ADT גנרי : מחסנית גנרית

2 הבעיה שנפתור לקלוט להדפיסבסדר הפוךנרצה לקלוט 100 מספרים אי שליליים מהקלט ולהדפיס אותם בסדר הפוך להתחרט ולבטל המספר האחרון –בזמן הכנסת הקלט המשתמש יכול להתחרט ולבטל את הכנסת המספר האחרון  לצורך כך הוא צריך להכניס -1 “undo” –פעולת הביטול דומה לפעולת “undo” בעורכי טקסטים כמה פעמים –המשתמש יכול לבצע “undo” כמה פעמים ולבטל כמה מספרים 2

3 שלושה פתרונות 1. פתרון ישיר 1. פתרון ישיר - נועד להמחשת הבעיה. ADT מחסנית 2. פתרון אשר משתמש ב -ADT של מחסנית ADT גנרי מחסנית 3. פתרון אשר משתמש ב -ADT גנרי של מחסנית 3

4 הפתרון הישיר #include #define MAX_INPUT_SIZE 100 #define UNDO_LAST_COMMAND -1 int main(){ int lastNumber, currentIndex = 0; int numbers[MAX_INPUT_SIZE]; while (currentIndex < MAX_INPUT_SIZE && scanf("%d",&lastNumber) == 1){ if (lastNumber == UNDO_LAST_COMMAND){ if (currentIndex < 1){ printf("No numbers were entered until now\n"); } else{ currentIndex--; printf("undo\n"); } } else { assert(currentIndex >= 0 && currentIndex < MAX_INPUT_SIZE); numbers[currentIndex++] = lastNumber; } while (currentIndex > 0){ assert(currentIndex >= 0 && currentIndex < MAX_INPUT_SIZE); printf("%d\n", numbers[--currentIndex]); } return 0; } 4

5 הבעיות בפתרון הישיר באגיםסכנה של באגים –קל לטעות –קל לטעות ב -1 ולהתבלבל :  currentIndex-- או --currentIndex  currentIndex++ או ++currentIndex  currentIndex > 0 או currentIndex >= 0  currentIndex < 1 או currentIndex < 0 לאמתעדהפתרון לא מתעד את העובדות הבאות –מוסיפים רק לסוף –מוסיפים מספר רק לסוף המערך –מורידיםרק מסוף –מורידים מספר רק מסוף המערך –מדפיסיםרק בסדר הפוך –מדפיסים את המספרים רק בסדר הפוך 5

6 מחסנית במדעי המחשב קיימות הרבה בעיות שבהן שמירת פריטים –יש צורך בשמירת פריטים כלשהם –מוציאים בסדר הפוך הוכנסו –מוציאים פריטים בסדר הפוך מהסדר שבו הם הוכנסו  ניגשים רק לפרט האחרון  ניגשים רק לפרט האחרון שהוכנס לדוגמא : –שמירת פעולות –שמירת פעולות לצורך undo –שמירת סדר קריאות לפונקציות מחסניתאת הבעיות האלה נהוג לפתור על ידי שימוש במחסנית 6

7 מחסנית מבנה נתונים שמירת איבריםמבנה נתונים המאפשר שמירת איברים, כאשר להוציא רק את איבר האחרון –בכל רגע נתון ניתן להוציא רק את איבר האחרון שהוכנס (Last In First Out) לגשת רק לאיבר האחרון –ניתן לגשת רק לאיבר האחרון הדגמת העבודה עם המחסנית : http://www.cosc.canterbury.ac.nz/people/mukundan/dsal/StackAppl.html המבנה תומך בפעולות הבאות : push הוסף – push - הוסף איבר למחסנית. pop הוצא – pop - הוצא את האיבר האחרון שהוכנס למחסנית ( מבלי להחזיר את ערכו ). top החזר את ערכו – top - החזר את ערכו של האיבר האחרון שהוכנס למחסנית ( מבלי להוציא אותו מהמחסנית ) 7

8 ADT מחסנית - הממשק ב -stack.h #ifndef _STACK_H #define _STACK_H /* ADT of Stack of integers */ typedef struct Stack_t* Stack ; /* possible return values */ typedef enum { StackBadArgument, StackSuccess, StackFail, StackEmpty, StackFull } StackResult ; 8

9 ADT מחסנית - הממשק ב -stack.h /* creates a Stack with maximal capacity of 'maxSize'. if fails, returns NULL */ Stack stackCreate(int maxSize); /* releases the memory allocated for the stack */ void stackDestroy(Stack stack); /* insert a number to the top of the stack. Error Codes: StackBadArgument if stack is NULL StackFull if the stack is full. */ StackResult stackPush(Stack stack, int number); 9

10 ADT מחסנית - הממשק ב -stack.h /* removes the element at the top of the stack. Error codes: StackBadArgument if stack is NULL StackEmpty if the stack is empty */ StackResult stackPop(Stack stack); /* returns in 'number' the last element that was pushed. Error codes: StackBadArgument if stack or number are NULL StackEmpty if the stack is empty */ StackResult stackTop(Stack stack, int* number); /* returns the number of elements in the stack. Error codes: StackBadArgument if stack or size are NULL */ StackResult stackSize(Stack stack, int* size); #endif 10

11 מימוש אפשרי של המחסנית : בעזרת מערך מבנה שלושה שדותנגדיר מבנה שבו שלושה שדות : מערךמערך בו יישמרו המספרים גודל המערךשדה אשר ישמור את גודל המערך ( שיהיה זהה למספר האיברים המכסימלי שיכולים להישמר ) האינדקס במערךשדה שישמור את האינדקס במערך אליו יוכנס האיבר הבא ( יהיה שווה למספר האיברים במבנה ) 11 2 nextIndex 7 17 3

12 ADT מחסנית - המימוש ב -stack.c #include #include "stack.h" /* a structure that represents a Stack */ struct Stack_t { /* The Stack is implemented as an array of integers. With nextIndex as an index to the next available position and maximal size stored in maxCapacity. */ int* array; int nextIndex; int maxCapacity; }; 12

13 ADT מחסנית - המימוש ב -stack.c Stack stackCreate(int maxSize) { if (maxSize <= 0){ return NULL; } Stack stack = (Stack) malloc(sizeof(struct Stack_t)) ; if (stack == NULL){ return NULL; } stack->array = (int*) malloc(sizeof(int) * maxSize); if (stack->array == NULL){ free(stack); return NULL; } stack->nextIndex = 0; stack->maxCapacity = maxSize; return stack; } 13 ב -C99 ניתן להגדיר משתנים לא רק בתחילת בלוק עדיף להגדיר משתנים כמה שיותר קרוב לשימוש הראשון שלהם

14 ADT מחסנית - המימוש ב -stack.c StackResult stackPush(Stack stack, int number) { if (stack == NULL){ return StackBadArgument; } if (stack->nextIndex >= stack->maxCapacity){ return StackFull; } assert(stack->nextIndex >= 0 && stack->nextIndex maxCapacity); stack->array[stack->nextIndex++] = number; return StackSuccess; } 14

15 ADT מחסנית - המימוש ב -stack.c StackResult stackPop(Stack stack) { if (stack == NULL){ return StackBadArgument; } if (stack->nextIndex < 1){ return StackEmpty; } stack->nextIndex--; return StackSuccess; } 15

16 ADT מחסנית - המימוש ב -stack.c StackResult stackTop(Stack stack, int* number) { if ((stack == NULL) || (number == NULL)){ return StackBadArgument; } if (stack->nextIndex < 1){ return StackEmpty; } assert(stack->nextIndex > 0 && stack->nextIndex maxCapacity); *number = stack->array[stack->nextIndex-1]; return StackSuccess; } 16

17 ADT מחסנית - המימוש ב -stack.c StackResult stackSize(Stack stack, int* size) { if (stack == NULL || size == NULL){ return StackBadArgument; } *size = stack->nextIndex; return StackSuccess; } void stackDestroy(Stack stack) { if (stack != NULL){ free(stack->array); free(stack); } 17

18 הפתרון של הבעיה הקודמת בעזרת מחסנית #include #include "stack.h" #define MAX_INPUT_SIZE 100 #define UNDO_LAST_COMMAND -1 int main(){ Stack stack = stackCreate(MAX_INPUT_SIZE); if (stack == NULL){ fprintf(stderr,"failed to create stack\n"); exit(1); } StackResult stackResult; int lastNumber, tmpNumber, size = 0; 18

19 הפתרון של הבעיה הקודמת בעזרת מחסנית /* read the input numbers */ while (size < MAX_INPUT_SIZE && scanf("%d",&lastNumber) == 1){ if (lastNumber == UNDO_LAST_COMMAND){ stackResult = stackPop(stack); if (stackResult == StackEmpty){ printf("No numbers were entered until now\n"); } else{ assert(stackResult == StackSuccess); printf("undo\n"); } } else { stackResult = stackPush(stack,lastNumber); assert(stackResult == StackSuccess); } stackResult = stackSize(stack, &size); assert(stackResult == StackSuccess); } 19

20 הפתרון של הבעיה הקודמת בעזרת מחסנית /* print the numbers in the reverse order */ do { stackResult = stackTop(stack,&tmpNumber); if (stackResult == StackSuccess){ printf("%d\n", tmpNumber); stackResult = stackPop(stack); } } while (stackResult == StackSuccess); stackDestroy(stack); return 0; { 20

21 יתרונות השימוש ב -ADT מחסנית בדוגמא שראינו הקטנת באגיםהקטנת סיכוי לבאגים –אין סכנה להתבלבל בין האינדקסים של המערך מתעד את עצמו self-documentingהקוד מתעד את עצמו (self-documenting) מדעי המחשב מחסנית –כל מי שלמד מדעי המחשב מבין מה זה מחסנית ויבין מה הקוד מבצע יותר בקלות 21

22 יתרונות נוספים לשימוש במבני נתונים אבסטרקטיים בתוכנה שיכפול קודמניעת שיכפול קוד בכמה מקומות לכתוב כמה פעמים –אם בתוכנה עובדים עם נתונים בצורה מסוימת בכמה מקומות - אין צורך לכתוב אותו קוד כמה פעמים  למשל אם בכמה מקומות בתוכנה יש צורך לעבד נתונים בסדר הפוך מסדר קליטתם, בכל המקומות האלה נשתמש במחסנית הבטחה אוטומטיתאופן העבודה הבטחה אוטומטית של אופן העבודה עם הנתונים באגים –פחות באגים  מחסנית מבטיחה שלא ניתן לגשת לאמצע שלה  Set מבטיח שלא יימצאו בו שני איברים זהים 22

23 מצביעים לפונקצית פונקציות גנריות

24 מצביעים לפונקציות מצביע לפונקציה מצביע למשתנהב -C ניתן להגדיר מצביע לפונקציה, בצורה דומה כמו שניתן להגדיר מצביע למשתנה השמה כתובת של פונקציה –ניתן לבצע השמה של כתובת של פונקציה למצביע לפונקציה להעבירכפרמטרים –ניתן להעביר מצביעים לפונקציות כפרמטרים לפונקציות אחרות int foo(char c, int i); int (*p) (char, int); p = &foo; (*p) (‘a’, 7); 24 מה הבדל עם int *p(char, int); ? פה יתבצע foo(‘a’,7);

25 מצביעים לפונקציות ניתן להשמיטניתן להשמיט & וגם * בהתייחסות למצביעים לפונקציות p = foo; p(‘a’, 7); ניתן לשנותניתן לשנות ערך של p ולגרום לו להצביע לפונקציה אחרת int bar(char c, int i);... p = foo; p(‘a’, 7); p = bar; p(‘b’, 17); 25 פה יתבצע foo(‘a’,7); פה יתבצע bar(‘b’,17);

26 דוגמא פונקציות השוואה נתונות שתי פונקציות השוואה בין מספרים typedef enum { Left, Eq, Right } Relation ; Relation bigger(int a, int b){ if (a > b) return Left ; if (a==b) return Eq ; return Right ; } Relation bigger2(int a, int b) { if (a<0) a = -a; if (b<0) b = -b; if (a > b) return Left ; if (a==b) return Eq; return Right; } 26 מה ההבדל בין הפונקציות ?

27 דוגמא פשוטה למצביעים לפונקציות 27 int main() { /* function is a pointer to a function with signature Relation f(int, int) */ Relation (*function)(int, int) ; if (getchar() == '1') { function = bigger; } else { function = bigger2; function = bigger2; } int a = -5, b = 3 ; Relation relation = function(a,b); switch (relation) { case Left: printf ("%d\n",a); break; case Eq: printf ("%d\n",a); break; case Right: printf ("%d\n",b); break; default: assert(0); } return 0; }

28 דוגמא מתקדמת – מיון מערכים typedef Relation (*CmpFunction)(int, int); CmpFunction compare void sort(int *array, int n, CmpFunction compare){ int i, j, tmp; assert(array !=NULL && compare != NULL); for(i=0; i<n; i++) { for(j=i+1; j<n; j++) { compare(arr[i], arr[j]) if(compare(arr[i], arr[j])==Left) { tmp = array[i]; array[i] = array[j]; array[j] = tmp; } 28

29 דוגמא מתקדמת – מיון מערכים int main(){ int arr[] = { 1, -3, 9, -10, -5 }; sort(arr, 5, bigger); sort(arr, 5, bigger); /* -10 -5 -3 1 9 */ sort(arr, 5, bigger2); sort(arr, 5, bigger2); /* 1 -3 -5 9 -10*/ return 0; } 29

30 פונקצית מיון גנרית נרחיב עצמים מכל טיפוסנרחיב את פונקצית המיון למיין עצמים מכל טיפוס שהוא עצמים מטיפוסים שונים פונקציה גנריתפונקציה שיכולה לעבד עצמים מטיפוסים שונים נקראת פונקציה גנרית למנוע שיכפול קודהמטרה של פונקציות גנריות היא למנוע שיכפול קוד אותו קוד טיפוסים שונים –להימנע מכתיבת אותו קוד עבור טיפוסים שונים פונקציות גנריות מבצעות את העבודה שלהם בעזרת : –מצביעים ל - void עצמים כללים –מצביעים ל - void לייצוג עצמים כללים שהפונקציה עובדת איתם –מצביעים לפונקציות פעולות –מצביעים לפונקציות לייצוג פעולות על העצמים 30

31 פונקצית מיון גנרית 31 typedef Relation (*CmpFunction)(int, int); void sort(int *array, int n, CmpFunction compare){ int i, j, tmp; assert(array !=NULL && compare != NULL); for(i=0; i<n; i++) { for(j=i+1; j<n; j++) { if(compare(array[i], array[j])==Left) { tmp = array[i]; array[i] = array[j]; array[j] = tmp; } void*, void* typedef Relation (*CmpFunction)(void*, void*); void ** void sort(void **array, int n, CmpFunction compare){ int i, j; void* void* tmp; assert(array !=NULL && compare != NULL); for(i=0; i<n; i++) { for(j=i+1; j<n; j++) { if(compare(array[i], array[j])==Left) { tmp = array[i]; array[i] = array[j]; array[j] = tmp; }

32 פונקצית השוואה בשביל פונקצית מיון גנרית לשלמים לתאריכים 32 Relation dateCompare(void* date1, void* date2){ int difference; DateResult result = dateDifference((Date)date1,(Date)date2, &difference); assert(result == DateSuccess); return bigger(difference,0); } Relation intCompare(void* a, void* b) { return bigger (*(int*)a, *(int*)b); }

33 מיון תאריכים ושלמים int main() { void *dates[3]; dates[0] = dateCreate(20, 5, 2010); dates[1] = dateCreate(1, 1, 2000); dates[2] = dateCreate(2, 2, 2001); void* numbers[3]; numbers[0] = malloc(sizeof(int)); *(int*)numbers[0] = 17; numbers[1] = malloc(sizeof(int)); *(int*)numbers[1] = 1; numbers[2] = malloc(sizeof(int)); *(int*)numbers[2] = 7; sort(dates,3,dateCompare); sort(numbers,3,intCompare); for (int i=0; i<3; i++){ dateWrite(stdout,dates[i]); printf(“\n”); } for (int i=0; i<3; i++){ printf(“%d\n”,*(int*)numbers[i]); } return 0; } 1 JAN 2000 2 FEB 2001 20 MAY 2010 1 7 17 33

34 מבנה נתונים ( ממומש כ -ADT) גנרי The stack example generic version

35 מבנה נתונים גנרי מבנה נתוניםטיפוסי נתונים לוגיקהזההלרוב למבנה נתונים לא משנה איזה טיפוסי נתונים יכיל, בין אם הם מחרוזות, מבנים, שלמים או תווים. בכל מקרה ה -“ לוגיקה ” של המבנה תהיה זהה. –למשל, מחסנית תמיד תוציא את האיברים שהוכנסו אליה בסדר הפוך לסדר ההכנסה (LIFO) - ללא קשר לטיפוס האיברים מבנה נתונים גנרי מכל טיפוס שהואנרצה לכתוב מבנה נתונים גנרי שמסוגל להכיל איברים מכל טיפוס שהוא לכתוב פעם אחת כל הטיפוסים –מספיק לכתוב את מבנה הנתונים רק פעם אחת בשביל כל הטיפוסים שיכפול קוד  מניעת שיכפול קוד –הכללה פונקציות גנריות –הכללה של הרעיון של פונקציות גנריות 35

36 מבנה נתונים גנרי הבעיהכיצד לבצע פעולותהבעיה : מבנה הנתונים לא יידע כיצד לבצע פעולות פשוטות הקשורות לאיברים שבו : –להעתיק –למחוק –להשוות ידיעה של הטיפוסביצוע פעולות אלו דורש ידיעה של הטיפוס של האיברים. מצביעים לפונקציות הפתרון : שימוש במצביעים לפונקציות מעביר בעת יצירת המבנה מצביעים לפונקציות פעולות –המשתמש במבנה הנתונים מעביר בעת יצירת המבנה מצביעים לפונקציות שמבצעות את הפעולות הספציפיות לטיפוס –בדומה לפונקצית השוואה שפונקצית המיון מקבלת 36

37 ADT מחסנית גנרית - הממשק ב -stack.h #ifndef _STACK_H #define _STACK_H /* generic ADT of Stack of integers */ typedef struct Stack_t* Stack ; typedef void* Element; typedef Element (*CopyFunction)(Element); typedef void (*FreeFunction)(Element); /* possible return values */ typedef enum { StackBadArgument, StackSuccess, StackFail, StackEmpty, StackFull } StackResult ; 37

38 ADT מחסנית גנרית - הממשק ב -stack.h /* Creates a Stack with maximal capacity of 'maxSize'. If fails, returns NULL */ Stack stackCreate(int maxSize, CopyFunction copyFunction, FreeFunction freeFunction); /* releases the memory allocated for the stack */ void stackDestroy(Stack stack); /* insert an element to the top of the stack. Error Codes: StackBadArgument if stack is NULL StackFull if the stack is full. */ StackResult stackPush(Stack stack, Element element); 38

39 ADT מחסנית גנרית - הממשק ב -stack.h /* removes the element at the top of the stack. Error codes: StackBadArgument if stack is NULL StackEmpty if the stack is empty */ StackResult stackPop(Stack stack); /* returns in the ‘element’ the last element that was pushed. Error codes: StackBadArgument if stack or element are NULL StackEmpty if the stack is empty */ StackResult stackTop(Stack stack, Element* element); /* returns the number of elements in the stack. Error codes: StackBadArgument if stack or size are NULL */ StackResult stackSize(Stack stack, int* size); #endif 39

40 ADT מחסנית גנרית - המימוש ב -stack.c #include #include "stack.h" /* a structure that represents a generic Stack */ struct Stack_t { /* The Stack is implemented as an array of Elements. With nextIndex as an index to the next available position and maximal size stored in maxCapacity. */ Element* array; int nextIndex; int maxCapacity; CopyFunction copyElement; FreeFunction freeElement; }; 40

41 ADT מחסנית גנרית - המימוש ב -stack.c Stack stackCreate(int maxSize, CopyFunction copyFunction, FreeFunction freeFunction) { Stack stack; if (maxSize <= 0){ return NULL; } stack = (Stack) malloc(sizeof(struct Stack_t)) ; if (stack == NULL){ return NULL; } stack->array = (Element*) malloc(sizeof(Element) * maxSize); if (stack->array == NULL){ free(stack); return NULL; } stack->nextIndex = 0; stack->maxCapacity = maxSize; stack->copyElement= copyFunction; stack->freeElement = freeFunction; return stack; } 41

42 ADT מחסנית גנרית - המימוש ב -stack.c StackResult stackPush(Stack stack, Element element) { if (stack == NULL){ return StackBadArgument; } if (stack->nextIndex >= stack->maxCapacity){ return StackFull; } Element newElement = stack->copyElement(element); if (newELement == NULL) { return StackFail; } assert(stack->nextIndex >= 0 && stack->nextIndex maxCapacity); stack->array[stack->nextIndex++] = newElement ; return StackSuccess; } 42

43 ADT מחסנית גנרית - המימוש ב -stack.c StackResult stackPop(Stack stack) { if (stack == NULL){ return StackBadArgument; } if (stack->nextIndex < 1){ return StackEmpty; } assert(stack->nextIndex > 0 && stack->nextIndex maxCapacity); stack->freeElement(stack->array[stack->nextIndex-1]); stack->nextIndex--; return StackSuccess; } 43

44 ADT מחסנית גנרית - המימוש ב -stack.c StackResult stackTop(Stack stack, Element* element) { if ((stack == NULL) || (element == NULL)){ return StackBadArgument; } if (stack->nextIndex < 1){ return StackEmpty; } assert(stack->nextIndex > 0 && stack->nextIndex maxCapacity); Element newElement = stack->copyElement(stack->array[stack->nextIndex-1]); if (newElement == NULL){ return StackFail; } *element = newElement; return StackSuccess; } 44

45 ADT מחסנית גנרית - המימוש ב -stack.c StackResult stackSize(Stack stack, int* size) { if (stack == NULL || size == NULL){ return StackBadArgument; } *size = stack->nextIndex; return StackSuccess; } void stackDestroy(Stack stack) { /* empty the stack - free all the elements */ while (stackPop(stack) == StackSuccess){ /* empty while body */ ; } if (stack != NULL){ free(stack->array); free(stack); } 45

46 הפתרון של הבעיה הקודמת בעזרת מחסנית גנרית #include #include "stack.h" #define MAX_INPUT_SIZE 100 #define UNDO_LAST_COMMAND -1 /* functions that will be used by the ADT */ Element copyInt(Element element) { int *newInt; if (element == NULL) return NULL; newInt = (int*) malloc (sizeof(int)); *newInt = *(int*)element; return newInt; } void freeInt(Element element) { free (element); } 46

47 הפתרון של הבעיה הקודמת בעזרת מחסנית גנרית int main(){ Stack stack; StackResult stackResult; int lastNumber, size = 0; stack = stackCreate(MAX_INPUT_SIZE, copyInt, freeInt); if (stack == NULL){ fprintf(stderr,"failed to create stack\n"); exit(1); } 47

48 הפתרון של הבעיה הקודמת בעזרת מחסנית /* read the input numbers */ while (size < MAX_INPUT_SIZE && scanf("%d",&lastNumber) == 1){ if (lastNumber == UNDO_LAST_COMMAND){ stackResult = stackPop(stack); if (stackResult == StackEmpty){ printf("No numbers were entered until now\n"); } else{ assert(stackResult == StackSuccess); printf("undo\n"); } } else{ stackResult = stackPush(stack,&lastNumber); assert(stackResult == StackSuccess); } stackResult = stackSize(stack, &size); assert(stackResult == StackSuccess); } 48

49 הפתרון של הבעיה הקודמת בעזרת מחסנית /* print the numbers in reverse order */ int* tmpNumber; do { stackResult = stackTop(stack,&tmpNumber); if (stackResult == StackSuccess){ printf("%d\n", *tmpNumber); free(tmpNumber); stackResult = stackPop(stack); } } while (stackResult == StackSuccess); stackDestroy(stack); return 0; { 49

50 דוגמא נוספת לשימוש במחסנית גנרית מחרוזות פקודותנניח שהפעם אנחנו רוצים לקלוט מהקלט מחרוזות שמייצגות פקודות –גודל מחרוזת מקסימלי הוא 80 תדפיס בסדר הפוךבסוף קליטת הפקודות התוכנית תדפיס את הפקודות בסדר הפוך UNDO מבטלת פקודה קודמתאחת הפקודות יכולה להיות UNDO - היא מבטלת קליטת פקודה קודמת –פקודת UNDO לא נקלטת ולא מודפסת בסוף התוכנית 50

51 הפתרון של הבעיה הקודמת בעזרת מחסנית גנרית #include #include "stack.h" #define MAX_INPUT_SIZE 100 #define UNDO_LAST_COMMAND “UNDO” #define MAX_COMMAND_SIZE 80 /* functions that will be used by the ADT */ Element copyString(Element element) { char *oldString = (char*) element; char *newString; if (element == NULL) return NULL; newString = (char*) malloc (strlen(oldString) + 1); strcpy(newString, oldString); return newString; } void freeString(Element element) { free (element); } 51

52 הפתרון של הבעיה הקודמת בעזרת מחסנית int main(){ Stack stack; StackResult stackResult; int size = 0; char lastCommand[MAX_COMMAND_SIZE]; stack = stackCreate(MAX_INPUT_SIZE, copyString, freeString); if (stack == NULL){ fprintf(stderr,"failed to create stack\n"); exit(1); } 52

53 הפתרון של הבעיה הקודמת בעזרת מחסנית /* read the input commands */ while (size < MAX_INPUT_SIZE && scanf("%s", lastCommand) == 1){ if (strcmp(lastCommand,UNDO_LAST_COMMAND) == 0){ stackResult = stackPop(stack); if (stackResult == StackEmpty){ printf("No commands were entered until now\n"); } else{ assert(stackResult == StackSuccess); printf("undo\n"); } } else { stackResult = stackPush(stack,lastCommand); assert(stackResult == StackSuccess); } stackResult = stackSize(stack, &size); assert(stackResult == StackSuccess); } 53

54 הפתרון של הבעיה הקודמת בעזרת מחסנית /* print the commands in reverse order */ Element tmpCommand; do { stackResult = stackTop(stack,&tmpCommand); if (stackResult == StackSuccess){ printf("%s\n", (char*)tmpCommand); freeString(tmpCommand); stackResult = stackPop(stack); } } while (stackResult == StackSuccess); stackDestroy(stack); return 0; { 54

55 ADTs בסיסיים שנלמדים בקורס מבני הנתונים הבסיסייםבקורס אנחנו לומדים את מבני הנתונים הבסיסיים הבאים ( כולם בצורת ADT) : 1.List 1.List ( רשימה ) –קיים הסדר –קיים הסדר בין האיברים יכול להופיע כמה פעמים –כל איבר יכול להופיע במבנה כמה פעמים 2.Set 2.Set ( קבוצה ) –הסדר לא מוגדר –הסדר בין האיברים לא מוגדר יכול להופיע פעם אחת בלבד –כל איבר יכול להופיע במבנה פעם אחת בלבד 3.Stack 3.Stack ( מחסנית ) –קיים הסדר LIFO –קיים הסדר בין האיברים והוא LIFO יכול להופיע כמה פעמים –כל איבר יכול להופיע במבנה כמה פעמים 4. Graph אבסטרקציה צמתים קשתות –מתאים לבעיות שדורשות אבסטרקציה של צמתים וקשתות  למשל, תיאור ערים וכבישים ביניהם 55

56 התאמת מבנה נתונים בסיסי לבעיה חשוב למצוא כמה שיותר מתאיםלכל בעיה חשוב למצוא מבנה נתונים בסיסי, שהוא כמה שיותר מתאים לה. בפרט, יש לשים לב סדר –לסדר בין האברים כפילויות –לכפילויות בין האיברים המטרותהמטרות בבחירת מבנה נתונים : –ייצוג טבעי וברור –ייצוג טבעי וברור לבעיה מתעד את עצמו  הקוד שמתעד את עצמו –מניעת שיכפול קוד  הקוד קצר וברור  הקוד שעובד מול המבנה צריך להיות כמה שיותר קצר וברור –מניעת באגים להגן נגד טעיות  המבנה צריך להגן נגד טעיות של המשתמש –למשל Set ימנע הכנסת אותו איבר יותר מפעם אחת לא מתחשביםהערה : מטרה נוספת היא סיבוכיות הפעולות עם המבנה. במטרה הזאת לא מתחשבים במת '' מ, אלא בקורס " מבני נתונים " 56


Download ppt "תרגול 5 דוגמא של ADT: מחסנית מצביעים לפונקציות תכנות גנרי דוגמא של ADT גנרי : מחסנית גנרית."

Similar presentations


Ads by Google