Ex 3
Ex 3
                                                                                 1הערות כלליות
                                                                תרגיל זה מהווה  6%מהציון הסופי    •
                                                                     התרגיל להגשה בזוגות בלבד.    •
 מענה לשאלות בנוגע לתרגיל יינתן אך ורק בפורום התרגיל בפיאצה או בסדנות .לפני פרסום שאלה בפורום     •
אנא בדקו אם כבר נענתה – מומלץ להיעזר בכלי החיפוש שהוצגו במצגת האדמיניסטרציה בתרגול הראשון.
         שימו לב :לא תינתנה דחיות במועד הגשת התרגיל פרט למקרים חריגים .תכננו את הזמן בהתאם.       •
    ראו את התרגיל עד סופו לפני תחילת המימוש .חובה להתעדכן בעמוד ה F.A.Q-של התרגיל ,הכתוב שם       •
                                                                                         מחייב.
החומר הרלוונטי על תבניות ( )templatesשישמש אתכם בחלק  4ילמד בהרצאות ובתרגולים עד סוף שבוע         •
     .8ניתן להתחיל מלממש את התור עבור טיפוס ספציפי (למשל  )intולשנות את המימוש לתבניתי בשלב
                                                                                    יותר מאוחר.
    העתקות קוד בין סטודנטים ובפרט גם העתקות מסמסטרים קודמים תטופלנה .עם זאת – מומלץ ומבורך        •
                                                      להתייעץ עם חברים על ארכיטקטורת המימוש.
               קבצי התרגיל נמצאים ב GitHub repositoryהבאhttps://github.com/CS234124/ex3 :         •
                                    המסמך נכתב בלשון זכר מטעמי נוחות בלבד ומיועד לשני המינים.     •
                        טכניון – מכון טכנולוגי לישראל     הפקולטה למדעי המחשב
                                                                            HealthPoints 3
