ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ Κεφάλαιο 16 Επιμέλεια: Βασίλης Παλιουράς, Αναπληρωτής Καθηγητής Ευάγγελος Δερματάς, Αναπληρωτής Καθηγητής Σταύρος Νούσιας, Βοηθός Ερευνητή Πολυτεχνική Σχολή Τμήμα Ηλεκτρολόγων Μηχανικών & Τεχνολογίας Υπολογιστών
Άδειες Χρήσης Το παρόν εκπαιδευτικό υλικό υπόκειται σε άδειες χρήσης Ceative Commons. Για εκπαιδευτικό υλικό, όπως εικόνες, που υπόκειται σε άλλου τυπου άδειας χρησης, η άδεια χρησης αναφερεται ρητώς. 2
Χρηματοδότηση Το παρόν εκπαιδευτικό υλικό έχει αναπτυχθεί στα πλαίσια του εκπαιδευτικού έργου των διδασκόντων καθηγητών. Το έργο «Ανοικτά Ακαδήμαϊκά Μαθήματα στο Πανεπιστήμιο Πατρών» έχει χρηματοδοτηθεί μόνο τη αναδιαμόρφωση του εκπαιδευτικού υλικού. Το έργο υλοποιείται στο πλαίσιο του Επιχειρησιακού Προγράμματος «Εκπαίδευση και Δια Βίου Μάθηση» και συγχρηματοδοτείται από την Ευρωπαϊκη Ένωση (Ευρωπαϊκό Κοινωνικό Ταμείο) και από εθνικους πόρους. 3
Ανάπτυξη Το παρόν εκπαιδευτικό υλικό αναπτύχθηκε στο τμήμα Ηλεκτρολόγων Μηχανικών και Τεχνολογίας Υπολογιστών του Πανεπιστημίου Πατρών 4
Σκοπός Στόχος της παρακάτω ενότητας είναι η εισαγωγη σε β ασικες αρχες και εννοιες των Αρχων Προγραμματισμ ού. 5
Σχετικά με το εργαστήριο 3 Μια προσέγγιση Διάβασε κείμενο από αρχείο σε πίνακα Διάβασε λεξικό από αρχείο σε πίνακα Τροποποίησε πίνακες Γράψε πίνακες σε αρχείο Άλλη προσέγγιση Προσθέτω λέξεις στο λεξικό κατευθείαν στο αρχεί ο 6
Δυναμική διαχείριση μνήμης στη C Δέσμευση μνήμης: void *malloc(size_t size); Επιστρέφει δείκτη σε εξασφαλισμένη περιο χή μεγέθους size bytes ή NULL αν δεν υπά ρχει τέτοια. Απελευθέρωση μνήμης: void fee(void *pointe); 7
Πώς δουλεύει ο μηχανισμός; Χρησιμοποιεί δεδομένα στο heap Λεπτομερή διαχείριση ανά block Διεύθυνση αρχής Μέγεθος Μοιράζεται πληροφορία μεταξύ διαφορετικών συναρ τήσεων malloc ( ), fee ( ) Πώς γίνεται αυτό; 8
Παράδειγμα #include <stdio.h> #include <stdlib.h> #define N 10 main ( ) { matix[n]; scanf("%s", matix); pintf("hello %s!\n", matix); 9
Παράδειγμα #include <stdio.h> #include <stdlib.h> #define N 10 main ( ) { matix[n]; *dynamicdata; scanf("%s", matix); pintf("hello %s!\n", matix); dynamicdata = ( *) malloc( N * sizeof ()); scanf("%s", dynamicdata); pintf("hello dynamic %s!", dynamicdata); 10
Παράδειγμα #include <stdio.h> #include <stdlib.h> #define N 10 main ( ) { matix[n]; *dynamicdata; int i; scanf("%s", matix); pintf("hello %s!\n", matix); dynamicdata = ( *) malloc( N * sizeof ()); scanf("%s", dynamicdata); pintf("hello dynamic %s!\n", dynamicdata); fo (i=0;dynamicdata[i]!=0;i++) pintf("%c\n", dynamicdata[i]); 11
Παράδειγμα #include <stdio.h> #include <stdlib.h> #define N 10 main ( ) { matix[n]; *dynamicdata; int i, ns; scanf("%s", matix); pintf("hello %s!\n", matix); while (1) { pintf("how many s?"); scanf("%d", &ns); dynamicdata = ( *) malloc( ns * sizeof ()); scanf("%s", dynamicdata); pintf("hello dynamic %s!\n", dynamicdata); fo (i=0;dynamicdata[i]!=0;i++) pintf("%c\n", dynamicdata[i]); fee(dynamicdata); 12
13 * * * * **
** * * * * Δημιούργησε χώρο για τη νέα λέξη Δημιούργησε χώρο για τη διεύθυνση της νέας λέξης Αποθήκευσε τη διεύθυνση της νέας λέξης 14
#include <stdio.h> #include <stdlib.h> #include <sting.h> #define CHARS 10 int main(int agc, *agv[]) { **mytext = NULL; int wods = 0; wod[chars] = ""; int i; ealloc while (scanf("%s", wod), stcmp(wod,"telos")) { wods++; mytext = ealloc(mytext, wods*sizeof( *)); mytext[wods-1] = malloc (CHARS*sizeof()); stcpy(mytext[wods-1], wod); fo (i=0; i<wods; i++) pintf("%s\n", mytext[i]); etun 0; 15
malloc #include <stdio.h> #include <stdlib.h> #include <sting.h> #define CHARS 10 int main(int agc, *agv[]) { **mytext = NULL; int wods = 0; *wod; int i; while (scanf("%s", wod=malloc(chars*sizeof())),stcmp(wod,"telos")) { wods++; mytext = ealloc(mytext, wods*sizeof( *)); mytext[wods-1] = wod; fo (i=0; i<wods; i++) pintf("%s\n", mytext[i]); etun 0; 16
Δυναμικές δομές δεδομένων Διασυνδεδεμένες λίστες Διαχείριση μνήμης (memoy management) 17
Στατικές και δυναμικές δομές δεδομένων Στατικές: θέση και μέγεθος καθορίζονται στη μεταγλ ώτ τιση. int aay[10]; Δυναμικές: θέση και μέγεθος καθορίζονται κατά την εκτέλεση. Απλούστερος τύπος: η λίστα Λίστα: Έτοιμη σε C++/Java, σε C γράφουμε κώδικα 18
Λίστες και στοιχεία τους Αρχή (όνομα) NULL 19
Eισαγωγή στοιχείου Αρχή (όνομα) NULL 20
Διαγραφή στοιχείου Αρχή (όνομα) NULL Τι γίνεται με τη μνήμη την οποία το στοιχείο καταλάμβανε; 21
Στοιχείο λίστας Δεδομένα προβλήματος #define N 10 stuct elem { value[ν]; int count ; stuct elem *next; ; typedef stuct elem Element; Θέση επόμενου στοιχείου 22
Χρήσιμοι συμβολισμοί stuct test { int a ; stuct test *next; atest, *atest_pt, *btest_pt; Διεύθυνση στοιχείου μετά το atest atest.next atest.a = 4; /* δείκτης σε δομή */ atest_pt = atest.next; btest_pt = &atest; (*btest_pt).a ++; /* το ίδιο με το προηγούμενο */ (btest_pt->a)++ ; 23
Αναφορά σε πολλά στοιχεία Με στατικό τρόπο stuct test atest, btest, ctest ; stuct test manytests[10] ; Ή δυναμικά Πώς μπορεί να δημιουργεί «μεταβλητές» την ώρα της εκτέλεσης; Βασική ιδέα: δε δημιουργεί νέα ονόματα μεταβλητών, Αλλά δεσμεύει αναλυτικά κατάλληλες περιοχές μνήμης και κρατάει αναφορές σε αυτές 24
Όχι πραγματική λίστα, ενδιάμεσο βήμα #include <stdio.h> #define L 30 stuct listelement { name[l]; int age; stuct listelement *next; ; typedef stuct listelement Listelement; int main(int agc, *agv[]) { /* Initialize */ Listelement c = { "Giannis", 5, NULL, b = { "Maia", 10, NULL, a = { "Vassilis", 3, NULL; Listelement *iteato; /* Connect to list*/ a.next = &b; b.next = &c; /* Access elements */ fo (iteato = &a; iteato!= NULL ; iteato = (*iteato).next) { pintf( "name: %s\n", (*iteato).name); pintf("age: %d\n", (*iteato).age); etun 0; 25
Απλοποιημένος συμβολισμός stuct mystuct *test; (*test).next test->next 26
(*iteato).next Listelement c = { "Giannis", 5, NULL, b = { "Maia", 10, NULL, a = { "Vassilis", 3, NULL; Listelement *iteato; a b c NULL NULL NULL a.next = &b; b.next = &c; iteato = &a iteato = &b iteato = &c fo (iteato = &a; iteato!= NULL ; iteato = iteato->next) 27
Λίστα Δεν χρησιμοποιήθηκαν τα ονόματα a, b, c για να επεξεργαστούμε τη λίστα! Αρκεί η διεύθυνση του πρώτου στοιχείου μόνο! Η διεύθυνση του επόμενου στοιχείου είναι iteato->next 28
Λίστα Στατική δήλωση Listelement c = { "Giannis", 5, NULL; Δυναμική δήλωση στοιχείου της λίστας Listelement *element_pt; element_pt = (Listelement *) malloc ( sizeof (Listelement)); stcpy((*element_pt).name,"ntina"); (*element_pt).age = 9; (*element_pt).next = NULL; Άλλος συμβολισμός, ενδεικτικά: element_pt->name αντί (*element_pt).name Listelement *element_pt; element_pt = (Listelement *) malloc ( sizeof (Listelement)); stcpy(element_pt->name,"ntina"); element_pt->age = 9; element_pt->next = NULL; 29
Παράδειγμα #include <stdio.h> #include <stdlib.h> #include <sting.h> #define L 30 stuct listelement { name[l]; int age; stuct listelement *next; ; typedef stuct listelement Listelement; typedef Listelement * Listelement_pt; int main(int agc, *agv[]) { /* Initialize */ Listelement_pt iteato=null, element_pt, pevious_pt, fist_pt; put them to list*/ element_pt = (Listelement_pt) malloc ( sizeof (Listelement)); stcpy(element_pt->name,"ntina"); element_pt -> age = 9; element_pt -> next = NULL; fist_pt = element_pt; pevious_pt = element_pt; element_pt = (Listelement_pt) malloc ( sizeof (Listelement)); stcpy(element_pt->name,"giannis"); element_pt -> age = 6 ; pevious_pt -> next = element_pt; /* Access elements */ fo (iteato = fist_pt; iteato!= NULL ; iteato = iteato->next) { pintf( "name: %s\n", iteato->name); pintf("age: %d\n", iteato->age); etun 0; /* ceate elements and 30
mytypes.h #define L 30 stuct listelement { name[l]; int age; stuct listelement *next; ; typedef stuct listelement Listelement; typedef Listelement * Listelement_pt; typedef Listelement * List; 31
#include <sting.h> #include <stdlib.h> #include "mytypes.h" Δημιουργία στοιχείου Listelement_pt ceatenewelement( wod[], int numbe) { Listelement_pt newelement_pt; newelement_pt = (Listelement_pt) malloc ( sizeof (Listelement)); stcpy(newelement_pt->name, wod); newelement_pt -> age = numbe; newelement_pt -> next = NULL; etun newelement_pt; 32
Διατρέχει όλα τα στοιχεία της λίστας #include <stdio.h> #include "mytypes.h" void epotlist(list const alist) { Listelement_pt iteato= alist; fo (; iteato!= NULL ; iteato = iteato->next) { pintf( "name: %s\n", iteato->name); pintf("age: %d\n", iteato->age); NULL 33
Προσθήκη στοιχείου στο τέλος λίστας NULL #include <stdio.h> #include "mytypes.h" Παράμετρος δείκτης σε λίστα ή διπλός δείκτης σε στοιχείο void addtolist (List *list, Listelement_pt elem_pt ) { Listelement_pt iteato = *list; if (*list==null) /* handle empty list*/ *list = elem_pt; else { /* if not empty, move to last element list*/ fo (; iteato->next!= NULL; iteato = iteato->next); /* append element to list */ iteato->next = elem_pt; Όταν βγει από το βρόχο, ο iteato δείχνει στο τελευταίο στοιχείο 34
Παράδειγμα #include <stdio.h> #include <stdlib.h> #include <sting.h> #include "mytypes.h Listelement_pt ceatenewelement( *, int); Listelement_pt findelementbyname(list, []); void epotlist( List const); void addtolist(list *, Listelement_pt); void deleteelement(list *, Listelement_pt); int main(int agc, *agv[]) { /* Initialize */ Listelement_pt iteato=null, element_pt, pevious_pt; List nameslist = NULL; name[50]; /* ceate elements and put them to list*/ element_pt = ceatenewelement("ntina", 10); addtolist (&nameslist, element_pt); element_pt = ceatenewelement("giannis", 5); addtolist( &nameslist, element_pt); element_pt = ceatenewelement("maia", 7); addtolist( &nameslist, element_pt); epotlist(nameslist); /* find, delete, epot */ do { pintf("name: "); scanf("%s", name); element_pt = findelementbyname(nameslist, name); if (element_pt) { pintf("found it. data: %d\n", element_pt->age); deleteelement(&nameslist, element_pt); epotlist(nameslist); while (nameslist!=null) ; etun 0; 35
Παράδειγμα #include <stdio.h> #include <stdlib.h> #include "mytypes.h" Παράμετρος: δείκτης σε λίστα ή διπλός δείκτης σε στοιχείο λίστας int deleteelement(list *alist, Listelement_pt element) { Listelement_pt iteato = *alist, todelete_pt; if (element == NULL *alist == NULL) etun -1 ; if (element== *alist) { /* if equied, delete fist element */ *alist = element->next ; fee(element); else { /* find the element befoe the one to be deleted */ fo(; iteato->next!= element; iteato = iteato->next) ; iteato->next = element->next; fee(element); etun 0; 36
Λίστες στη C #define N 10 stuct elem { value[ν]; int count ; stuct elem *next; ; typedef stuct elem Element; Τα στοιχεία της λίστας είναι τύπου Element int FindWod(const *, Element *); void AppendWod(const *, Element **); void DeleteWod(const *, Element **); void RepotList(Element * const); Element *CeateNode (void ); Υπάρχουν διαδικασίες που μπορεί να αλλάξουν την αρχική διεύθυνση (διαγραφή πρώτου στοιχείου, προσθήκη πρώτου στοιχείου) 37
Δέσμευση μνήμης για στοιχείο λίστας Element *CeateNode (void ) { etun (Element *) malloc (sizeof (Element)) ; 38
Προσθήκη στοιχείου στη λίστα void AppendWod(const *wod, Element **list_pt) { Element *item_iteato = *list_pt; Element *new_wod = CeateNode(); Αν η λίστα υπάρχει, να βάλεις το νέο στοιχείο στο τέλος if (*list_pt!=null) { fo( ; item_iteato->next!=null;item_iteato=item_iteato->next) ; item_iteato->next = new_wod; else { Αν η λίστα δεν υπάρχει, να είναι αυτό το πρώτο στοιχείο *list_pt = new_wod; stcpy(new_wod->value, wod); new_wod->next=null; 39
Παράδειγμα void RepotList(Element * const list) { Element *item_iteato = list; if (list == NULL) { pintf("empty list\n"); else { fo(;item_iteato!=null;item_iteato=item_iteato->next) pintf("wod: %s\n", item_iteato->value); 40
Αναζήτηση στη λίστα int FindWod(const *s, Element *alist) { Element *test = alist; int found = 0; while ((test->next!= NULL) &&(!found)) { pintf("%s ", test->value); found =!stcmp (s, test->value); if (found) (test->count)++; test = test->next; etun found; 41
Διαγραφή στοιχείου/αποδέσμευση μνήμης void DeleteWod(const *wod, Element **list_pt) { Element *test = *list_pt, *pev; int found = 0; pev = NULL; pintf("deleting...\n"); while ((test!= NULL) &&(!found)) { pintf("%s ", test->value); found =!stcmp (wod, test->value); if (found) (test->count)++; else { pev = test; test = test->next; if (found) { pintf("wod found: %s.\n", test->value); if (pev == NULL) *list_pt = test->next; else { pintf("pevious wod: %s\n", pev->value); pev->next = test->next; fee(test); 42
Σημείωμα αναφοράς Copyight Πανεπιστήμιο Πατρών, Παλιουράς Βασίλειος, Δερματάς Ευάγγελος «Αρχές Προγραμματισμού». Έκδοση: 1.0. Πάτρα 2015 Διαθέσιμο από τη δικτυακιακή διέυθυνση https://eclass.upatas.g/modules/ 43