ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ Φροντιστήρια Εισηγητής: Σπύρος Αργυρόπουλος Μέλος ΕΤΕΠ Εργαστήριο Προγραμματισμού & Τεχνολογίας Ευφυών Συστημάτων
Abstract Data Types Abstract Data Type (ADT): a definition for a data type solely in terms of a set of values and a set of operations on that data type. Each ADT operation is defined by its inputs and outputs. Encapsulation: Hide implementation details.
Data Structure A data structure is the physical implementation of an ADT. –Each operation associated with the ADT is implemented by one or more subroutines in the implementation. Data structure usually refers to an organization for data in main memory. File structure is an organization for data on peripheral storage, such as a disk drive.
Logical vs. Physical Form Data items have both a logical and a physical form. Logical form: definition of the data item within an ADT. –Ex: Integers in mathematical sense: +, - Physical form: implementation of the data item within a data structure. –Ex: 16/32 bit integers, overflow.
Data Type ADT: Type Operations Data Items: Logical Form Data Items: Physical Form Data Structure: Storage Space Subroutines
C++ Πρότυπα συναρτήσεων : return_type function_name(type 1 name 1, type 2 name 2,...); Δηλώσεις σταθερών : const double PI = ; char *strcpy(char *target, const char *source);
C++ (συνέχεια) Μεταβίβαση παραμέτρων δια μέσου αναφοράς: int string2int(char *string, int &flag); int result, status; result = string2int("5", status); if (status == 0) {... Υπερφόρτωση ονομάτων (overloading): Παράδειγμα
C++ (συνέχεια) Δηλώσεις μεταβλητών σε οποιοδήποτε σημείο του κώδικα Εξ ορισμού τιμές για παραμέτρους συναρτήσεων (default values): FILE *open_file(const char *path, const char *mode = "r") { return fopen(path, mode); }
C++ (συνέχεια) Συναρτήσεις inline : inline int max(int x, int y) { return x > y ? x : y; } inline double max(double x, double y) { return x > y ? x : y; } Ορισμός τελεστών Παράδειγμα Τελεστές εισόδου, εξόδου (cin, cout, cerr) Παράδειγμα
C++ (συνέχεια) Σχόλια: i++; // Το i αυξάνεται κατά 1 j++; // Το ίδιο και το j
C++ (συνέχεια) Κλάσεις αντικειμένων (Classes) –Private, public, protected members Private, public, protected membersPrivate, public, protected members –Methods & inline functions Methods & inline functionsMethods & inline functions –Constructor, destructor Constructor, destructorConstructor, destructor –Copy constructor Copy constructorCopy constructor –Τελεστής ανάθεσης Τελεστής ανάθεσηςΤελεστής ανάθεσης –Δείκτης this Δείκτης thisΔείκτης this –Τελεστές new & delete (γενικό παράδειγμα)Τελεστές new & delete (γενικό παράδειγμα)
C++ (συνέχεια) Κληρονομικότητα Επανορισμός μεθόδων, διπλός ορισμός μεταβλητής Συμβατότητα δεικτών / αναφορών Virtual methods, virtual table, pure virtual methods
C++ (συνέχεια) Friend classes Static member κλάσεων Class templates template class myTemplate {...}; Παράδειγμα Exception classes
void Input(char *prompt, int &i) { …. } void Input(char *prompt, double &d) { …. } void Input(char *prompt, char *s) { …. } int main(void) { int my_integer; double my_double; char my_string[100]; Input("Δώστε τιμή για το my_integer", my_integer); Input("Δώστε τιμή για το my_double", my_double); Input("Δώστε τιμή για το my_string", my_string); printf("my_integer = %d\nmy_double = %f\nmy_string = %s\n",my_integer, my_double, my_string); } BACKBACK
typedef struct Employee { char name[100]; int salary; } Employee; void operator +=(Employee &e, int raise) { e.salary = e.salary + raise; } int main(void) { Employee e1; strcpy(e1.name, "Janitor John"); e1.salary = 100; e1 += 200; /* Κλήση του τελεστή που ορίσαμε */ printf("%d\n", e1.salary); return 0; } BACKBACK
int a; double b; char c[100]; cin >> a; /* Ανάγνωση του a */ cin >> b >> c; /* Ανάγνωση δύο μεταβλητών, πρώτα της b και μετά της c */ cout << "Η τιμή του a είναι " << a << "\n"; cout << "Η τιμή του b είναι " << b << endl; /* Η σταθερά endl σημαίνει αλλαγή γραμμής */ cout << "Η τιμή του c είναι " << c << endl; BACK
class Person { private: char name[30]; char address[50]; int birth_year; public: void set_name(const char *); void set_address(const char *); void set_birth_year(int y) {birth_year = y;} const char *get_name(void) const {return name;} const char *get_address(void) const {return address;} int get_birth_year(void) const {return birth_year;} }; BACK
void Person::set_name(const char *n) { strncpy(name, n, 29); name[29] = '\0'; } void Person::set_address(const char *a) { strncpy(address, a, 49); name[49] = '\0'; } BACK
class String { private: char *str; public: String(void); // Συνάρτηση κατασκευής χωρίς παραμέτρους String(const char *s); // Συνάρτηση κατασκευής όπου ορίζεται // η τιμή που επιθυμούμε να αποδόσουμε στο στιγμιότυπο ~ String(void); // Συνάρτηση καταστροφής void set_value(const char *s); const char *get_value(void) const {return str;} }; BACK
String::String(void) { str = strdup(""); } String::String(const char *s) { str = strdup(s); } String::~String(void) {free(str);} void String::set_value(const char *s) { free(str); str = strdup(s); } BACK
Copy costructor String(String &s) {str = strdup(s.str);} Τελεστής ανάθεσης void operator=(String &s) {free(str); str = strdup(s.str);} BACK
void Person::marry(Person &new_spouse) { // Ελεγχος αν και οι δύο είναι ελεύθεροι if ((spouse != NULL) || (new_spouse.spouse != NULL)) { cerr << "Πρέπει και οι δύο να είναι ελεύθεροι!" << endl; return; } spouse = &new_spouse; new_spouse.spouse = this; } BACK
class IntegerListNode { private: int value;// Η τιμή του κόμβου IntegerListNode *next;// Ο δείκτης στον επόμενο public: IntegerListNode(int v, IntegerListNode *n) { value = v; next = n; } int getValue(void) const {return value;} void setNext(IntegerListNode *n) {next = n;} IntegerListNode *getNext(void) const {return next;} }; BACK
class IntegerList { private: IntegerListNode *first; public: IntegerList(void); // Συνάρτηση κατασκευής ~IntegerList(void); // Συνάρτηση καταστροφής void add(int v); // Προσθήκη κόμβου με συγκεκριμένη τιμή int remove(int v);// Διαγραφή κόμβου με συγκεκριμένη τιμή. // Επιστρέφουμε 1 σε επιτυχία, 0 σε αποτυχία // (δεν υπάρχει τέτοιος κόμβος. int has(int v) const;// Ελεγχος ύπαρξης κόμβου με συγκεκριμένη // τιμή. Επιστρέφουμε // 1 αν υπάρχει, 0 αν δεν υπάρχει. };
IntegerList::IntegerList(void) { // Δημιουργία του dummy κόμβου με αδιάφορη τιμή και NULL ως // επόμενο, δηλ. ο dummy κόμβος είναι ο τελευταίος στη λίστα. first = new IntegerListNode(0, NULL); } IntegerList::~IntegerList(void) { IntegerListNode *cur, *nxt; // Διατρέχουμε τους κόμβους της λίστας for (cur = first; cur != NULL; ) { nxt = cur->getNext(); // Κάθε φορά φυλάμε τον επόμενο delete cur; //... σβήνουμε τον τρέχοντα cur = nxt; //... και προχωράμε στον επόμενο }
void IntegerList::add(int v) { // Προσθέτουμε τον νέο κόμβο ως πρώτο στη λίστα, // αμέσως μετά από τον dummy. IntegerListNode *newNode = new IntegerListNode(v, first->getNext()); first->setNext(newNode); } int IntegerList::remove(int v) { // Προσπάθεια εντοπισμού του κόμβου που θα διαγραφεί. Σε κάθε βήμα // φροντίζουμε να δείχνουμε έναν κόμβο πιο πριν, έτσι ώστε να // μπορούμε να τροποποιήσουμε τον κατάλληλο δείκτη next. // Φυσικά, η τιμή του πρώτου κόμβου αγνοείται.
for (IntegerListNode *prev = first; prev->getNext() != NULL; prev = prev->getNext()) { if (prev->getNext()->getValue() == v) { // βρέθηκε ο κόμβος που πρέπει να διαγραφεί IntegerListNode *victim = prev->getNext(); // Βγάζουμε τον κόμβο-θύμα από τη λίστα, συνδέοντας // απ' ευθείας τον προηγούμενό του με τον επόμενό του prev->setNext(victim->getNext()); // αποδεσμεύουμε τη μνήμη για τον κόμβο-θύμα delete victim; return 1; // Επιστροφή με ένδειξη επιτυχίας } return 0; // Επιστροφή με ένδειξη αποτυχίας }
int IntegerList::has(int v) const { // Αναζήτηση του κόμβου. Ο πρώτος κόμβος αγνοείται συνολικά. for (IntegerListNode *n = first->getNext(); n != NULL; n = n- >getNext()) if (n->getValue() == v) return 1; // Ναι, βρέθηκε return 0; // Οχι, η λίστα εξαντλήθηκε χωρίς να βρεθεί. } BACK
class B: [public] A {... }; Κανόνες: 1.Όσα είναι private στην Α δεν είναι ορατά στη Β. 2.Όταν δεν έχει παρατεθεί η λέξη public, όλα τα public της Α είναι private για τη Β. 3.Όταν έχει παρατεθεί η λέξη public, όλα τα public της Α είναι public για τη Β. 4.Όσα είναι protected στην Α είναι ορατά στη Β και είναι χαρακτηρισμένα πάλι ως protected. BACK
ΔήλωσηΕπιτρ έπεται ; Σχόλια A &ra = b;ΝαιΣε μία αναφορά προς στιγμιότυπο της υπερκλάσης μπορούμε να αναθέσουμε ένα στιγμιότυπο της υποκλάσης. A *pa = &b;ΝαιΣε έναν δείκτη προς στιγμιότυπο της υπερκλάσης μπορούμε να αναθέσουμε τη διεύθυνση ενός στιγμιοτύπου της υποκλάσης. a = b;ΌχιΗ μόνη περίπτωση να επιτρέπεται είναι να έχουμε ορίσει στην κλάση B έναν τελεστή μετατροπής στιγμιοτύπων της σε στιγμιότυπα της κλάσης A, δηλ. τον τελεστή A &operator B::A(void) const; B *pb = &a;ΌχιΔεν επιτρέπεται η ανάθεση δείκτη προς στιγμιότυπο της υπερκλάσης σε δείκτη προς στιγμιότυπο της υποκλάσης.
BACK ΔήλωσηΕπιτρ έπετα ι; Σχόλιο B *pb =(B *) &a;ΝαιΗ ανάθεση επιτρέπεται διότι παραθέτουμε ρητή μετατροπή τύπου. B &rb = a;ΌχιΔεν επιτρέπεται η ανάθεση στιγμιοτύπου της υπερκλάσης σε αναφορά προς στιγμιότυπο της υπερκλάσης, εκτός αν έχουμε ορίσει κατάλληλο τελεστή μετατροπής στην κλάση B, δηλ. τον τελεστή B &operator A::B(void) const; b = a;ΌχιΔεν επιτρέπεται η ανάθεση στιγμιοτύπου της υπερκλάσης σε στιγμιότυπο της υπερκλάσης, εκτός αν έχουμε ορίσει κατάλληλο τελεστή μετατροπής στην κλάση B, δηλ. τον τελεστή B &operator A::B(void) const;
Παράδειγμα: #include template class Array { private: T *data; int maxSize; public: Array(int size); ~Array(void) { delete [] data; } Array &setValue(const T &value, int position); T getValue(int position); }; BACK BACK
template Array ::Array(int size) { if (size <= 0) { cerr << "Μη παραδεκτό μέγεθος για πίνακα (" << size << ")\n"; exit(1); } if ((data = new T[size]) == NULL) { cerr << "Δεν υπάρχει αρκετή μνήμη για τον πίνακα.\n"; exit(1); } maxSize = size; } BACK BACK
template Array &Array ::setValue(const T &value, int position) { if ((position = maxSize)) { cerr << "Μη παραδεκτός δείκτης για πίνακα (" << position << ")\n"; exit(1); } data[position] = value; return *this; } BACK
template T Array ::getValue(int position) { if ((position = maxSize)) { cerr << "Μη παραδεκτός δείκτης για πίνακα (" << position << ")\n"; exit(1); } return data[position]; } BACK
int main(void) { Array a(50); for (int i = 0; i < 100; i++) { a.setValue(i * 2, i); cout << "Position " << i << ", value " << a.getValue(i) << endl; } return 0; } BACK
template class MyList; template class MyListNode { private: // Δήλωση της κλάσης MyList ως φίλης, ώστε να έχει πρόσβαση // στα ιδιωτικά τμήματα. friend class MyList ; T datum; MyListNode *next; // Παραθέτουμε και μία μέθοδο κατασκευής. Η μέθοδος αυτή // παραμένει ιδιωτική, καθώς προσπελαύνεται μόνο από την // MyList κλάση η οποία έχει δηλωθεί ως φίλη κλάση. MyListNode(T d, MyListNode *n) { datum = d; next = n; } }; BACKBACK
template class MyList { private: MyListNode *first; MyListNode **find(const T target) { MyListNode **result; for (result = &first;*result != NULL;result = &((*result)->next)) if ((*result)->datum == target) return result; // Δεν βρέθηκε κατάλληλος κόμβος return NULL; } public: MyList(void) {first = NULL;} BACK
~MyList(void) { MyListNode *victim, *nxt; for (victim = first; victim != NULL; victim = nxt) { nxt = victim->next; delete victim; } MyList &insert(const T datum) { MyListNode *newNode = new MyListNode (datum, first); first = newNode; return *this; } BACK
MyList &remove(const T datum) { MyListNode **victim, *next; victim = find(datum); if (victim == NULL) return *this; next = (*victim)->next; delete (*victim); *victim = next; return *this; }
int search(const T datum) { MyListNode **temp = find(datum); if (temp == NULL) return 0; else return 1; } }; // end of class definition BACK
class Person { public: char idNumber[20]; char name[100]; int birthYear; Person(const char *i, const char *n, int b) { strcpy(idNumber, i); strcpy(name, n); birthYear = b; } }; BACK
int main(void) { MyList IntegerList; IntegerList.insert(2); IntegerList.insert(7); printf("Searching for 2... %d\n", IntegerList.search(2)); printf("Searching for 5... %d\n", IntegerList.search(5)); printf("Searching for 7... %d\n", IntegerList.search(7)); printf("Removing 2...\n"); IntegerList.remove(2); printf("Searching for 2... %d\n", IntegerList.search(2)); printf("Searching for 7... %d\n", IntegerList.search(7));
MyList PersonList; Person p1("A312", "John", 1968), p2("C5670", "Mary", 1974), p3("Z80", "Zilog", 1978); PersonList.insert(p1); PersonList.insert(p2); printf("Searching for \"John\"... %d\n", PersonList.search(p1)); printf("Searching for \"Mary\"... %d\n", PersonList.search(p2)); printf("Searching for \"Zilog\"... %d\n", PersonList.search(p3)); printf("removing \"Mary\"\n"); PersonList.remove(p2); printf("Searching for \"Mary\"... %d\n", PersonList.search(p2)); return 0; } BACKBACK