בס"ד תרגיל 3 מועד אחרון ל כללי בתרגיל זה עליכם לכתוב תוכנה שמדמה מאגר נתונים של חנות. את מוצרי החנות תייצגו באמצעות עצים ורשימות מקושרות יהיה עליכם לנהל את מאגר הנתונים של החנות, לבצע אליו שינוים ושאילתות ולקרוא אותו מקובץ. כמו כן לכל אורך העבודה תאלצו להשתמש בזיכרון דינמי. העבודה מחולקת לשלושה חלקים, שדורשים ידע שונה, לכל חלק קובץ *.c נפרד, פתרון כל חלק מתבסס על החלק הקודם. 1. רשימות מקושרות: ייצוג קבוצה של מחרוזות ע י רשימות מקושרות - part1-lists.c 2. עצים: מבנה נתונים של חנות בעזרת עץ - part2-trees.c 3. קבצים: קריאת מידע של חנות מקובץ- part3-files.c כמו כן מצורפים עוד שני קבצים, אשר מוכנים לעבודה, אין לשונותם: 1. :definitions.h מכיל הגדרות של המבנים ואת החתימות של כל הפונקציות שבשימוש. עבור פונקציות עזר שתכתבו אין צורך בשימוש 2. :mainmenu.c מכיל את כל התפריטים, ופונקציות הקלט מהמשתמש. *במקרה של טעות בקוד באחד הקבצים אנא שלחו למתרגל האחראי מייל בנושא. ניתן להדר ולהריץ את הפרויקט באופן מידי, פשוט פותחים פרויקט חדש, מוסיפים לו )בעזרת האופציה )Add Existing Item את חמשת הקבצים הצורפים. בשלב זה הפרויקט אמור לרוץ. כל שנשאר לכם לעשות הוא לכתוב את הפונקציות שיתוארו בהמשך. כל המעטפת מוכנה. כל פונקציה שתתבקשו לכתוב קימת כבר בקבצי הקוד אך לא עושה שום דבר משימתכם למלאה. typedef struct StringList { char *string; struct StringList *next; } StringList; 1. חלק א- פעולות על רשימות מקושרות: בחלק זה של העבודה נעבוד אם רשימות מקושרת של מחרוזות. לכל סעיף אתם נדרשים לממש פונקציה, החתימה שלה מופיעה בקובץ הגדרות. להלן המבנים הדרושים לחלק זה
קלט: מצביע לרשימה מקושרת של מחרוזות. פעולת הפונקציה: מיון הרשימה בסדר לקסיקוגרפי )לפי השדה.)string פלט:.void חתימה: *sl) void sortlist(stringlist )1 קלט: מצביע למצביע לרשימה מקושרות ממוינות ללא כפילויות של מחרוזות A ו מחרוזת S. פעולת הפונקציה: מוסיף את S ל A כך שרשימה נותרת ממוינת לאחר ההוספה. במידה ומחרוזת זאת כבר קיימת ברשימה לא מוספים אותה!!!! פלט: void חתימה: *s) void addtosortedlist(stringlist **a, char )2 *שימו לב שאליכם להקצות זיכרון חדש עבור המחרוזת שאתם מוסיפים ברשימה ולהעתיק את המחרוזת S לרשימה, שמירת המצביע ללא העתקה ממשית של הנתונים תיצור באגים בתכנית. ראו הוזהרתם.
קלט: מצביעים לשתי רשימות מקושרות ממוינות ללא כפילויות של מחרוזות A ו B. פעולת הפונקציה: בדוק האם כל אברי A מוכלים ב B. פלט: 1 אם A מוכלת ב B, אחרת 0. חתימה: *b) int issubsetof(stringlist *a, StringList )3 קלט: מצביעים לשתי רשימות מקושרות ממוינות ללא כפילויות של מחרוזותA ו B. פעולת הפונקציה: מציאת קבוצת החיתוך של A ו B. (תת רשימה C של A וגם של B בעלת גודל מקסימלי( פלט: מצביע לרשימה מקושרת ממוינת חדשה C כך שכל איבר שמופיעה ב A וגם ב B מופיע ב C (אם אין אף איבר מחזיר את הרשימה הריקה(. חתימה: *b) StringList* intersection(stringlist *a, StringList )4 ***שימו לב שהרשימות A ו B אמורות להישאר ללא שינוי בתום הריצה של הפונקציה. בידוקו זאת היטב, זה ייבדק. כמו כן המחרוזות ברשימה המוחזרת חייבים להיות שכפול.
2. חלק ב - מאגר הנתונים של חנות: בחלק זה של העבודה נגדיר מבנה נתונים ששומר מידע על מוצרי חנות. חנות הינה עץ בינארי של מוצרים שממוין ע"פי שמות המוצרים. למוצר יש שם, מחיר ורשימה מקושרת ממוינת של מחרוזות ללא כפילויות שמייצגות מאפיינים של המוצר (כל מחרוזת מייצגת מאפיין יחיד(. לכל סעיף אתם נדרשים לממש פונקציה, החתימה שלה מופיעה בקובץ הגדרות. typedef struct Product { char *name; int price; struct StringList *properties; } Product; להלן המבנים הנוספים הדרושים לחלק זה typedef struct ProductTree { Product *product; struct ProductTree *left; struct ProductTree *right; } ProductTree; קלט: מצביע למצביע לעץ מוצרים T ומצביע למוצר P. פעולת הפונקציה: במידה ולא קיים מוצר בעל אותו שם בעץ T מוספים את P לעץ. פלט: void חתימה: *p) void addproduct(producttree **t, Product )1
קלט: מצביע לעץ מוצרים T, מחרוזת N (שם מוצר(, ומחרוזת P (מאפיין(. פעולת הפונקציה: חיפוש מוצר בעל שם N בעץ T. במידה וקיים מוצר בשם זה נוסיף לו את המאפיין P (זאת במידה והמאפיין לא שייך כבר לרשימה מאפיינים בדיוק כמו ב 1.2( פלט: void חתימה: *p) void addproductproperty(producttree *t,char *n, char )2 קלט: מצביע לרשימת מאפיינים ממוינת ללא כפילויות של מחרוזות L ומצביע לעץ מוצרים T. פעולת הפונקציה: מציאת המוצר P בעל העלות המינימלית בחנות אשר כל אברי L שייכים לרשימת מאפיינים של P. פלט: אם לא קיים מוצר אשר מכיל את רשימת המאפיינים L אז 0 אחרת מצביע למוצר אם העלות המינימלית, אם יש יותר ממוצר אחד בעל עלות מינימלית מחזרים את זה שהכי קטן על פי סידור לקסיקוגרפי חתימה: *l) Product* findminimal(producttree *t,stringlist )3
קלט: מצביע לרשימת שמות מוצרים L (לא בהכרח ממוינת( ומצביע לעץ מוצרים T. פעולת הפונקציה: מציאת רשימת מאפיינים מקסימלית שמוכלת בכל אחת מרשימות המאפיינים של שמות המוצרים ב L. במידה ויש מוצר בעץ פלט: במידה וקיים שם מוצר ב L שלא מופיעה ב T אז מחזרים 0 )רשימה ריקה(, אחרת מחזרים מצביע לרשימה שמכילה את חיתוך כל רשימות המאפיינים של המוצרים ששמם ב.L חתימה: *l) StringList * findcommonprops(producttree *t,stringlist )4 בונוס 10 נקודות קלט: מצביע לעץ מוצרים T ו ומחרוזת N שמייצגת שם של מוצר. פעולת הפונקציה: חיפוש מוצר בעל שם N בעץ T. במידה וקיים מוצר בשם זה מורדים אותו מהעץ. פלט: אם יש מוצר בשם N בעץ T אזי מחזירם מצביע למוצר. אחרת מחזרים 0. חתימה: *n) Procduct* removeproduct(producttree **t, char )5
3. חלק ג - טעינת מאגר נתונים של חנות מקובץ: בחלק זה נטען מקובץ בסיס נתונים מלא של חנות. קבצים אלו יהיו אם סיומת csv. אשר מאפשר פתיחה ועריכה אם תוכנת.excel כל שורה בקובץ תייצג מוצר. מוצר מחזיק שלוש ערכים, שם, מחיר ורשימת מאפיינים כאשר ביניהם יפריד ; רשימה של מחרוזות נשמור בקובץ ברצף את אברי הרשימה אשר מופרדים ע"י פסיק, חשוב!!! המאפיינים של כול מוצר לא חייבים להיות ממוינים!!!!! (אתם צריכים לעשות זאת( כמו כן במחרוזות צריכות להיות מנוקות מרווחים וטאבים למשל ; b ; a שקול ל ;b a; דוגמה לקובץ: wine ; 100 ; alcoholic,drink,grapes tomatoes ; 12 ; vegetable,red nutella ; 50 ; hazelnut spread,cocoa onion ; 3 ; vegetable קלט: מחרוזתFN (שם של קובץ(. פעולת הפונקציה: פותחים את הקובץ בעל השם,fn מאתחלים עץ מוצרים חדש, קוראים מהקובץ שורה שורה (כל שורה מייצגת מוצר( ומוספים את המוצרים המתקבלים משורות לעץ. פלט: עץ מוצרים חדש שמכיל בדיוק את כל המוצרים מהקובץ. במידה ויש בעיה אם פתיחת הקובץ מדפיסים file\n" "Error opening ומחזרים 0. במידה והפורמט של הקובץ דפוק מדפיסים corrupt\n" "File ומחזרים 0. חתימה: *fn) ProductTree* readstore(char )1 *שימו של שהמחיר של מוצר הינו מספר חיובי גדול ממש מאפס. כל ערך אחר הוא לא חוקי. כמו כן ניתן להניח שהמרחק המקסימלי בין תחילת שורה ו ; ו, לבין ; ו, וסוף שורה הוא לכל היותר 522 תווים. בונוס 10 נקודות אל מנת לקבל את הנקודות של בונוס זה אליכם להוסיף אופציה של שמירת בסיס נתונים מלא בקובץ. לעומת הסעיפים הקודמים פה אתם נדרשים לשנות את הקובץ.mainMenu.c אליכם להוסיף אופציה מספר 8 ל (8"(, Save to file"( treemenu במידה והמשתמש בוחר באופציה זו יש לבקש ממנו להכניס שם של קובץ אליו שומרים name"(,)"enter file ולאחר מכן לקורא לפונקציה )שמוגדרת פה, את חתימתה יש להוסיף ל definitions.h ואת הגדרתה יש להוסיף לקובץ part3- )Files.c אשר מקבלת את שם הקובץ, מדפיסה בתוך הקובץ את נתוני החנות בפורמט זהה לזה שהוגדר בחלק ג של העבודה. להלן תיאור הפונקציה ששמורת את הנתונים לקובץ. קלט: מצביע לעץ מוצרים T ומחרוזת מחרוזתFN (שם של קובץ) פעולת הפונקציה: פותחים קובץ בשם FN לכתיבה וכותבים לתוכו את תוני העץ, מוסדרים לפי סידור לקסיקוגרפי על שם המוצרים פלט: void חתימה: *fn) void savestore(producttree *t, char )1
הערות חשובות: ניתן להגיש תרגיל זה בזוגות )מציאת בן זוג אידיאלי באחריותכם )ככה זה בחיים (( מצורף קובץ שלד עליו עליכם להוסיף את קטעי הקוד הרלוונטיים, אין להגדיר מערכים, מלבד מחרוזות עזר )מערך חד ממדי של,)char ניתן להגדיר פונקציות עזר כרצונכם. אין לשנות את המבנים והפונקציות שהגדרנו לכם, אך ניתן להגדיר רשימות ועצים נוספים כרצונכם. תרגיל אותו לא ניתן להדר (לקמפל( או להריץ (בד"כ בשל חריגה מגבולות הזיכרון( יקבל ציון נכשל. בדקו שעבודתכם רצה גם ב- debug וגם ב-,release לפני הגשתה, כישלון בניסיון להריצה באחד מהמצבים נובע משגיאה קריטית בתוכנית (שוב בד"כ קשור לחריגה מגבולות זיכרון( לכן נסו לגלות זאת לפני הבודקים. יש להגיש קובץ יחיד שנקרא ID1_ID2.zip ובתוכו חמשת הקבצים שקיבלתם לעבודה. =ID מספר תעודת זהות. כל חשד להעתקה יועבר לטיפול וועדת משמעת, אנא אל תגרמו לנו להעביר שמות לוועדה זו, זה ממש לא כיף. שאלות הקשורות לתרגיל יש להפנות דרך הדואר האלקטרוני yoavfekete@gmail.com יש לוודא כי שאלה זו לא זכתה כבר להתייחסות ב- FAQ כותרת המייל חייבת להכיל את המחרוזת.IPC122 ASS3 ID הקפידו לרשום הערות ולפעול על פי הסטנדרטים המוגדרים במסמך Coding Standards המופיע באתר הקורס חלק מהניקוד של העבודה מוקדש לנושא זה. על הפלט שלכם להיות זהה לחלוטין לפלט של קובץ הדוגמא שסופק (כולל רווחים אותיות גדולות וכו'... בדקו זאת ע"י התוכנה (. txtdiff לכל פונקציות עזר שאתם כותבים חייבים להיות הערות. אל הערות להיות בפורמט זהה לזה של הפונקציות הקימות בקוד שקיבלתם. תיהנו ובהצלחה, פקטה יואב שאלות ותשובות: Q : Can I add more structs of my own? A : Yes. Q : Can I use functions from string.h? A : Yes. Q : Do I need to free memory I allocated using malloc? A : Yes. Q : What arrays am I allowed to use? A : You can use only 1 dimensional char array for names. No other arrays are allowed! You can (and should) use malloc to allocate dynamic 1 dimensional char arrays. Q : Can I use the function realloc()? A : No.