Presentation is loading. Please wait.

Presentation is loading. Please wait.

תרגול 4 פיתוח מודולרי ב -C makefile ADT-Abstract Data Type דוגמא פשוטה ל ADT- ( תאריך ( לי-טל משיח נערך.

Similar presentations


Presentation on theme: "תרגול 4 פיתוח מודולרי ב -C makefile ADT-Abstract Data Type דוגמא פשוטה ל ADT- ( תאריך ( לי-טל משיח נערך."— Presentation transcript:

1 תרגול 4 פיתוח מודולרי ב -C makefile ADT-Abstract Data Type דוגמא פשוטה ל ADT- ( תאריך ( לי-טל משיח litalma@cs.technion.ac.illitalma@cs.technion.ac.il נערך והורחב ע''י ודים אייזנברג

2 הבעיה : קשה לפתח ולתחזק תוכנה גדולה –תוכנה גדולה למיליוני שורות קוד –תוכנה גדולה יכולה להגיע למיליוני שורות קוד קשה לתפוס כמות מידע –למוח האנושי קשה לתפוס כמות כזאת של מידע להביןלשנות –יש צורך להבין, לדבג ולשנות את התוכנה לכל אורך החיים שלה 2

3 שלבים בחיים של תוכנה 1. פיתוח 2. תחזוקה הרבה שנים –תוכנה יכולה " לחיות " הרבה שנים אחרי שהגרסה הראשונה פותחה –הוצאות תחזוקה –הוצאות על תחזוקה מהוות עד 80% מכל ההוצאות על התוכנה משתנה –התוכנה משתנה כל הזמן באגיםתיקוני באגים הוספת אפשרויותהוספת אפשרויות / סביבות עבודה נוספות שינוייםשינויים בחוקים / כללים עסקיים / נהלים שמצריכים שינויים בתוכנה 3

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

5 הפיתרון : תכנות מודולרי חלוקתלמודוליםחלוקת התוכנה למודולים בצורה לוגית –בנוסף לחלוקה לפונקציות הסתרת מידעהסתרת מידע לא נחוץ להבנה של המודלים התמודדות כמויות מידע –מקלה על התמודדות עם כמויות מידע גדולות שינוי מימוש –מאפשרת שינוי מימוש של המודולים בלי להשפיע על שאר התוכנה שימוש חוזרשימוש חוזר במודולים (code reuse) –אין צורך לכתוב אותו קוד כמה פעמים –מקטין את התוכנה פחות קוד להבין, לתחזק ולדבג 5

6 הפרדה לממשק ומימוש כל מודול מורכב משני חלקים : 1. ממשק 1. ממשק (interface) 2. מימוש 2. מימוש (implementation) ממשק מהווה מעין " חוברת הוראות שימוש " או " לוח כניסות " של המודול מסתירמסתיר כל פרטי המימוש של המודול הלא נחוצים לעבודה עם המודול 6

7 פיתוח תוכנה בלי מודולים 7

8 חלוקה למודולים 8

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

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

11 שינוים במימוש של מודול כלשהו שינויים במודול כלשהו לא משפיעים על שאר המודולים 11

12 כל מודול יכול גם להתחלק למודולים 12

13 שימוש חוזר במודולים בתוכנה אחרת תוכנה א תוכנה ב 13

14 יתרונות נוספים של תכנות מודולארי להיכתב ולהיבדקכל מודול יכול להיכתב ולהיבדק בנפרד אנשים שונים –על ידי אנשים או צוותים שונים –בזמנים שונים –במקומות שונים 14

15 תכנות מודולארי ב -C : הממשק headerהממשק נכתב בקובץ header (.h) הקובץ מכיל –ההצהרות הפונקציות –ההצהרות על הפונקציות אותן מממש המודול –הגדרות קבועיםטיפוסים –הגדרות של קבועים והגדרות של טיפוסים אשר המשתמש במודול זה צריך להכיר ערכי שגיאה למשל ערכי שגיאה אפשריים של הפונקציות השירותיםהפונקציות המוצהרות ב header הינן השירותים אותם מספק המודול לשאר התוכנה 15

16 תכנות מודולארי ב -C : המימוש המימושהמימוש נכתב בקובץ.c הקובץ מכיל –מימוש הפונקציות –מימוש הפונקציות אשר הוצהרו ב -header –פונקציות פנימיות –פונקציות פנימיות למודול אשר לא נועדו לשימוש מחוץ למודול –משתנים סטטיים –משתנים סטטיים של הקובץ 16

17 דוגמא : מודול תאריך פעולות לתאריכיםבתוכנית שנכתוב מתבצעות פעולות הקשורות לתאריכים נממש את הפעולות במודול נפרד בשם date 17

18 קובץ ה -date.h :header #include /* date module This module defines a date type and implements some date manipulation functions. */ typedef struct Date_t { int day; char month[4]; int year; } Date; typedef enum {DateSuccess,DateFail,DateFailRead, DateBadArgument} DateResult; 18

19 המשך קובץ ה -date.h :header /* reads a date from an open file – ‘inputFile’ expects the ‘date’ to point to an allocated Date */ DateResult dateRead (FILE* inputFile, Date* date); /* writes the date to the output file ‘outputFile’ */ DateResult dateWrite (FILE* outputFile, Date* date); /* returns the number of days between dates */ DateResult dateDifference(Date* date1, Date* date2, int* difference); 19

20 קובץ המימוש : date.c #include #include "date.h" #define MIN_DAY 1 #define MAX_DAY 31 #define MIN_MONTH 1 #define MAX_MONTH 12 #define DAYS_IN_YEAR 365 static char * months[]= {"JAN", "FEB", "MAR", " APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; 20 קבועים שמוגדרים בקובץ.c – מוסתרים משאר התוכנה משתנה סטאטי של קובץ – מוסתר משאר התוכנה

21 קובץ המימוש : date.c /* returns the date’s month number (1-12) */ static DateResult dateToMonth(Date* date, int* month); /* returns the number of days passed from 01/01/00 */ static DateResult dateToDays(Date* date, int* day); 21 פונקציות פנימיות של המודול – מוסתרות משאר התוכנה

22 קובץ המימוש : date.c static bool isDayValid(int day){ return ((day >= MIN_DAY) && (day <= MAX_DAY)); } static bool isMonthNumberValid(int month){ return ((month >= MIN_MONTH) && (month <= MAX_MONTH)); { static bool isMonthStringValid(char* month){ for (int i = MIN_MONTH; i <= MAX_MONTH; i++){ if (strcmp(month, months[i-1]) == 0){ return true; } return false; } 22 פונקציות פנימיות של המודול – מוסתרות משאר התוכנה

23 קובץ המימוש : date.c DateResult dateRead(FILE* inputFile, Date* date) { if (inputFile == NULL || date == NULL) return DateBadArgument; if (fscanf (inputFile, "%d %s %d", &(date->day), date->month, &(date->year)) != 3) return DateFailRead; if (!isDayValid(date->day) || !isMonthStringValid(date->month)) return DateFail; return DateSuccess; } 23

24 קובץ המימוש : date.c DateResult dateWrite(FILE* outputFile, Date* date){ if (outputFile == NULL || date == NULL) return DateBadArgument; if (fprintf (outputFile, "%d %s %d ", date->day, date->month, date->year) < 0) return DateFail; return DateSuccess; } 24

25 קובץ המימוש : date.c static DateResult dateToMonth(Date* date, int* month) { int i = 0; if (date== NULL || month == NULL) return DateBadArgument; for (i = MIN_MONTH; i <= MAX_MONTH; i++){ if (strcmp(date->month, months[i-1]) == 0){ *month = i; return DateSuccess; } return DateFail; } 25

26 קובץ המימוש : date.c static DateResult dateToDays(Date* date, int* days) { int month; if (date == NULL || days == NULL) return DateBadArgument; if (dateToMonth(date,&month) != DateSuccess) return DateFail; assert(isMonthNumberValid(month)); *days = date->day + month*(MAX_DAY – MIN_DAY + 1) + DAYS_IN_YEAR *date->year; return DateSuccess; } 26 אם ה -assert נכשל - יש באג ב - dateToMonth

27 קובץ המימוש : date.c DateResult dateDifference(Date* date1, Date* date2, int* difference) { int days1, days2; if (date1 == NULL || date2 == NULL || difference == NULL) return DateBadArgument; if ((dateToDays(date1,&days1) != DateSuccess) || (dateToDays(date2,&days2) != DateSuccess)) return DateFail; *difference = (days1 > days2) ? (days1 – days2) : (days2 - days1); assert(*difference >= 0); return DateSuccess; } 27

28 מודול שמשתמש במודול תאריך : proc.c #include #include "date.h" int main() { Date date1,date2; int difference; if (dateRead(stdin,&date1) == DateFail || dateRead(stdin,&date2) == DateFail) return 1; printf ("The difference between "); dateWrite(stdout,&date1); printf(" and "); dateWrite(stdout,&date2); dateDifference(&date1, &date2,&difference); printf("is %d days.\n", difference); return 0; } 28

29 תמיכת שפת C בכתיבת מודולים –כתיבת מודולים הוטמעה בשפת C בכך שבניית התוכנה נעשית בשני שלבים : 1. הידור 1. הידור (compilation) של כל קובץ בנפרד 2. קישור 2. קישור (linking) של כל הקבצים ביחד 29

30 הידור ב -C מקומפל בנפרדכל קובץ מקומפל בנפרד לקמפל בנפרד פונקציות חיצוניות בקבצים אחריםהבעיה : איך אפשר לקמפל קובץ כלשהו בנפרד אם הוא משתמש בפונקציות חיצוניות שנמצאות בקבצים אחרים ? המימוש הפונקציות החיצוניות הצהרותיהןהפתרון : הקומפיילר אינו צריך לראות את המימוש של הפונקציות החיצוניות, אלא רק את הצהרותיהן include קבצי header הצהרות פונקציות משתמשיש לעשות include של קבצי header שמכילים הצהרות של פונקציות שהמודול משתמש בהן 30

31 שימוש בקבצי header להשתמש include –כל קובץ שצריך להשתמש בפריטים כלשהם של מודול מסוים, יבצע include לקובץ ה header- שלו : #include “date.h” #include 31 include של header של התוכנה ניתן לציין path מלא של הקובץ include של header סטנדרטי ( של מערכת ההפעלה ) כל ה -headers הסטנדרטיים נמצאים במקום מוגדר מראש ע '' י מערכת ההפעלה

32 הוראת include רק שצריכים במקוםחייבים לעשות include רק לדברים שצריכים אותם במקום שבו עושים include רק אם יש צורך בהגדרות –עושים include ב -header רק אם יש צורך בהגדרות של הקובץ הנכלל ב -header עצמו בהצהרה של פונקציות של ה header- לצמצם תלויותהמטרה - לצמצם תלויות הוראות include ללא צורך במקום הלא נחוץהוראות include ללא צורך או במקום הלא נחוץ - סגנון תכנות רע 32

33 מגנון #ifndef בקבצי header להיכלל במספר קבצים ifndef#מכיוון שקובץ ה -header עשוי להיכלל במספר קבצים, יש להשתמש במנגנון ifndef#, אשר בודק האם קבוע מסוים הוגדר. רק בפעם הראשונהרק בפעם הראשונה בה יתבצע,#include "date.h" הקובץ date.h ייכלל בפועל חייב להופיע בכל קובץ header 33 #ifndef DATE_H #define DATE_H /* file date.h – the header of module date*/...#endif

34 הידור ב -C קובץ objectתוצאת ההידור היא קובץ object קוד מכונה –מכיל קוד מכונה שמתאים לקוד מקור של המודול חורים –במקום קריאות לפונקציות חיצוניות יש " חורים " שלב הקישור –ה " חורים " ימולאו בשלב הבא – שלב הקישור 34 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 14: e8 00 00 00 00 callq 19 19: c7 45 fc 00 00 00 00 movl $0x0,0xfffffffffffffffc(%rbp) 36: eb e8 jmp 20 38: b8 00 00 00 00 mov $0x0,%eax 3d: e8 00 00 00 00 callq 42 42: c9 leaveq 43: c3 retq קוד מכונה ניתן פה להמחשה בלבד – אין צורך להבין אותו

35 קישור (linking) linker מחברה -linker מחבר את כל קבצי ה -object לתוכנית אחת ממלא ה " חוריםממלא את כל ה " חורים " בקבצי object במידע אמיתי 35

36 הידור וקישור על ידי gcc כאשר מבצעים ניתן להפריד את השלבים : gcc -c prog.c date.c יוצר את קבצי ה- object gcc prog.o date.o -o prog מקשר את קבצי ה- objectויוצר קובץ הרצה prog gcc prog.c date.c -o prog מבוצעים שני השלבים ביחד – נוצר קובץ הרצה prog 36

37 שינוי במודולים של תוכנה קובץ משתנה צריך לקמפל / לקשר מחדשאם קובץ מסוים משתנה – אילו קבצים צריך לקמפל / לקשר מחדש ? בקובץ.c –אם השינוי נעשה בקובץ.c ניתן לקמפל רק אותו בקובץ header תלויים בקובץ ששונה –אם השינוי נעשה בקובץ header, חייבים לקמפל את כל הקבצים שתלויים בקובץ ששונה קישור מחדש –ואחרי שקימפלנו קובץ כלשהוא חייבים לבצע קישור מחדש של כל קבצי ה -object 37

38 בנייה יעילה של תוכנה ממספר קבצים דוגמא : תוכנית המורכבת מהקבצים הבאים : – calc.c – control.c – main_prog.c שמשנים קובץ.cבכל פעם שמשנים קובץ.c מסוים, מספיק להדר שוב רק אותו ולבצע קישור מחדש. לדוגמא, אם שונה control.c, מספיק לבצע : gcc -c calc.c gcc -c control.c gcc -c main_prog.c gcc calc.o control.o main_prog.o -o prog gcc -c control.c gcc calc.o control.o main_prog.o -o prog 38

39 אוטומציה של בניית התוכנה בניית תוכנהמורכבתהליך בניית תוכנה גדולה יכול להיות מורכב –אלפי קבצים –אלפי קבצים ( מודולים ) כמה שעות –עלול לקחת כמה שעות הידור בצורה שונה –כל קובץ יכול לדרוש הידור בצורה שונה דגלי קומפילציה שונים שפות תכנות שונות קומפיילרים שונים –תלויות מורכבות –תלויות מורכבות בין הקבצים כשקובץ מסוים משתנה – אילו קבצים צריך לקמפל מחדש ? קיימת סכנה בפספוס חלק מהתלויות ובניית תוכנה פגומה כתוצאה מכך לא יעיל לקמפל את כל הקבצים בשביל כל שינוי 39

40 אוטומציה של בניית התוכנה - make תהליך אוטומטי makeניתן להפוך את תהליך בניית התוכנה לאוטומטי ע " י שימוש בתוכנה make Makefile חוקי בניית התוכנה –מקבלת כקלט קובץ Makefile שבו מקודדים חוקי בניית התוכנה אילו קבציםאילו קבצים יש לקמפל ולקשר, מתי ובאילו תנאים איךאיך לקמפל / לקשר את הקבצים תלויותתלויות בין הקבצים משנים make אילו צעדים חייבים לבצע –כאשר משנים קובץ כלשהו ומריצים,make הפקודה מחשבת אילו צעדים בבניית התוכנה חייבים לבצע ומבצעת רק אותם חוסכת קימפול מחדש של כל הקבצים 40

41 קבצי Makefile Makefileקובץ ה -Makefile המתאים לדוגמא הנ " ל הוא : 41 prog: main_prog.o calc.o control.o gcc calc.o control.o main_prog.o -o prog calc.o: calc.c gcc -c calc.c control.o: control.c gcc -c control.c main_prog.o: main_prog.c gcc -c main_prog.c

42 Makefile – דוגמא נוספת תוכנה שמורכבת מהקבצים הבאים : 42

43 make Makefileקובץ ה -Makefile המתאים לתוכנה הזאת : makeהפעלת make על התוכנה prog:a.o b.o c.o gcc a.o b.o c.o -o prog a.o:a.c a.h b.h gcc -c a.c b.o:b.c b.h gcc -c b.c c.o:c.c c.h b.h gcc -c c.c > make > make prog 43

44 מבנה קובץ Makefile ממספר כניסותקובץ Makefile מורכב ממספר כניסות מבנה הכניסות : : targetכל target בדרך כלל מציין קובץ ( קובץ מקור, header, object או הרצה ) # הערה עד סוף השורה # מסמן הערה עד סוף השורה נקודות נוספות : TAB הפקודה לא תתבצע –בלי TAB בתחילת שורת הפקודה, הפקודה לא תתבצע. לשבור שורה ארוכה \ –כדי לשבור שורה ארוכה לכמה שורות יש להוסיף \ בסוף כל שורה פרט לאחרונה ( ועדיין יש לשים TAB בתחילת כל שורה ) –אין לשים רווחים –אין לשים רווחים לא בתחילת שורה ולא בסופה סיום שורות ב -Enter 44

45 שימוש ב -make make [ -f filename ] [ target ] מחפש make מחפש את קובץ ה -Makefile באופן הבא : –אם לא משתמשים באופציה -f הוא מחפש קובץ בשם makefile או Makefile בתיקיה הנוכחית. –אם משתמשים באופציה -f הוא מחפש את הקובץ filename target מופיעאם target מופיע בהפעלת make, הפקודה מבצעת את רשימת הפקודות המופיעות ב -target ב -Makefile target לא מופיע ה -target הראשוןאם target לא מופיע בהפעלת make הפקודה מבצעת את ה -target הראשון ב -Makefile 45

46 אופן פעולת make 1. בודקת את התלויות 1. בודקת את התלויות ב -target אותו הוא הולך לבצע חדש יותר לעדכנו 2. אם יש קובץ ברשימת התלויות שהוא חדש יותר מקובץ ה - target יש לבצע את הפקודה של ה - target על מנת לעדכנו 3. בדיקת התלויות רקורסיבי בסדר הנכון 3. בדיקת התלויות נעשית באופן רקורסיבי, כך שיבוצעו כל הפקודות של הקבצים שבהם ה - target תלוי, בסדר הנכון 46

47 הגדרת מאקרו ב -Makefile מאקרוב -Makefile כדאי להגדיר כמאקרו מחרוזת –שחוזרת כמה פעמים –שעשויה להשתנות בעתיד ניתן להגדיר מאקרו בצורה הבאה : EXEC = prog אחרי שמאקרו כלשהו מוגדר, ניתן להתיחס אליו על ידי $ ושם המאקרו בסוגריים : ($(EXEC מאקרו מוגדרים מראשקיימים מאקרו מוגדרים מראש : – $@ הוא ה -target הנוכחי – $* הוא ה -target הנוכחי ללא סיומת 47

48 דוגמא לשימוש במאקרו ב -Makefile 48 CC = gcc OBJS = a.o b.o c.o EXEC = prog DEBUG_FLAG = # now empty, assign -g for debug COMP_FLAG = -c -Wall $(EXEC) : $(OBJS) $(CC) $(DEBUG_FLAG) $(OBJS) -o $@ a.o : a.c a.h b.h $(CC) $(DEBUG_FLAG) $(COMP_FLAG) $*.c b.o : b.c b.h $(CC) $(DEBUG_FLAG) $(COMP_FLAG) $*.c c.o : c.c c.h b.h $(CC) $(DEBUG_FLAG) $(COMP_FLAG) $*.c clean: rm -f $(OBJS) $(EXEC) > make clean rm -f a.o b.o c.o prog > make gcc -c -Wall a.c gcc -c -Wall b.c gcc -c -Wall c.c gcc a.o b.o c.o -o prog

49 יצירת תלויות ל -Makefile באופן אוטומטי למצוא תלויות בין קבציםאפשר למצוא תלויות בין קבצים ע " י שימוש בפקודה הבאה : gcc -MM למשל : לשמור שלדניתן לשמור פלט זה בקובץ ולהשתמש בו כשלד ל - Makefile > gcc -MM *.c a.o : a.c a.h b.h b.o : b.c b.h c.o : c.c c.h b.h 49

50 ADT Abstract Data Type

51 ADT מבנה נתונים מופשט ADT מודול מיוחד ADT הינו מודול מסוג מיוחד מסתירים הגדרת המבנהב -ADT מסתירים גם את הגדרת המבנה משאר התוכנה טיפוס של מצביע למבנהמגדירים טיפוס של מצביע למבנה אינם ידועים מחוץ למודול – גודל המבנה ושדותיו אינם ידועים מחוץ למודול של ה - ADT קבוצת פונקציותנותנים למשתמש קבוצת פונקציות אשר רק בעזרתן ניתן לטפל בטיפוס כמו לכל מודול ל -ADT יש – ממשק ( קובץ.h) –מימוש ( קובץ (.c 51

52 מודול תאריך שאינו ADT הגדרת המבנה חשופהבמודול תאריך שראינו קודם, הגדרת המבנה הופיעה בקובץ header ולכן הייתה חשופה לשאר התוכנה לכן הוא אינו ADT חשיפת המבנה גורמת לבעיות 52

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

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

55 ADT כפתרון המבנה מוסתרב -ADT המבנה מוסתר משאר המודולים מקולקל פונקציות של ה - ADT עצמו –אם משתנה מסוג ADT מקולקל – רק פונקציות של ה - ADT עצמו יכלו לקלקל אותו קל למצוא באגים השינוי משפיע –אם מתעורר צורך בשינוי המבנה, השינוי משפיע רק על הפונקציות של ה -ADT איןגרירה של שינוייםאין גרירה של שינויים לשאר מודולים של התוכנה 55

56 ADT תאריך : קובץ date.h header #ifndef DATE_H #define DATE_H #include /* date ADT */ typedef struct Date_t* Date; typedef enum {DateSuccess,DateFail,DateFailRead, DateBadArgument} DateResult; 56 ב -ADT מגדירים מצביע ל -struct לא ידוע ה -struct עצמו מוגדר בקובץ.c

57 ADT תאריך : קובץ date.h header /* reads a date from an open file – ‘inputFile’ expects the ‘date’ to point to an allocated Date */ DateResult dateRead(FILE* inputFile, Date date); /* writes the date to the output file ‘outputFile’ */ DateResult dateWrite(FILE* outputFile, Date date); /* returns the number of days between dates */ DateResult dateDifference(Date date1, Date date2, int* difference); 57 השינוי היחיד הוא שעכשיו Date הוא מצביע ל -struct

58 ADT תאריך : קובץ date.h header /* Allocates and initializes a new date. Returns NULL if fails.*/ Date dateCreate(int day, int month, int year); /* deallocates the date*/ void dateDestroy (Date date); /* copies the Date. returns NULL if fails */ Date dateCopy(Date date); #endif 58 פונקציות חדשות – ליצירה, הריסה והעתקה של ה -ADT

59 ADT תאריך : קובץ date.c #include #include “date.h” #define MIN_DAY 1 #define MAX_DAY 31 #define MIN_MONTH 1 #define MAX_MONTH 12 #define DAYS_IN_YEAR 365 struct Date_t { int day; char month[4]; int year; }; static char* months[]= {"JAN", "FEB", "MAR", “APR”, "MAY", "JUN", "JUL", "AUG", “SEP", "OCT", "NOV", "DEC"}; 59 המבנה מוגדר בקובץ.c ! מוסתר משאר התוכנה

60 ADT תאריך : קובץ date.c DateResult dateWrite(FILE* outputFile, Date date){ if (outputFile == NULL || date == NULL) return DateBadArgument; if (fprintf (outputFile, "%d %s %d ", date->day, date->month, date->year) < 0) return DateFail; return DateSuccess; } 60 אותו מימוש כמו בגרסה שהיא לא ADT, רק הפעם Date הוא מצביע ל -struct אותה הערה תקפה לגבי שאר הפונקציות שהיו בגרסה שהיא לא ADT

61 ADT תאריך : קובץ date.c Date dateCreate(int day, int month, int year) { Date date = NULL; if (!isDayValid(day) || !isMonthNumberValid(month)) return NULL ; date = (Date) malloc(sizeof(struct Date_t)); if (date == NULL) return NULL; date->day = day ; strcpy (date->month,months[month-1]); date->year = year ; return date ; } 61 פונקציה חדשה

62 ADT תאריך : קובץ date.c void dateDestroy(Date date) { free(date); } Date dateCopy(Date date) { int month = -1; if (dateToMonth(date,&month) != DateSuccess) return NULL; assert(isMonthNumberValid(month)); return dateCreate(date->day, month, date->year); { 62 פונקציות חדשות

63 מודול שמשתמש ב -ADT תאריך : proc.c #include #include "date.h" int main() { Date date1,date2; int difference; if ((date1 = dateCreate(1,1,1)) == NULL)||(date2 = dateCreate(2,2,2)) == NULL)) return 1; if ((dateRead(stdin,date1) == DateFail) || (dateRead(stdin,date2) == DateFail)) return 1; printf ("The difference between "); dateWrite(stdout,date1); printf(" and "); dateWrite(stdout,date2); dateDifference(date1,date2,&difference); printf(" is %d days.\n", difference); dateDestroy(date1); dateDestroy(date2); return 0; } 63 חייבים לקרוא ל - dateDestroy


Download ppt "תרגול 4 פיתוח מודולרי ב -C makefile ADT-Abstract Data Type דוגמא פשוטה ל ADT- ( תאריך ( לי-טל משיח נערך."

Similar presentations


Ads by Google