בחלק זה נממש מחלקה שתייצג לנו נקודות חיים ) (HPשל שחקן במשחק .נקודות החיים של שחקן הן מספר
                                       שלם בין  0לכמות נקודות מקסימלית האפשריות לאותו שחקן.
                                                                         3.1ממשק HealthPoints
                                                        בחלק זה נגדיר את ממשק המחלקה .HealthPoints
                                                                                     3.1.1בנאי
מייצר אובייקט המייצג נקודות חיים עם מספר מקסימלי של נקודות המתקבל כפרמטר .במידה ולא מסופק מספר
                                                            מקסימלי ,ערך ברירת המחדל הינו .100
כמות הנקודות ההתחלתית של האובייקט שווה למספר הנקודות המקסימלי של אותו מופע.
             אם מועבר לבנאי מספר שלילי או  ,0יש לזרוק חריגה מסוג .HealthPoints::InvalidArgument
HealthPoints healthPoints1; /* has 100 points out of 100 */
HealthPoints healthPoints(150); /* has 150 points out of 150 */
{ try
        ;)HealthPoints healthPoints3(-100
}
{ )catch (HealthPoints::InvalidArgument& e
        /* some code... */
}
                                                                  3.1.2אופרטורים אריתמטיים
 נגדיר אופרטור חיבור ואופרטור חיסור .ניתן לחבר ולחסר מופעים של  HealthPointsעם מספרים שלמים מסוג
 .intהמספר אותו נחבר או נחסר מהאובייקט יתווסף או יוחסר מכמות הנקודות הנוכחית של האובייקט .בכל מקרה
כמות הנקודות הנוכחית לא תעלה על המקסימלית ולא תרד מתחת ל .0-לא ניתן לחבר או לחסר שני אובייקטים
                                                                                       אחד עם השני.
בנוסף לחיבור וחיסור ( )- ,+נגדיר גם אופרטורים = +ו -= -הפועלים באותו אופן ומבצעים השמה לאובייקט עליו
                                                                                             פועלים.
healthPoints1   -= 20; /* now has 80 points out of 100 */
healthPoints1   +=100; /* now has 100 points out of 100 */
healthPoints1   -= 150; /* now has 0 points out of 100 */
healthPoints2   = healthPoints2 - 160; /* now has 0 points out of 150 */
healthPoints2   = 160 + healthPoints1; /* now has 100 out of 100 */
                         טכניון – מכון טכנולוגי לישראל     הפקולטה למדעי המחשב
                                                                     אופרטורים בוליאניים3.1.3
 שני מופעים נחשבים שווים זה לזה.!= -לשם השוואה בין מופעים של המחלקה נגדיר עבורה את האופרטורים == ו
. <, <=, >, >= : בנוסף נגדיר אופרטורי יחס עבור המחלקה.אם ורק אם כמות נקודות החיים הנוכחית שלהם שווה
                . אופרטורים אלו משווים בין הכמות הנקודות הנוכחית של שני אובייקטים,כמו אופרטורי ההשוואה
bool comparisonResult;
HealthPoints healthPoints1(100);
HealthPoints healthPoints2 = 100; /* 100 points out of 100 */
comparisonResult = (healthPoints1 == healthPoints2); /* returns true */
healthPoints2 = HealthPoints(150); /* has 150 points out of 150 */
comparisonResult = (healthPoints1 == healthPoints2); /* returns false */
healthPoints2 -= 50; /* now has 100 points out of 150 */
comparisonResult = (100 == healthPoints2); /* returns true */
comparisonResult = (healthPoints1 < healthPoints2); /* returns false */
healthPoints1 -= 50; /* now has 50 points out of 100 */
comparisonResult = (healthPoints1 < healthPoints2); /* returns true */
                                                                           אופרטור הדפסה3.1.4
 בדומה,ostream- נגדיר עבורה אופרטור הדפסה ל,על מנת להדפיס מופעים של המחלקה בצורה נוחה
             .<currentValue>(<maxValue>)  פורמט ההדפסה הינו.למה שראינו בהרצאות ובתרגולים
std::cout << healthPoints1 << ", " << healthPoints2;
/* output is "50(100), 100(150)" */
                         טכניון – מכון טכנולוגי לישראל         הפקולטה למדעי המחשב
                                                                                            Queue 4
                      בחלק זה תדרשו לממש מבנה נתונים שנקרא תור ( )Queueאשר יוכל לשמש אותנו בהמשך
                                                      כדי לנהל חפיסת קלפים ,ואת תור שחקני המשחק.
                                                                               4.2ממשק של QUEUE
בחלק זה נגדיר את הפעולות בהם הממשק של התור יתמוך .פעולות אלו צריכות לתמוך בכל דוגמאות הקוד המופיעות
                                                                                         במסמך זה.
                                                                                  pushBack 4.2.1
                הפעולה  pushBackמכניסה איבר חדש לסוף התור .שימו לב שנישמר עותק של האיבר החדש.
;Queue<int> queue1
;)queue1.pushBack(1
;)queue1.pushBack(2
                                                                                        front 4.2.2
                                                           הפעולה  frontמחזירה לנו את האיבר הראשון בתור.
int front1 = queue1.front(); /* front1 equals 1 as its the first value */
queue1.front() = 3; /* queue1 content is: 3, 2 (left to right) */
front1 = queue1.front(); /* front1 now equals 3 */
                                                                                   popFront 4.2.3
                                                         הפעולה  popFrontמוציאה את האיבר הראשון מהתור.
;)(queue1.popFront
                                                                                         size 4.2.4
                                                הפעולה  sizeמחזירה את כמות האיברים שנמצאים כרגע בתור.
;)(int size1 = queue1.size
                                                                                   filter 4.2.5
הפעולה  filterמקבלת תנאי מסויים ומסננת את איברי התור על פיו .התנאי (פרדיקט) מובא ע״י אובייקט עם
אופרטור סוגריים (מצביע לפונקציה או  )Function Objectהמקבל איבר ומחזיר ערך בוליאני עבורו.
    הפונקציה  filterתחזיר תור חדש בו נמצאים כל איברי התור המקורי עבורם מתקבל  trueבהפעלת הפרדיקט.
)static bool isEven(int n
{
        ;return (n % 2) == 0
}
)(int main
{
        /* some code... */
        ;Queue<int> queue3
        { )for (int i = 1; i <= 10; i++
                ;)queue3.pushBack(i
        }
        ;)Queue<int> queue4 = filter(queue3, isEven
        /* now queue4 contains: 2, 4, 6, 8, 10 (left to right) */
}
שימו לב – בשונה ממה שראיתם בהרצאה עבור המחלקה  Setבהרצאה ,הפונקציה  filterאינה מתודה של
                                                         המחלקה  Queueאלא פונקציה חיצונית.
                                                                            Transform 4.2.6
הפעולה  transformעוברת על כל איברי התור ומשנה אותם ) (In-placeע״י אופרציה נתונה .האופרציה המבוצעת
על כל אחד מהאיברים נתונה על ידי אובייקט עם אופרטור סוגריים (מצביע לפונקציה או  )Function Objectהמקבל
איבר מהתור ומשנה אותו .הפעולה  transformמשנה את התור שקיבלה בכך שתפעיל על כל אחד מהאיברים את
                                                                                           האופרציה.
)static void setFortyTwo(int& n
{
        ;n = 42
}
)(int main
{
        /* some code... */
        ;Queue<int> queue5
        { )for (int i = 1; i <= 5; i++
                ;)queue5.pushBack(i
        }
        ;)transform(queue5, setFortyTwo
        /* now queue5 contains: 42, 42, 42, 42, 42 */
        /* some more code... */
}
      שימו לב – האופרציות ש transform-מקבלת משנות את האיבר שמקבלות כארגומנט ואינן מחזירות ערך.
                        טכניון – מכון טכנולוגי לישראל       הפקולטה למדעי המחשב
                                                                                4.2.7איטרטורים
נגדיר איטרטור בכדי לבצע איטרציה על איברי התור .האיטרטור יתמוך בממשק מינימלי כפי שראיתם בהרצאה
בעזרת האופרטורים != ,++ :ו .*-כמו כן נגדיר לתור פעולות  beginו  endהמחזירות איטרטורים לתחילת התור
                                                                                      ולסופו בהתאמה.
שימו לב  -האיטרטור המוחזר מ end-אינו מצביע לאיבר האחרון בתור אלא מצביע "אחרי האיבר האחרון" .למשל
  במקרה של תור ריק ,אין איבר אחרון שהתור יכול להצביע עליו .לאיטרטור המוחזר לא ניתן לבצע .Dereference
כל שינוי של התור (דחיפה\ הוצאה וכו' )...הופכת את כל האיטרטורים הקיימים של אותו תור ללא חוקיים .שימוש
      באיטרטור לא חוקי גורר התנהגות לא מוגדרת ולא יבדקו מקרים מסוג זה בבדיקות האוטומטיות של התרגיל.
{ )for (Queue<int>::Iterator i = queue5.begin(); i != queue5.end(); ++i
        /* some code... */
}
                                                                                            4.3חריגות
על מנת להתמודד עם שגיאות נרצה להשתמש בחריגות .בתור שלנו נגדיר שני סוגי חריגות עבור שגיאות אפשריות
                                                                                של התור והשימוש בו.
שימו לב – ניתן להפעיל את  transformואת  filterעל תור ריק ,אין צורך לזרוק חריגה במקרה זה.
                                                                           4.4הערות על הממשק
                                                על הממשק יתמוך בתור קבוע ) (constולא קבוע.     •
                                      מסופק עבורכם קובץ בדיקה בשם .QueueExampleTest.cpp        •
                    ממשק התור צריך לתמוך בכל דוגמאות השימוש המובאות במסמך ובקבצי הבדיקה.       •
                                                                           4.5מימוש של Queue
                                                         אין להשתמש ב STL-לשם מימוש התור.      •
                                    על המימוש לעמוד בקונבנציות הקוד המפורטות באתר הקורס.       •
       מותר להגדיר פונקציות עזר לשם מימוש התור ללא הגבלה ,כל עוד הן לא משנות את ממשק התור.     •
                                 אין להגדיר מחלקות או מתודות חברות ( )friendאם אין בכך צורך.   •
במימוש הפנימי של התור ניתן ואף כדאי להשתמש באלמנטים של הממשק אותו אתם נדרשים לממש (למשל        •
                                                                                איטרטורים).
                        טכניון – מכון טכנולוגי לישראל     הפקולטה למדעי המחשב
                                                                                      5חלק יבש
  בחלק זה מספר שאלות הנוגעות לממשק התור ולשימושים בו .עליכם לענות על השאלות בקובץ הנקרא .dry.pdf
א .על מנת לאפשר איטרציה על תור קבוע ( ,)constהממשק מאפשר לנו שימוש ב ConstIterator-בנוסף
       לאיטרטור הרגיל של התור .מדוע לא ניתן להסתפק בלהגדיר את פעולות האיטרטור הרגיל כ?const-
ב .באילו מהפונקציות בממשק התור קיימות הנחות על הטיפוס הטמפלייטי? עבור כל אחת מהפונקציות הללו
                                                                          פרטו את הנחות.
ג .סטודנט בקורס מבוא לתכנות מערכות שכח מהאזהרות שקיבל בתרגול ומימש את המחלקה  Queueבקובץ
 cppבמקום בקובץ  .hמהי השגיאה שיקבל כאשר ינסה לקמפל את התרגיל ובאיזה משלבי הקומפילציה היא
                                                                                מתרחשת?
ד .סטודנטית בקורס מבוא לתכנות מערכות סיימה לפתור את תרגיל בית  ,3והחליטה להשתמש במימוש התור
מהתרגיל לפרוייקט צד שהיא מפתחת בשעות הפנאי .במימוש פרוייקט הצד הסטודנטית נדרשה לסנן תור של
מספרים שלמים ,כך שישארו בתור רק מספרים המתחלקים במספר כלשהו שאינו ידוע בזמן קומפילציה אלא
              רק בזמן ריצה .הסבירו כיצד ניתן לממש את הפונקציונליות הדרושה בעזרת הפונקציה .filter
                                                                                 6הגשת התרגיל
                                                                           6.1הידור קישור ובדיקה
                           החלק הרטוב בתרגיל ייבדק על שרת  csl3ועליו לעבור הידור בעזרת הפקודה הבאה:
> g++ --std=c++11 -o ex3_test -Wall -pedantic-errors -Werror -DNDEBUG *.cpp
לנוחיותכם ,מסופקת לכם תוכנית "בדיקה עצמית" בשם , finalCheckהתוכנית בודקת שקובץ ההגשה ,קובץ הzip-
         ,בנוי נכון ומריצה את הטסטים שסופקו כפי שירוצו על ידי הבודק האוטומטי .הפעלת התוכנית ע"י הפקודה:
~mtm/public/2223a/ex3/finalCheck <submission>.zip
              הקפידו להריץ את הבדיקה על קובץ ההגשה .אם אתה משנים אותו ,הקפידו להריץ את הבדיקה שוב.
                                                                                 6.3בדיקת התרגיל
החלק היבש של התרגיל יבדק ידנית .הקוד שתכתבו בחלקים  3ו 4-יעבור בדיקה רטובה ובנוסף יעבור בדיקה יבשה
של הקוד על מנת להעריך את איכות הקוד (שכפולי קוד ,קוד מבולגן ,קוד לא ברור ,שימוש בטכניקות תכנות "רעות").
בדיקה רטובה כוללת את הידור התכנית המוגשת והרצתה במגוון בדיקות אוטומטיות .על מנת להצליח בבדיקה שכזו,
                     על התוכנית לעבור הידור ,לסיים את ריצתה ,ולתת את התוצאות הצפויות ללא דליפות זיכרון.
                                                                                          6.4הגשה
                                                               את ההגשה יש לבצע דרך אתר הקורס ,תחת
Assignments -> HW3 -> Electronic Submit.
                                                                                הקפידו על הדברים הבאים:
                                     • יש להגיש את קבצי הקוד יחד עם קובץ תשובות לחלק היבש
                                                                מכווצים לקובץ ( zipלא פורמט אחר).
                                      • אין להגיש אף קובץ מלבד פתרון לחלק היבש ,קבצי  hוקבצי cpp
                                                                            אשר כתבתם בעצמכם.
                                              • את הפתרון לחלק היבש ניתן יש להגיש כקובץ  pdfבלבד.
  • הקבצים אשר מסופקים לכם יצורפו על ידנו במהלך הבדיקה ,וניתן להניח כי הם יימצאו בתיקייה הראשית.
                                  • ניתן להגיש את התרגיל מספר פעמים ,רק ההגשה האחרונה נחשבת.
• על מנת לבטח את עצמכם נגד תקלות בהגשה האוטומטית שימרו את קוד האישור עבור ההגשה .עדיף לשלוח
גם לשותף .כמו כן שימרו עותק של התרגיל על חשבון ה Google Drive/Github/CSL3-שלכם לפני ההגשה
האלקטרונית ואל תשנו אותו לאחריה (שינוי הקובץ יגרור שינוי חתימת העדכון האחרון) .כל א מצעי אחר לא
                                                             יחשב הוכחה לקיום הקוד לפני ההגשה.
בהצלחה!