Οικονομικό Πανεπιστήμιο Αθηνών, Τμήμα Πληροφορικής Μάθημα: Προγραμματισμός Υπολογιστών με C++ Εξεταστική περίοδος: Σεπτεμβρίου 2011. Διδάσκων: Α. Δημάκης Γράψτε όλες τις απαντήσεις σας πάνω σε αυτό το φυλλάδιο. Χρησιμοποιήστε το τετράδιο μόνο για πρόχειρο, εκτός όπου ρητά ζητείται το αντίθετο. Γράψτε το ονοματεπώνυμό σας στο τετράδιο και σε όλα τα φύλλα αυτού του φυλλαδίου. Ονοματεπώνυμο και ΑΜ: Είχα παραδώσει εργασίες τα εξής ακαδημαϊκά έτη: Διάρκεια: 2,5 ώρες, κλειστά βιβλία και σημειώσεις ΚΑΛΗ ΕΠΙΤΥΧΙΑ! 1o θέμα (20%): Δίνονται οι παρακάτω ορισμοί τάξεων: // Αρχείο foo.h #include <iostream> using namespace std; class A public: A() cout << A s constructor\n ; A(const A &) cout << A s copy constructor\n ; void operator=(const A& right) cout << A s =\n ; virtual void f() cout << A s f()\n ; ; class B: public A public: B() cout << B s constructor\n ; void f() cout << B s f()\n ; ; (α) Τί θα εκτυπώσει η παρακάτω συνάρτηση main(); #include foo.h A func(a& arg) return arg; A a,b; b = a; A c(a); func(a); (β) Τί θα εκτυπώσει η παρακάτω συνάρτηση main(); #include foo.h A a; B b; a.f(); b.f(); B* p1 = new B; p1->f(); A* p2 = &b; p2->f();
(γ) Τί θα εκτυπώσει η παραπάνω συνάρτηση main() εάν η μέθοδος A::f() δε δηλωθεί ως εικονική (virtual); 2o θέμα (25%): (α) Δίνεται ο ορισμός της τάξης Matrix η οποία αναπαριστά (μαθηματικούς) πίνακες με στοιχεία τύπου float και υποστηρίζει πρόσθεση μεταξύ πινάκων. Συμπληρώστε τους ορισμούς στα κενά που ακολουθούν έτσι ώστε (1): οι διαστάσεις n,m ενός πίνακα να μη μπορούν να αλλάξουν μετά την αρχικοποίησή του, και (2) κατά την αρχικοποίησή του, όλα τα στοιχεία λαμβάνουν την ίδια τιμή value (ενώ μπορεί να λάβουν διαφορετική τιμή στη συνέχεια). class Matrix n; // πλήθος γραμμών m; // πλήθος στηλών float *storage; // δείκτης στο χώρο αποθήκευσης των στοιχείων του πίνακα public: Matrix(unsigned ni, unsigned mi, float value=0f) : n(ni), m(mi), storage(new float[n*m]) for (unsigned i=0; i < ; i++ ) for ( unsigned j=0; j < ; j++ ) (*this)[i][j] = ; Matrix(const Matrix &original); ~Matrix(); const Matrix operator+(const Matrix &obj) const; const Matrix operator=(const Matrix &right); float* const operator[](unsigned int i) const return &storage[i*m]; ; friend ostream& operator<<(ostream &out, const Matrix &matrix); (β) Υλοποιήστε τη συνάρτηση operator<<(ostream&, const Matrix&) έτσι ώστε η παρακάτω συνάρτηση main() να έχει το επιθυμητό αποτέλεσμα. Matrix m(2,3,1.0f); cout << m; // Εκτυπώνει: 1.0 1.0 1.0 // 1.0 1.0 1.0
ostream& operator<<(ostream &out, const Matrix &matrix) // Συμπληρώστε εδώ: (γ) Υλοποιήστε τον τελεστή +. Θα πρέπει να επιστρέφεται το άθροισμα δύο πινάκων, χωρίς να αλλάζει κανείς από αυτούς. (Υπενθυμίζεται ότι εάν Α, Β είναι n m πίνακες, τότε το άθροισμα Γ είναι ένας n m πίνακας με Γ ij =A ij +B ij για όλα τα i=1,..,n και j=1,,m.) Δε χρειάζεται να κάνετε έλεγχο λαθών, π.χ., συμβατότητα διαστάσεων. const Matrix Matrix::operator+(const Matrix &obj) const
(δ) Υλοποιήστε καταστροφέα, κατασκευαστή αντιγράφου και τελεστή εκχώρησης έτσι ώστε να αποφεύγεται η διαρροή μνήμης. Matrix::~Matrix() Matrix::Matrix(const Matrix &original) const Matrix Matrix::operator=(const Matrix &right) (ε) Ορίσετε και υλοποιήστε μία μέθοδο ή συνάρτηση η οποία δίνει τη δυνατότητα πολλαπλασιασμού αριθμού float με πίνακα, έτσι ώστε π.χ., το ακόλουθο πρόγραμμα να έχει το επιθυμητό αποτέλεσμα: Matrix m(2,3,5.0f); cout << -0.5F*m; // Εκτυπώνει: -2.5-2.5-2.5 // -2.5-2.5-2.5 Συμπληρώστε την υλοποίησή σας στον κενό χώρο που ακολουθεί. Επίσης περιγράψτε τις αλλαγές που απαιτούνται στον ορισμό της τάξης Matrix.
3 ο θέμα (25%): Σε αυτό το ερώτημα θα ορίσετε και υλοποίησετε τις τάξεις Animal, Pig, Cow, Farm, έτσι ώστε η συνάρτηση main() που δίδεται παρακάτω να δίνει το αποτέλεσμα που περιγράφεται στα σχόλια εκεί. Η τάξη Pig αναπαριστά ένα γουρούνι, ενώ η Cow μια αγελάδα. Η Farm αναπαριστά μια φάρμα η οποία αποτελείται από έναν πεπερασμένο αριθμό ζώων (Animal). Η μέθοδος feed() της Farm αναπαριστά το τάϊσμα όλων των ζώων της φάρμας. Κάθε φορά που ταΐζεται ένα γουρούνι το βάρος του αυξάνεται κατά 0,3 κιλά ενώ το βάρος μιας αγελάδας αυξάνεται κατά 1,5 κιλό. Δεν επιτρέπεται η χρήση τάξεων/συναρτήσεων της βιβλιοθήκης STL, όπως vector, map κτλ. class Animal ; class Pig: public Animal ; class Cow: public Animal ; class Farm ; void show(const Farm& f) for ( int i = 0; i < f.numofanimals; i++ ) cout << f.getanimal(i).getname() << ( << f.getanimal(i).gettype() << ) << f.getanimal(i).getweight() << endl; Farm farm(2); // Αρχικοποίηση φάρμας με 2 ζώα // Αρχικοποίηση 1 ου ζώου (γουρούνι με όνομα Miss Piggy 32.5 κιλών) farm.setanimal(0, new Pig( Μiss Piggie,32.5)); // Αρχικοποίηση 2 ου ζώου (αγελάδα με όνομα Clarabelle 320.2 κιλών) farm.setanimal(1, new Cow( Clarabelle,320.2)); show(farm); // Εκτυπώνει: Miss Piggy (γουρούνι), 32.5 κιλά // Clarabelle (αγελάδα), 320.2 κιλά farm.feed(); // Τάϊσμα ζώων της φάρμας show(farm); // Εκτυπώνει: Miss Piggy (γουρούνι), 32.8 κιλά // Clarabelle (αγελάδα), 321.7 κιλά
4 ο θέμα: (α) (30%) Σε αυτό το ερώτημα θα ορίσετε και υλοποιήσετε την τάξη SortedList η οποία αναπαριστά μια ταξινομημένη λίστα ακεραίων (int), την οποία θα υλοποιήσετε ως μια απλά συνδεδεμένη λίστα. Θα πρέπει να υποστηρίζονται οι εξής μέθοδοι: void SortedList::insert(int val) Εισαγωγή ακέραιου με τιμή val έτσι ώστε στη θέση εισαγωγής, τα επόμενα στοιχεία να μην είναι μικρότεροι ακέραιοι, ενώ τα προηγούμενα στοιχεία δεν είναι μεγαλύτεροι ακέραιοι. int SortedList::getLength() const Επιστρέφει τον αριθμό των στοιχείων της λίστας. const int SortedList::operator[](int i) const throw(sortedlist::invalidindex) Επιστρέφει την τιμή του i-οστού στοιχείου της λίστας. (Το πρώτο στοιχείο λαμβάνεται για i=0.) Η εξαίρεση SortedList::InvalidIndex ενεργοποιείται όταν δεν υπάρχει i-οστό στοιχείο, π.χ., γιατί i<0 ή η λίστα δεν περιέχει αρκετά στοιχεία. void show() const Εκτυπώνει τα περιεχόμενα της ουράς αρχίζοντας από το 1 ο στοιχείο, στη standard έξοδο. Ένα παράδειγμα χρήσης της SortedList δίδεται στη main() που ακολουθεί. Επίσης θα πρέπει να ορίσετε και υλοποιήσετε κατάλληλα κατασκευαστή αντιγράφου (copy constructor), καταστροφέα (destructor) και τελεστή εκχώρησης (operator=) έτσι ώστε να αποφεύγεται η διαρροή μνήμης. Δώστε την απάντησή σας στο τετράδιο εξέτασης. List ls; ls.insert(10); ls.insert(3); ls.insert(7); try cout << ls[0] << endl; // Εκτυπώνεται το 1 ο στοιχείο, δηλ. 3 catch(sortedlist::invalidindex ex) cout << Index << ex.index << not valid.\n ; ls.show(); // Εκτυπώνεται: 3 7 10 (β) Εξηγήσετε με σαφή τρόπο, πώς πρέπει να αλλαχθεί ο ορισμός και η υλοποίηση της SortedList έτσι ώστε να μπορεί να διαχειριστεί αυθαίρετους τύπους όχι μόνο ακέραιους-. (Δε χρειάζεται να ξαναγράψετε ολόκληρο τον ορισμό και υλοποίηση της νέας SortedList.) Για παράδειγμα, η νέα SortedList θα πρέπει να μπορεί να χρησιμοποιηθεί ως εξής: List<string> ls; ls.insert( Γιάννης ); ls.insert( Αλεξάνδρα ); ls.insert( Δήμητρα ); try cout << ls[0] << endl; /* Εκτυπώνεται το αλφαβητικά 1 ο Αλεξάνδρα */ catch(sortedlist::invalidindex ex) cout << Index << ex.index << not valid.\n ; ls.show(); // Εκτυπώνεται: Αλεξάνδρα Γιάννης Δήμητρα στοιχείο, δηλ.
Σημειώστε ότι στη C++ η έκφραση s1<s2, όπου τα s1, s2 είναι string, έχει τιμή true εάν και μόνο εάν το s1 προηγείται αλφαβητικά του s2. Παρόμοια καθορίζεται το αποτέλεσμα των σύγκρισεων >, <=, >=. Δώστε την απάντησή σας στο χώρο που ακολουθεί: