Presentation is loading. Please wait.

Presentation is loading. Please wait.

שאלות ממבחנים - ADT שאלות ממבחנים - C-Shell

Similar presentations


Presentation on theme: "שאלות ממבחנים - ADT שאלות ממבחנים - C-Shell"— Presentation transcript:

1 שאלות ממבחנים - ADT שאלות ממבחנים - C-Shell
תרגול מס' 14 שאלות ממבחנים - ADT שאלות ממבחנים - C-Shell

2 שאלות ממבחנים - ADT מבוא לתכנות מערכות

3 שאלה 1 (מועד ב', אביב 2006) מבני נתונים מופשטים - ADT (40 נקודות): לצורך בקרת כניסה למתקן סודי של המוסד הוחלט להקים מערכת המצלמת את פניהם של הבאים למתקן ומאפשרת את כניסתם רק במידה והפנים זוהו כפנים של אחד העובדים. לכל עובד יש שם ומספר ת"ז (ייחודי). בעת התקנת המערכת יצולם כל אחד מהעובדים ממספר זוויות צילום שונות (יתכן מספר שונה של תמונות לכל עובד) והתמונות יישמרו במערכת. במנשק ומימוש המערכת נעזר ב-ADT בשם Image המייצג תמונה דיגיטאלית ותומך בין היתר בפעולות הבאות: imageCopy: הפונקציה מקבלת תמונה ומחזירה העתק שלה imageDestroy: משחררת את כל משאבי התמונה imagesSimilarity: מקבלת שתי תמונות ומחזירה מספר ממשי בין 0 ל- 1 המשקף את מידת הדמיון בין התמונות. ניתן להתייחס אל Image כאל "קופסא שחורה", אין צורך לתאר את מבנה הנתונים או המימוש שלו מבוא לתכנות מערכות

4 שאלה 1 (מועד ב', אביב 2006) סעיף א' (20 נקודות): ממשו את קובץ המנשק של המודול SurveillanceSystem או בקיצור SurSys. על המנשק לתמוך בפונקציות הבאות בלבד: CreateSurSys: יצירת SurSys. AddWorker: הוספת עובד חדש למערכת (הפונקציה מקבלת את שמו ות"ז שלו). AddWorkerImage: הוספת תמונה של עובד הקיים במערכת (מחזירה מספר סידורי לתמונה זו. מספר זה הנו ייחודי לעובד זה בלבד, אולם יתכן כי לעובדים אחרים ישנן תמונות עם מספר סידורי זהה) RemoveWorker: מחיקת עובד מהמערכת (כולל כל התמונות שלו) RemoveWorkerImage: מחיקת תמונה של עובד (על-פי ת"ז של העובד והמספר הסידורי של התמונה) GetWorkerImages: החזרת אוסף כל התמונות של עובד מסוים. CheckSimilarity: זיהוי עובד על סמך תמונה חדשה (הסבר בהמשך...) DestroySurSys: הריסת ה-SurSys. פונקציה מס' 7 מקבלת כפרמטר תמונה (Image) ומספר – threshold בין 0 ל- 1. על פונקציה זו להשוות את התמונה (ע"י שימוש בפונקציה imagesSimilarity) לכל תמונות העובדים שנשמרו במערכת. במידה ונמצאה תמונה שמידת הדמיון שלה גבוהה מה- threshold הפונקציה תחזיר ערך המשקף זיהוי מוצלח. אחרת, הפונקציה תחזיר ערך המשקף חוסר זיהוי. בנוסף, תחזיר הפונקציה בכל מקרה את ת"ז ושמו של העובד עבורו נמצא הדמיון הגדול ביותר. מבוא לתכנות מערכות

5 פתרון - סעיף א' #ifndef SURSYS_H #define SURSYS_H #include "image.h" #include <stdbool.h> typedef struct SurSys_t *SurSys; typedef enum {SUR_SYS_SUCCESS, SUR_SYS_FAIL, SUR_SYS_OUT_OF_MEMORY,...} SurSysResult; SurSys CreateSurSys(); // or SurSysResult CreateSurSys(SurSys *system); SurSysResult AddWorker(SurSys system, int id, const char* name); SurSysResult AddWorkerImage(SurSys system, int id, Image image, int* imageId); SurSysResult RemoveWorker(SurSys system, int id); SurSysResult RemoveWorkerImage(SurSys system, int id, int imageId); SurSysResult GetWorkerImages(SurSys system, int id, Image** images, int* imagesSize); SurSysResult CheckSimilarity(SurSys system, Image image, double threshold, bool* match, int* bestID, char** bestName); void DestroySurSys(SurSys system); #endif מבוא לתכנות מערכות

6 שאלה 1 (מועד ב', אביב 2006) סעיף ב' (20 נקודות):
סעיף ב' (20 נקודות): (8 נקודות) הציגו את מבנה הנתונים של SurSys כפי שיופיע בקובץ SurSys.c, עם כל ההגדרות הנלוות הנדרשות. אין צורך לממש אף פונקציה בסעיף זה. (9 נקודות) ממשו את פונקציה 7 מסעיף א' על פי מבנה הנתונים שבחרתם בסעיף ב' 1. על המימוש להיות נכון ויעיל. המימוש צריך לתאר את האלגוריתם העיקרי במלואו (בפונקציה אחת או יותר), אין צורך לממש פונקציות מנשק של ADTs בסיסיים וגם לא פונקציות מנשק אחרות של SurSys. (3 נקודות) ציינו 3 קודי שגיאה אפשריים שונים (ספציפיים ל-SurSys) המוחזרים ע"י פונקציות המנשק (אין לציין "בעיה בהקצאת זיכרון", וגם לא קודי שגיאה של ADT(s) בסיסיים). מבוא לתכנות מערכות

7 פתרון - סעיף ב' 1 #include "SurSys.h" #include "set.h" /* the struct of the ADT */ struct SurSys_t { Set workers; }; /* internal struct (not ADT) */ typedef struct Worker_t { int id; char* name; Set workerImages; } Worker; typedef struct WorkerImage_t { Image image; } WorkerImage; מבוא לתכנות מערכות

8 פתרון -סעיף ב' 2 SurSysResult CheckSimilarity(SurSys system, Image image, double threshold, bool* match, int* id, char** name) { if (system == NULL || match == NULL || id == NULL || name == NULL || image == NULL) return SUR_SYS_BAD_PARAM; if (threshold < 0 || threshold > 1) return SUR_SYS_INVALID_THRESHOLD; double maxSimilarity = 0.0; char* tempName = NULL; SET_FOREACH(Worker, worker, system->workers) { SET_FOREACH(WorkerImage, image, worker->workerImages) { double similarity = imagesSimilarity(image->image, image); if (similarity > maxSimilarity) { maxSimilarity = similarity; *id = worker->id; tempName = worker->name; } } } מבוא לתכנות מערכות

9 פתרון - סעיף ב' 2 - המשך if (tempName != NULL) { *name = malloc(strlen(tempName) + 1); if (*name == NULL) return SUR_SYS_OUT_OF_MEMORY; strcpy(*name, tempName); } *match = maxSimilarity > threshold; return SUR_SYS_SUCCESS; מבוא לתכנות מערכות

10 פתרון - סעיף ב' 3 קודי שגיאה אפשריים: SUR_SYS_INVALID_THRESHOLD
SUR_SYS_IMAGE_DOESNT_EXIST SUR_SYS_WORKER_ALREADY_EXISTS מבוא לתכנות מערכות

11 שאלה 2 ברשותנו הקובץ student.h המגדיר את המחלקה Student. מכיוון שבמחשב עליו אתם עובדים יש רק מהדר של C ולא של C++, עליכם לכתובADT בשםStudent שיכלול את אותה פונקציונליות כמו המחלקה Student. עליכם לחלק את הקוד בין שני קבציםstudent_adt.h ו-student_adt.c ולציין איזה חלק של הקוד יכלול כל קובץ. הניחו שמישהו אחר כבר כתב את course_adt.h ושקיים set.h מתאים אין צורך להקפיד על const correctness אין צורך לממש את הפונקציות מבוא לתכנות מערכות

12 שאלה 2 #ifndef STUDENT_H_ #define STUDENT_H_ #include "course.h" #include <set> class Student { enum { MAX_COURSES = 30 }; char* name; Course *courses[MAX_COURSES]; int numCourses; double calculateAverageGrade(); public: Student(const char*); ~Student(); void addCourse(const Course&); void removeCourse(const Course&); double getAverage() const ; const char* getName() const ; set<Course> getFailedCourses(); bool isHonorsStudent() const ; friend bool operator<(const Student&, const Student&); // order by name class NoCoursesException {}; // the student has no courses yet class HasAllCoursesException {}; // the student has MAX_COURSES courses class CourseExistsException {}; // the student already took the course class CourseMissingException {}; // the student is not registered to the course }; #endif /* STUDENT_H_ */ מבוא לתכנות מערכות

13 שאלה 2 – student_adt.h #ifndef STUDENT_H_ #define STUDENT_H_ #include "course_adt.h" #include "set.h" typedef struct student_t* Student; typedef enum { STUDENT_SUCCESS, STUDENT_NULL_ARG, STUDENT_OUT_OF_MEMORY, STUDENT_NO_COURSES, STUDENT_HAS_ALL_COURSES, STUDENT_COURSE_EXISTS, STUDENT_COURSE_MISSING } StudentResult; Student studentCreate(const char*); void studentDestroy(Student); StudentResult studentAddCourse(Student, Course); StudentResult studentRemoveCourse(Student, Course); StudentResult studentGetAverage(Student, double* result); const char* studentGetName(Student); StudentResult studentGetFailedCourses(Student, Set* result); bool studentIsHonored(Student); int studentCompare(Student, Student); #endif /* STUDENT_H_ */ מבוא לתכנות מערכות

14 שאלה 2 – student_adt.c #include "student_adt.h" #define MAX_COURSES 30
struct student_t { char* name; Course *courses[MAX_COURSES]; int numCourses; }; מבוא לתכנות מערכות

15 שאלה 3 נתון מימוש פשוט של רשימה מקושרת (דו-כיוונית) של מספרים שלמים (int) תזכורת: ברשימה דו-כיוונית לכל צומת יש שני מצביעים - אחד לצומת שאחריו ואחר לצומת אשר לפניו. אם לא קיים כזה צומת אזי המצביע מכיל NULL. typedef struct node_t *Node; struct node_t { int n; Node next; Node previous; }; כיתבו פונקציה המקבלת רשימה מקושרת שכזו ומסירה ממנה צמתים כך שכל מספר שהופיע ברשימה לפני הרצת הפונקציה מופיע בדיוק פעם אחת ברשימה לאחר הרצת הפונקציה למשל הרשימה ( ) תהפוך ל-(1 2 3) לאחר הרצת הפונקציה הערות: אין צורך לשמור על סדר כלשהו ברשימה ניתן להניח כי כל הצמתים של הרשימה הוקצו דינאמית ואינם בשימוש במקום אחר מבוא לתכנות מערכות

16 שאלה 3 - פתרון void removeByValue(Node head, int n) { for(Node ptr = head; ptr ; ptr = ptr->next) { if (ptr->n != n) { continue; } if (ptr->previous) { ptr->previous->next = ptr->next; if (ptr->next) { ptr->next->previous = ptr->previous; Node tmp = ptr; ptr = ptr->previous; free(tmp); Node removeDuplicates(Node head) { for(Node ptr = head; ptr; ptr = ptr->next) { removeByValue(ptr->next, ptr->n); return head; דגשים: כל המקרים של ערכי NULL אפשריים ואינם מרסקים את הקוד (רשימה ריקה וכו') למרות שאין התייחסות נפרדת לאיברי הקצה ברשימה. מאחר ונרשם שהצמתים מוצבעים רק מתוך הרשימה והוקצו דינאמית עלינו לשחרר אותם בזמן הוצאתם מהרשימה כדי להימנע מדליפות זיכרון. הפונקציה הראשית מחזירה את ראש הרשימה החדש, למרות שהוא אינה משתנה בשיטת העבודה שלנו. הבדיקה if(ptr->previous) אינה הכרחית עבור הקריאות שלנו ל-removeByValue אך למען הכלליות הפונקציה היא הוספה גם. מבוא לתכנות מערכות

17 שאלה 4 נתון פונקציה גנרית (טמפלייט) למיון מערך:
template <class T> void bubble_sort(T* array, int size) { for(int i = 0; i < size; i++) { for(int j = 0; j < size - 1; j++) { if (array[j+1] < array[j]) { T temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } } מסתבר שבמחשב שברשותנו יש רק מהדר שלC ולא של C++, ועלינו להחליף את כל הקוד הגנרי בC++- בקוד גנרי שיעבור הידור ב-C. כיצד תראה הפונקציה הגנרית הממיינת מערך ב-C? שימו לב שהפונקציה אמורה להתאים לכל טיפוס שניתן למיון ולא רק לטיפוסים בסיסיים. הסבירו כל פרמטר שהפונקציה מקבלת. מבוא לתכנות מערכות

18 שאלה 4 - פתרון פירוש הפרמטרים לפונקציה:
void bubble_sort(void** array, int size, int (*compare)(void*, void*)) { for(int i = 0; i < size; i++) { for(int j = 0; j < size - 1; j++) { if (compare(array[j+1],array[j]) > 0) { void* temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } פירוש הפרמטרים לפונקציה: array הוא מערך העצמים כאשר כל איבר הוא מצביע לעצם כלשהו size הוא גודל המערך compare הוא מצביע לפונקציה המשווה בין שני עצמים ומחזירה מספר המייצג את הסדר ביניהם (כמו strcmp עבור מחרוזות למשל) התחביר הבא גם מתאים: void bubble_sort(void** array, int size, int compare(void*, void*)) מבוא לתכנות מערכות

19 שאלה 4 - המשך נניח שמוגדר הטיפוס הבא המכיל נתוני סטודנט:
struct student_t { int id; char *name; }; typedef student_t* Student; אנו רוצים למיין סטודנטים לפי מספר ת"ז שלהם. מה צריך להגדיר עבור הטיפוס הזה כדי שניתן יהיה להשתמש בפונקציה שכתבנו למיון מערך של סטודנטים? כתבו את הקריאה לפונקצית המיון ואת הקוד הנדרש כך שקריאה זו תתקמפל. מבוא לתכנות מערכות

20 שאלה 4 - פתרון עלינו לממש פונקצית השוואה מתאימה אשר משווה סטודנטים לפי מספר ת"ז שלהם: int studentCompare(void* a, void* b) { Student student1 = a; Student student2 = b; return student1->id - student2->id; } הקריאה לפונקציה (בהינתן מערך וגודלו) תיראה כך: bubble_sort(array, n, studentCompare); מבוא לתכנות מערכות

21 שאלות ממבחנים - C-Shell
מבוא לתכנות מערכות

22 שאלה 1 למשה יש מאגר גדול של מסמכים תחת התיקיה docs ובמשך עבודתו הוא צריך פעמים רבות למצוא את כל המסמכים תחת docs המכילים מילה מסוימת. בכל השאלה יש להניח שאנו ממוקמים בתיקית האב של התיקיה docs. סעיף א': כתבו פקודת טרמינל יחידה (ניתן להשתמש ב-pipeline) אשר מציגה את שמות הקבצים השונים בתיקיה docs המכילים את המילה "banana" כמילה עצמאית (לא תת מילה). אם אין כאלו קבצים הפקודה אינה מדפיסה כלום. בסעיף זה אין להשתמש בדגל -l של הפקודה grep. ניתן להניח שתחת התיקיה docs קיימים מספר קבצים. grep "banana" -w docs/* | cut -d":" -f1 | uniq אין צורך במיום לפני הקריאה ל-uniq מאחר והפלט של grep הוא לפי קבצים. מבוא לתכנות מערכות

23 שאלה 1 - המשך מסתבר שבגלל ריבוי המסמכים ביצוע הפקודה שהצעתם בסעיף א' לוקח יותר מדי זמן (משה לא ידוע בסבלנותו) ולכן משה חשב על הפתרון הבא: במקום לחפש את המילה בכל המסמכים בכל פעם מחדש, משה יכתוב תסריט אשר יוצר אינדקס שיאפשר חיפוש מהיר. לאחר קצת חשיבה משה החליט לממש את האינדקס כך: ליצור את התיקיה index לכל מילה אשר מופיעה בלפחות מסמך אחד ב-docs יווצר קובץ בשמה תחת התיקיה index אשר יכיל את רשימת הקבצים בהם היא מופיעה למשל, אם המילה "apple" מופיעה ב-3 מסמכים ב-docs: fruits.txt, monkies.txt ו-juices.txt אז תחת התיקיה index יווצר קובץ בשם apple אשר תוכנו יהיה: monkies.txt fruits.txt juices.txt סעיף ב': בהינתן אינדקס שכזה תחת התיקיה index, כתבו את הפקודה החדשה להצגת שמות הקבצים השונים המכילים את המילה "banana" כמו בסעיף א' if (-f docs/banana) cat docs/banana מבוא לתכנות מערכות

24 שאלה 1 - המשך כתבו את התסריט make-index אשר בונה את התיקיה index כך שתכיל קובץ לכל מילה המופיעה במסמך כלשהו בתיקיה docs. ניתן להניח שכל המסמכים נמצאים ישירות תחת התיקיה docs (והיא אינה מכילה תיקיות נוספות) #!/bin/tcsh -f mkdir index foreach f (docs/*) cat $f | addToIndex $f end make-index #!/bin/tcsh -f set line=($<) while($#line > 0) foreach word ($line) if (! -f index/$word || `grep $1 index/$word` == "") then echo $1 >>! index/$word endif end add_to_index מבוא לתכנות מערכות

25 שאלה 2 הינכם נדרשים לכתוב תסריט בשם create_makefile אשר מייצר קובץ Makefile בצורה אוטומטית יש להניח כי בספריית העבודה קיימים רק קבצי קוד מקור בשפת C (*.h, *.c) יש להניח כי הקבצים מבצעיםinclude בצורה תקינה ושאין שגיאות תחביר בקבצים שם המטרה הראשית (קובץ ההרצה) ינתן כפרמטר לתסריט מומלץ להשתמש בתסריטי עזר אין להשתמש בקבצים זמניים הקובץ שיווצר צריך לעמוד במספר כללים אשר מפורטים בדוגמה ובהמשך מבוא לתכנות מערכות

26 שאלה 2 דוגמה: בספריית העבודה קיימים 4 קבצים – a.c, a.h, b.c, b.h אשר תוכנם נתון להלן עבור הפרויקט הנתון הרצת הפקודה create_makefile prog תיצור קובץ בשם Makefile בעל התוכן הבא. שימו לב כי הינכם נדרשים להגדיר מאקרו עבור הקומפיילר ועבור רשימת קבצי האובייקט. בקובץ הפלט תהיה מטרה עבור כל קובץ ובנוסף מטרה עבור קובץ ההרצה אשר שמה זהה לפרמטר שמועבר לתסריט. הנחייה: השתמשו בפלט של הפקודה gcc –MM *.c כדי ליצור שלד ממנו תיצרו את קובץ ה – Makefile. a.c: #include "a.h" int main() { return 0; } a.h: #include <stdio.h> b.c: #include "b.h" void f() { } b.h: #include "a.h" void f(); CC=gcc OBJS=a.o b.o prog: $(OBJS) $(CC) a.o b.o -o prog a.o: a.c a.h $(CC) -c a.c b.o: b.c b.h a.h $(CC) -c b.c מבוא לתכנות מערכות

27 שאלה 2 - פתרון create_makefile print_makefile #!/bin/tcsh -f
gcc -MM *.c | print_makefile $1 >! makefile create_makefile #!/bin/tcsh -f echo CC=gcc set objs=`gcc -MM *.c | cut -f1 -d":"` echo OBJS=$objs echo ${1}: '$OBJS' echo ' $(CC)' $objs -o $1 echo set line=($<) while($#line > 0) echo $line echo -n ' $(CC) -c' foreach f ($line[2-]) if ( $f ~= *.c ) echo -n $f end print_makefile מבוא לתכנות מערכות

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


Download ppt "שאלות ממבחנים - ADT שאלות ממבחנים - C-Shell"

Similar presentations


Ads by Google