260 likes | 458 Views
תרגול מס' 13. שאלות ממבחנים - C++. שאלה 1. בשאלה זאת עליכם לסייע בכתיבת תוכנית לניהול צי רכב של חברת השכרה.
E N D
תרגול מס' 13 שאלות ממבחנים - C++
שאלה 1 • בשאלה זאת עליכם לסייע בכתיבת תוכנית לניהול צי רכב של חברת השכרה. • סעיף א' (10 נקודות): עליכם לכתוב 3 מחלקות (ממשקים ומימושים) עבור 3 סוגי מכוניות שהחברה משכירה: Sedan (מכונית פרטית), Truck (מסחרית), ו- AllTerrain (רכב שטח), כולן יורשות ממחלקת בסיס אבסטרקטית משותפת Car (שגם אותה יש לכתוב). דרישות: • לכל מכונית יש מספר רישוי ייחודי • לכל מכונית ניתן לדעת אם היא פנויה או בהשכרה אצל לקוח, וניתן לשנות מצב זה מבחוץ. • ניתן להשוות מכוניות לפי מספר הרישוי • כל אובייקט מכונית יוכל להכין מעצמו עותק, באמצעות פונקצית מחלקה Clone, גם אם טיפוס האובייקט ידוע רק בזמן ריצה (כלומר – פולימורפיזם). הפונקציה תחזיר את כתובת המכונית החדשה. מבוא לתכנות מערכות - 234122
פתרון • classCar { • intserNum; • boolvacant; • public: • Car(intsn) : • serNum(sn), vacant(true) {} • virtual~Car() {} • booloperator==(constCar &car) const { • returnserNum == car.serNum; • } • voidRent() { vacant = false; } • voidReturn() { vacant = true; } • boolIsVacant() const{returnvacant; } • virtualCar* Clone() const = 0; • }; מבוא לתכנות מערכות - 234122
פתרון • classSedan: publicCar{ • public: • Sedan(intnum) : Car(num) {} • virtualCar* Clone() const { returnnew Sedan(*this); } • }; • classTruck: publicCar{ • public: • Truck(intnum) : Car(num){} • virtualCar* Clone() const { returnnew Truck(*this); } • }; • classAllTerrain: publicCar{ • public: • AllTerrain(intnum) : Car(num){} • virtualCar* Clone() const { returnnewAllTerrain(*this); } • }; מבוא לתכנות מערכות - 234122
שאלה 1 - המשך • סעיף ב' (10 נקודות): נתונה המחלקה Customer (לקוח) שהממשק שלה: classCustomer{ stringname; intid; constCar *pRentedCar; public: Customer(conststring& n, int i); voidRentCar(constCar& car); voidReturnCar(); }; • עליכם לכתוב ממשק למחלקה Branch (סניף של החברה). אין צורך לממש את המחלקה Customer. מבוא לתכנות מערכות - 234122
שאלה 1 - המשך • דרישות: • כל סניף יחזיק מערך של כלי הרכב שברשותו. המערך יכלול כלי רכב מכל 3 הסוגים. מספר כלי הרכב המקסימלי בסניף נתון ע"י קבוע. • לכל סניף יש שם ומספר סידורי. • כל סניף יוכל: הנחיות נוספות: • עבור הדרישות הנ"ל, פרט לדרישה 1, אם כלי הרכב הנדון לא נמצא בסניף, יש להתריע על כישלון הפעולה. • אם לא ניתן להוסיף מכונית מפאת חוסר מקום, הפונקציה המתאימה צריכה להתריע על כישלון הפעולה. • עבור כל אחת מהדרישות, הפונקציה המתאימה צריכה להיות יחידה, כלומר, אמורה לטפל בכל שלושת טיפוסי כלי הרכב • כל הדרישות הנ"ל ימומשו ע"י פונקציות מחלקה. • לבדוק אם כלי רכב נתון פנוי. אם כלי הרכב לא ברשימה, זה ייחשב כאילו הוא אינו פנוי. • לקבל כלי רכב חדש - הפונקציה המתאימה תיצור עותק של כלי הרכב • להוציא כלי רכב מהמלאי • להעביר כלי רכב לסניף אחר • לקבל כלי רכב מסניף אחר • להשכיר כלי רכב ללקוח • להחזיר כלי רכב מלקוח • ניתן לבנות סניף חדש בעזרת שם הסניף ומספרו מבוא לתכנות מערכות - 234122
פתרון • classBranch { • staticconstintMAX_CARS = 100; • Car* cars[MAX_CARS]; • stringname; • intnumber; • public: // functionality • Branch(stringname,int number); // 8 • ~Branch(); • boolisCarVacant(constCar& car) const; // 1 • voidaddCar(constCar& car); // 2 • voidremoveCar(constCar& car); // 3 • voidtransferTo(Branch& branch, constCar& car); // 4 • voidtransferFrom(Branch& branch, constCar& car); // 5 • voidrentCar(Customer& customer, Car& car); // 6 • voidreturnCar(Customer& customer, Car& car); // 7 • }; • classBranchException : publicexception {}; מבוא לתכנות מערכות - 234122
שאלה 1 - המשך • סעיף ג' (20 נקודות): יש לממש את הפונקציות האחראיות לפעולות 2) , 4), 5), 6), ו 8) • הנחיות: • יתכן צורך להגדיר משתני עזר ו/או פונקציות עזר נוספות במחלקות השונות. אם מגדירים פונקצית עזר, אין צורך לממש אותה, אלא רק לכתוב אב-טיפוס ולהסביר מה היא עושה. • אין להגדיר פונקציות או משתני מחלקה שלא מתחייבים מהדרישות, או מהנחייה 1) • אין להשתמש במבנים מ STL (פרט, אולי, ל-string) מבוא לתכנות מערכות - 234122
הוספת פונקציות עזר וחריגות נוסיף למחלקה שתי פונקציות עזר ואת הגדרת החריגות המדויקות שנזדקק להן במימוש • class Branch { • staticconstintMAX_CARS = 100; • Car* cars[MAX_CARS]; • stringname; • intnumber; • intfindCarIndex(constCar& car); • boolcontains(constCar& car); • intfindEmptySlot(); • //... • }; • classCarAlreadyInBranch: publicBranchException {}; • classCarNotFound: publicBranchException {}; • classBranchFull: publicBranchException {}; • classCarNotRented: publicBranchException {}; • classCarAlreadyRented: publicBranchException {}; מבוא לתכנות מערכות - 234122
מימוש פונקציות העזר בזכות השימוש בחריגות בפונקציות העזר פונקציות הקוראות להן לא יצטרכו לבדוק את ערך החזרה עבור מקרי קצה • intBranch::findCarIndex(constCar& car) { • for (int i = 0; i < MAX_CARS; i++) { • if (cars[i] && *cars[i] == car) { • return i;}}throwCarNotFound()}boolBranch::contains(constCar& car) { • try { • findCarIndex(car); • returntrue; • } catch (CarNotFound&) { • returnfalse;}}intBranch::findEmptySlot() { • for (int i = 0; i < MAX_CARS; i++) { • if (!cars[i]) { • return i;}}throwBranchFull();} נחסך הצורך בשימוש בערכי מספרים מיוחדים עבור מצביע השגיאה מבוא לתכנות מערכות - 234122
פתרון 8) ניתן לבנות סניף חדש בעזרת שם הסניף ומספרו • Branch::Branch(string name, int number) • : name(name), number(number) { • for (int i=0; i<MAX_CARS; i++) { • cars[i] = NULL; • } • } • voidBranch::addCar(constCar& car) { • if (contains(car)){ • throwCarAlreadyInBranch(); • } • int index = findEmptySlot(); • cars[index] = car.Clone(); • return; • } 2) לקבל כלי רכב חדש - הפונקציה המתאימה תיצור עותק של כלי הרכב מבוא לתכנות מערכות - 234122
פתרון • voidBranch::transferTo(Branch& branch, constCar& car) { • removeCar(car); • branch.addCar(car); • } • voidBranch::transferFrom(Branch& branch, constCar& car) { • branch.transferTo(*this, car); • } • voidBranch::rentCar(Customer& customer, Car& car) { • int index = findCarIndex(car); • if (!isCarVacant(car)) { • throwCarAlreadyRented(); • } • cars[index]->Rent(); • customer.RentCar(car); • } 4) להעביר כלי רכב לסניף אחר 5) לקבל כלי רכב מסניף אחר 6) להשכיר כלי רכב ללקוח מבוא לתכנות מערכות - 234122
שאלה 2 • עליכם לממש מחלקות גנריות עבור "מערכים בטוחים". מערך בטוח הוא מערך המכיל מידע על אורכו, המאפשר הגנה מפני גלישה בשימוש. הגנריות מתבטאת בעובדה שהמימוש מאפשר ליצור מערכים שונים עבור סוגי עצמים שונים. למשל, הפקודה • array<double> vec(12) • תיצור מערך של double בגודל 12. כדי למנוע שכפול קוד ע"י הקומפיילר (לכל instance של ה-template), יש לאסוף את החלקים המשותפים במחלקת בסיס class arrayBase ואח"כ לבצע הורשה: • template <class T> class array: public arrayBase {...} • יש לממש מחלקות כדי שהתוכנית למטה תתבצע כפי שנדרש. שימו לב: בראש הקוד הושמטו שמות המחלקות; עליכם להשלים את הקוד. מומלץ לקרוא את כל הקוד לפני פתרון השאלה. • סעיף א (15 נקודות): הגדרת המחלקות: • הגדירו את המחלקות 1T, 2T, 3T, ו-T4 עם מתודות סבירות לשימוש קל ונוח במערכים (כולל קלט/פלט). שימו לב כי יש להגדיר את כל שדות הנתונים ולהצהיר על כל הפונקציות הנדרשות. אין צורך לממש שום פונקציה. הגדירו גם את המחלקה לטיפול בחריגות. • סעיף ב (20 נקודות): מימוש (חלק מהפונקציות של) המחלקות: • ממשו את הפונקציות הבאות בכל מחלקה בה הן מופיעות: בנאים (constructors) אין צורך לאפס ערכים לא מאותחלים, הורסים (destructors), אופרטור פלט (operator<<), ופעולת אינדקס (operator[]), טפלו נכון בשגיאות. מבוא לתכנות מערכות - 234122
קוד השימוש במחלקות • typedef ........ T1; • typedef ........ T2; • typedef ........ T3; • typedef........ T4; • //... more code? ... • intmain () { • try { // משמעות + תוצאה • T1 a1(12), a11(10); //הגדרת 2 מערכים של • //בגודל 12 ו-10 double • T2 a2(10); // 10 בגודלintהגדרת מערך של • a2 = a11; // Syntax error • a1 = a11; // O.K. • a1[5] = a2[4]; // O.K. • cout << a1; // הדפסת מערך שלם • constT1 ca1(a11); // הגדרת מערך קבוע • // עם אתחול • ca1 = a11; // Syntax error • ca1[2] = a11[3]; // Syntax error • a11[3] = ca1[2]; // O.K. • doublec_array[] = {0.5, -7, 3.14, 0.3}; • // "C הגדרת "מערך • T1 a12(c_array, 4); // הגדרת מערך ואתחולו • // "C ע"י "מערך • T3 a3; // בגודל5double הגדרת מערך של • T4 a4; // בגודל8double הגדרת מערך של • a3[1] = a4[2]; // O.K. • a3 = a4; // Syntax error • a4 = a3; // Syntax error • a1 = a4; // O.K. • return 0; • } • catch (Bad_Indexexc) { • cerr << exc; //Bad-Index value is ... :פלט • } • } מבוא לתכנות מערכות - 234122
פתרון • typedef Array<double> T1; • typedef Array<int> T2; • typedefSizedArray<double, 5> T3; • typedefSizedArray<double, 8> T4; • classBadIndex { • intindex; • public: • BadIndex(int i) : index(i) {} • friendostream& operator<<(ostream& os, constBadIndex& b); • }; • ostream& operator<<(ostream& os, constBadIndex& b) { • returnos << "Array index " << b.index << " is out of bounds" << endl; • } מבוא לתכנות מערכות - 234122
פתרון • classArrayBase { • protected: • intsize; • boolisLegal(int index) const { • returnindex>=0 && index<size; • } • public: • ArrayBase(intsz): size(sz) { } • intgetSize() const { • returnsize; • } • }; מבוא לתכנות מערכות - 234122
פתרון • template<classT>classArray: publicArrayBase { • T* elements; voidfillArray(T* data,intsz){ • elements= newT[sz]; • size= sz; • for(int i=0;i<sz;i++) • elements[i] = data[i];}public: • Array(intsz):ArrayBase(sz), elements(newT[sz]) {} • Array(constArray<T>& array2) : ArrayBase(array2.size) { • fillArray(array2.elements,size); } • Array(T* array2, intsz) : ArrayBase(sz) { • fillArray(array2,size);} מבוא לתכנות מערכות - 234122
פתרון • ~Array() { delete[] elements; } • T& operator[](int i) { • if (!isLegal(i)) throwBadIndex(i); • returnelements[i]; } • constT& operator[](int i) const { • if (!isLegal(i)) throwBadIndex(i); • returnelements[i];} • array& operator=(const array& other) { • if (this == &other) {return*this; } • delete[] elements; • fillArray(other.elements,other.size()); • return *this;}}; מבוא לתכנות מערכות - 234122
פתרון • template<classT> • ostream& operator<< (ostream& out, constArray<T>& array) { • for(inti=0 ; i<array.getSize() ; i++) • out << array[i] << ' '; • returnout << endl; • } • template <classT> • istream& operator>> (istream& in, Array<T>& array) { • for(inti=0 ; i<array.getSize() ; i++) • in >> array[i]; • returnin; • } • template <classT,intSZ> • classArraySize: publicArray<T>{ • public: • ArraySize() : Array<T>(SZ) {}; • }; מבוא לתכנות מערכות - 234122
שאלה 3 • מה מדפיסה התכנית הבאה? intmain() { cout << "--1--" << endl; A<int> a; cout << "--2--" << endl; A<double> a1; cout << "--3--" << endl; B<int> b(a); cout << "--4--" << endl; B<int> b1(b); cout << "--5--" << endl; C c(a); cout << "--6--" << endl; B<int>& b2 = c; cout << "--7--" << endl; return 0; } #include<iostream>usingnamespacestd;template<classT>classA { public: A() { cout << "A::A()" << endl; } A(constA& a) : i(a.i) { cout << "A::A(A&)" << endl; } private: Ti; };template<classT> classB { public: B(A<T> aa) : a(aa) { cout << "B::B(A)" << endl; } B(constB& b) : a(b.a) { cout << "B::B(B&)" << endl; } A<T> a;};classC: publicB<int> { public: C(A<int> aa) : B<int> (aa), a(aa) { cout << "C::C(A aa)" << endl; } ~C() { cout << "C::~C()" << endl; } A<int> a; }; מבוא לתכנות מערכות - 234122
פתרון • יודפס: --5-- A::A(A&) A::A(A&) A::A(A&) B::B(A) A::A(A&) C::C(A aa) --6-- --7-- C::~C() --1-- A::A() --2-- A::A() --3-- A::A(A&) A::A(A&) B::B(A) --4-- A::A(A&) B::B(B&) מבוא לתכנות מערכות - 234122
שאלה 4 • הגדר מחלקה/מחלקות הנדרשות בקובץ Array.h על מנת שקטע הקוד הבא יעבור הידור (קומפילציה). • שים לב: רק הצהרת המחלקה/ות נדרשת - ללא מימוש הפונקציות. יש להניח שבמימוש המחלקה ישנם מצביעים. מבוא לתכנות מערכות - 234122
קטע הקוד for (int i = 0; i < 20; i++) { cin >> arr[i]; sum += arr[i]; } cout << "Sum is:" << sum << endl; min = arr[0]; for (i = 1; i < 20; i++) if (arr[i] < min) min = arr[i]; cout << "Min is: " << min << endl; if (min == arr[0]) cout <<"The first Array is the minimum"<<endl; const Array<double> c_arr = sum; for (int i = 0; i < c_arr.size(); i++) { cout <<"Element #"<<i<<": "<<c_arr[i]<<endl; } delete a1; Array<A> arr_A(7); Array<A> arr_A2 = arr_A; return 0; } #include"Array.h" #include"iostream.h" class A { inta; public: A(intaa = 0) : a(aa) {} };intmain() { Array<int> *a1 = new Array<int>(3); //An array with 3 elements of type int Array<double> arr[20]; //An array of 20 Arrays, each one of them //is of 100 elements of type double Array<double> sum(100); //An Array of 100 elements of type double Array<double> min(100); //An Array of 100 elements of type double sum[0] = 10; sum[1] = 20; sum[2] = 30; מבוא לתכנות מערכות - 234122
פתרון • #ifndef __ARRAY_H_ • #define __ARRAY_H_ • template<classT> • classArray { • public: • Array(int size = 100); • constT& operator[](int i) const; • T& operator[](int i); • Array& operator+=(constArray& arr); • intsize() const; • Array(constArray& src); • Array& operator=(constArray& src); • ~Array(); • private: • //... • }; מבוא לתכנות מערכות - 234122
פתרון • // the next operators are global functions • template<classT> • ostream& operator<<(ostream& out, constArray<T>& arr); • template<classT> • istream& operator>>(istream& inp, Array<T>& arr); • // the next operators may be implemented as member functions • template<classT> • booloperator<(constArray<T>& left, constArray<T>& right); • template<classT> • booloperator==(constArray<T>& left, constArray<T>& right); • #endif//__ARRAY_H_ מבוא לתכנות מערכות - 234122