Προγραµµατισµός Ι 1

Σχετικά έγγραφα
Προγραμματισμός Ι (ΗΥ120)

Δυναμική δέσμευση και αποδέσμευση μνήμης. Προγραμματισμός II 1

Προγραμμαηιζμός Ι ( ΗΥ120 )

Σύνθετοι Τύποι εδοµένων. Προγραµµατισµός Ι 1

Προγραμματισμός Ι (ΗΥ120)

Ανάπτυξη και Σχεδίαση Λογισμικού

Διάλεξη 13η: Δυναμική Διαχείρηση Μνήμης, μέρος 1

Προγραμματισμός Ι (ΗΥ120)

Προγραμματισμός Ι. Δυναμική Διαχείριση Μνήμης. Δημήτρης Μιχαήλ. Ακ. Έτος Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Προγραμματισμός Ι (ΗΥ120)

int a[5]; a[0] a[1] a[2] a[3] a[4] 15/10/2009

Εισαγωγή στον Προγραμματισμό

Προγραμματισμός Ι (ΗΥ120)

Διάλεξη 9: Δυναμική Δέσμευση Μνήμης

Η γλώσσα προγραμματισμού C Δυναμική διαχείριση μνήμης

Προγραμματισμός Η/Υ (ΤΛ2007 )

Βιβλιοθήκες Αφηρημένοι τύποι δεδομένων. Προγραμματισμός II 1

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Α' Περιόδου Θέµα 1. (α') 2 - ii 3 - iii 4 - iv

Διαδικασιακός Προγραμματισμός

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δυναμική Δέσμευση Μνήμης (Κεφάλαιο , KNK-2ED)

Εισαγωγή στον δομημένο προγραμματισμό

Α. unsigned int Β. double. Γ. int. unsigned char x = 1; x = x + x ; x = x * x ; x = x ^ x ; printf("%u\n", x); Β. unsigned char

ιαφάνειες παρουσίασης #5 (β)

ΠΛΗ111. Ανοιξη Μάθηµα 1 ο Ανασκόπηση της Γλώσσας Προγραµµατισµού C. Τµήµα Ηλεκτρονικών Μηχανικών και Μηχανικών Υπολογιστών Πολυτεχνείο Κρήτης

Δομημένος Προγραμματισμός. Τμήμα Επιχειρηματικού Σχεδιασμού και Πληροφοριακών Συστημάτων

Σημειώσεις έκτης και έβδομης εβδομάδας

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Περιεχόμενα. Πρόλογος... 21

Προγραμματισμός Η/Υ (ΤΛ2007 )

Εισαγωγή στον Προγραμματισμό (με. τη C)

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

FILE *fopen(const char *fname, const char *mode) void fclose(file *f) void fflush(file *f)

Η γλώσσα C. Δείκτες και Διαχείριση Μνήμης (memory management)

Επεξεργασία Αρχείων Κειµένου

Ανάπτυξη και Σχεδίαση Λογισμικού

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Προγραμματισμός Ι (ΗΥ120)

υναµική έσµευση Μνήµης (συν.) ΕΠΛ 132 Αρχές Προγραµµατισµού ΙΙ 2 Εφαρµογή

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Ι Αρχεία δεδομένων, μέρος δεύτερο: δυαδικά αρχεία ΙΙ Δομές δεδομένων (struct)

Δείκτες (Pointers) Ένας δείκτης είναι μια μεταβλητή με τιμή μια διεύθυνση μνήμης. 9.8

#include <stdlib.h> Α. [-128,127] Β. [-127,128] Γ. [-128,128]

Δομημένος Προγραμματισμός (ΤΛ1006)

Ενδεικτική περιγραφή μαθήματος

Κεφάλαιο Αλφαριθµητικές Σειρές Χαρακτήρων (Strings)

Δομημένος Προγραμματισμός (ΤΛ1006)

Ορισμός μεταβλητών δεικτών και αρχικοποίηση

Διδάσκων: Παναγιώτης Ανδρέου

Γλώσσα Προγραμματισμού C

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #5

Ενώσεις δεδομένων Απαριθμητές Ψηφιακοί τελεστές Αναδρομικές συναρτήσεις

υναµικές οµές εδοµένων

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ακαδημαϊκό έτος ΤΕΤΡΑΔΙΟ ΕΡΓΑΣΤΗΡΙΟΥ #4

H ΓΛΩΣΣΑ C. Μάθηµα 12: υναµική έσµευση Μνήµης. ηµήτρης Ψούνης

Φροντιστήριο 4 Σκελετοί Λύσεων

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Εισαγωγή στον Προγραµµατισµό. Διάλεξη 2 η : Βασικές Έννοιες της γλώσσας προγραµµατισµού C Χειµερινό Εξάµηνο 2011

Α' Εξάμηνο ΕΙΣΑΓΩΓΗ ΣΤΟ ΔΟΜΗΜΕΝΟ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Α Β Γ static; printf("%c\n", putchar( A +1)+2); B DB BD. int i = 0; while (++i); printf("*");

Διάλεξη 3η: Τύποι Μεταβλητών, Τελεστές, Είσοδος/Έξοδος

Προγραμματισμός Ι. Δείκτες. Δημήτρης Μιχαήλ. Τμήμα Πληροφορικής και Τηλεματικής Χαροκόπειο Πανεπιστήμιο

Κλήση Συναρτήσεων ΚΛΗΣΗ ΣΥΝΑΡΤΗΣΕΩΝ. Γεώργιος Παπαϊωάννου ( )

Οι δείκτες στη γλώσσα C

είκτες και Πίνακες (2)

ΕΠΛ232 Προγραμματιστικές Τεχνικές και Εργαλεία Δυναμική Δέσμευση Μνήμης και Δομές Δεδομένων (Φροντιστήριο)

Πανεπιστήµιο Θεσσαλίας, THMMY HY120, Σεπτέµβριος 2015 ΟΝΟΜΑΤΕΠΩΝΥΜΟ:

Αρχεία εδοµένων. Προγραµµατισµός Ι 1

Κεφάλαιο Αλφαριθμητικές Σειρές Χαρακτήρων (Strings) (Διάλεξη 20) 1) Strings στη C

Περιεχόμενα. Πρόλογος... 17

Πίνακες: μια σύντομη εισαγωγή. Πίνακες χαρακτήρων: τα "Αλφαριθμητικά"

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Δομές δεδομένων (2) Αλγόριθμοι

Διδάσκων: Παναγιώτης Ανδρέου

Sheet2 Α.Μ FAIL. οριακό PASS. - Έπρεπε να χρησιµοποιήσετε συναρτήσεις από τη string.h

Προγραµµατισµός Ι (ΗΥ120)

Προγραμματισμός Ι (ΗΥ120)

Διδάσκων: Κωνσταντίνος Κώστα Διαφάνειες: Δημήτρης Ζεϊναλιπούρ

ΑΡΧΕΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ

Αρχές Προγραμματισμού

Διασυνδεδεμένες Δομές. Λίστες. Προγραμματισμός II 1

Προγραμματισμός Υπολογιστών με C++

Διάλεξη 18η: Διαχείρηση Αρχείων

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

υναµικές οµές εδοµένων (συν.) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα:

οµές (structures) Στην ενότητα αυτή θα µελετηθούν τα εξής επιµέρους θέµατα: Πίνακες δοµών, δείκτες σε δοµές, και αυτοαναφορικές δοµές.

(programming interfaceή/και application programming interface API).

Εισαγωγή στον Προγραµµατισµό. Πανεπιστήµιο Θεσσαλίας Τµήµα Ηλεκτρολόγων Μηχανικών και Μηχανικών Η/Υ

C: Από τη Θεωρία στην Εφαρμογή

ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Ενδεικτικές Απαντήσεις Εξετάσεων Β' Περιόδου Θέµα 1. (α')

Μεθόδων Επίλυσης Προβλημάτων

Εισαγωγή στους Η/Υ. Γιώργος Δημητρίου. Μάθημα 3-4: Προγραμματισμός MIPS. Πανεπιστήμιο Θεσσαλίας - Τμήμα Πληροφορικής

Κεφάλαιο , 3.2: Συναρτήσεις II. ( ιάλεξη 12) ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Π. Σταθοπούλου ή Οµάδα Α (Φοιτητές µε µονό αριθµό Μητρώου ) ιδασκαλία : Παρασκευή 11πµ-13µµ ΗΛ7

Προγραμματισμός Ι (ΗΥ120)

Προγραμματισμός Ι (HY120)

ΗΥ-150. Προγραµµατισµός. υναµική ιαχείριση Μνήµης (1/2)

Προγραμματισμός Δομές Δεδομένων

Transcript:

υναµική µνήµη Προγραµµατισµός Ι lalis@inf.uth.gr 1

υναµική µνήµη προγράµµατος Πολλές φορές, δεν γνωρίζουµε εκ των προτέρων πόση µνήµη θα χρειαστεί το πρόγραµµα µας. Αν δεσµεύσουµε περισσότερη µνήµη από αυτή που θα χρειαστεί, καταναλώνουµε άσκοπα πόρους του Η/Υ, διαφορετικά περιορίζουµε την λειτουργικότητα του προγράµµατος µας. Εκτός από την στατική (καθολική) µνήµη (και την στοίβα), υπάρχει και η δυναµική µνήµη. Ο προγραµµατιστής µπορεί να δεσµεύσει και να αποδεσµεύσει δυναµική µνήµη κατά την διάρκεια της εκτέλεσης, ανάλογα µε τις(µεταβαλλόµενες) τρέχουσες απαιτήσεις του προγράµµατος. Προγραµµατισµός Ι lalis@inf.uth.gr 2

Σχετικές συναρτήσεις και βιβλιοθήκες #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t n, size_t size); void *realloc(void *p, size_t size); int free(void *p); #include <memory.h> void *memcpy(void *dst, const void *src, size_t n); void memset(void *p, int c, size_t n); int memcmp(const void *p1, const void *p2, size_t n); #include <string.h> char *strdup(const char *s); Προγραµµατισµός Ι lalis@inf.uth.gr 3

Κύριες συναρτήσεις void *malloc(size_t n) δέσµευση ενός συνεχόµενου τµήµατος µνήµης και επιστροφή διεύθυνσης της αρχής του τµήµατος (αν δεν υπάρχει αρκετή µνήµη, επιστρέφεται 0 / NULL) void free(void *adr) αποδέσµευση της µνήµης στη διεύθυνση που δίνεται void *realloc(void *adr, size_t n) αναπροσαρµογή του τµήµατος µνήµης (µε πιθανή αντιγραφή των περιεχοµένων) η διεύθυνση του οποίου δίνεται σαν παράµετρος, και επιστροφή διεύθυνσης της αρχής του (νέου) τµήµατος (αν δεν υπάρχει αρκετή µνήµη, επιστρέφεται 0 / NULL) Προγραµµατισµός Ι lalis@inf.uth.gr 4

Χρήση δυναµικής µνήµης Οι ρουτίνες διαχείρισης δυναµικής µνήµης δεν γνωρίζουν τίποτα σχετικά µε τους τύπους των δεδοµένων που χρησιµοποιεί το πρόγραµµα. Η διεύθυνση που επιστρέφεται χρησιµοποιείται µε αποκλειστική ευθύνη του προγραµµατιστή. Κλασική χρήση: δέσµευση χώρου που αντιστοιχεί στο µέγεθος ενός αντικειµένου τύπου Τ και ανάθεση της διεύθυνσης (µε type casting) σε µια µεταβλητή τύπου δείκτη-σε-τ για ελεγχόµενηπρόσβασηστηνµνήµη. Ο προγραµµατιστής είναι υπεύθυνος για την αποδέσµευση δυναµικής µνήµης που δεν χρησιµοποιεί το πρόγραµµα διαφορετικά υπάρχει περίπτωση τερµατισµού λόγω µη επάρκειας µνήµης. Προγραµµατισµός Ι lalis@inf.uth.gr 5

Έλεγχος τιµής που επιστρέφεται Οι malloc και realloc επιστρέφουν NULL αν δεν µπορεί να δεσµευτεί όση µνήµη ζητήθηκε. Η τιµή επιστροφής πρέπει να ελέγχεται (αυτό δεν γίνεται στα παραδείγµατα για οικονοµία χώρου). ιαφορετικά, αν η τιµή NULL ανατεθεί σε δείκτη, ηεπόµενη αναφορά στη µνήµη µέσω του δείκτη θα οδηγήσει σε τερµατισµό του προγράµµατος. Πρόβληµα 1: µπορεί να µην επιθυµούµε ένα τέτοιο «απότοµο» τερµατισµό (π.χ. χάσιµο δεδοµένων). Πρόβληµα 2: δεν γνωρίζουµε σε ποιό σηµείο του προγράµµατος έγινε αυτή η αναφορά. Προγραµµατισµός Ι lalis@inf.uth.gr 6

#include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int a,b,*c; δέσµευση µνήµης από scanf("%d %d",&a,&b); sizeof(int) bytes c = (int *) malloc( sizeof(int) ); if (c == NULL) { printf("no memory\n"); return; *c = a+b; type cast σε δείκτη-σε-ακέραιο printf("%d\n",*c); free(c); αποδέσµευση µνήµης Προγραµµατισµός Ι lalis@inf.uth.gr 7

Μονιµότητα δυναµικής µνήµης Ηδυναµική µνήµη είναιµόνιµη, δηλαδή υφίσταται καθ όλη τη διάρκεια της εκτέλεσης του προγράµµατος. υναµική µνήµη που δεσµεύεται µέσα από µια συνάρτηση παραµένει εν ισχύ µετά την κλήση της. Άλλος ένας τρόπος επιστροφής αποτελεσµάτων στο περιβάλλον κλήσης µιας συνάρτησης. 1. Ησυνάρτησηδεσµεύει δυναµική µνήµη όπου αποθηκεύει τα δεδοµένα που επιθυµεί να επιστρέψει. 2. Η συνάρτηση επιστρέφει σαν αποτέλεσµα την διεύθυνση του µπλοκ της µνήµης. 3. Το περιβάλλον κλήσης χρησιµοποιεί την διεύθυνση όπως απαιτείται ανάθεση σε κατάλληλη µεταβλητή δείκτη, αποδέσµευση µετά την χρήση, κλπ. Προγραµµατισµός Ι lalis@inf.uth.gr 8

#include <stdio.h> #include <stdlib.h> int *add(int a, int b) { int *c = (int *)malloc(sizeof(int)); *c = a+b; return(c); int main(int argc, char *argv[]) { int a,b,*c; scanf("%d %d",&a,&b); c = add(a,b); printf("%d\n",*c); free(c); Προγραµµατισµός Ι lalis@inf.uth.gr 9

#include <stdio.h> int *add(int a, int b) { int c; c = a+b; return(&c); /* αυτό είναι λάθος! */ int f(int a, int b) { int c = 0; int main(int argc, char *argv[]) { int a,b,*c; scanf("%d %d",&a,&b); c = add(a,b); f(a,b); printf("%d\n",*c); Προγραµµατισµός Ι lalis@inf.uth.gr 10

#include <stdio.h> #include <stdlib.h> char *strappend(const char *s1, const char *s2) { int i,j,len1,len2; char *s3; for (len1=0; s1[len1]!='\0'; len1++); for (len2=0; s2[len2]!='\0'; len2++); s3=(char *)malloc((len1+len2+1)*sizeof(char)); for (i=0; i<len1; i++) { s3[i]=s1[i]; for (j=0; j<len2; j++,i++) { s3[i]=s2[j]; s3[i]='\0'; return(s3); int main(int argc, char *argv[]) { char s1[64],s2[64],*s3; scanf("%63s %63s",s1,s2); s3=strappend(s1,s2); printf("%s plus %s is %s\n",s1,s2,s3); free(s3); Προγραµµατισµός Ι lalis@inf.uth.gr 11

υναµικοί πίνακες Με χρήση δυναµικής µνήµης µπορεί να υλοποιηθούν δυναµικοί πίνακες, το µέγεθος των οποίων ορίζεται (αλλάζει) κατά την διάρκεια της εκτέλεσης. 1. εσµεύεται µε malloc ή realloc δυναµική µνήµη µεγέθους n*sizeof(t), και η διεύθυνση που επιστρέφεται αποθηκεύεται σε µεταβλητή δείκτη σε Τ. 2. Αν το n αποδειχθεί µικρό ή µεγάλο, χρησιµοποιείται η realloc για την επέκταση / αποκοπή του πίνακα. 3. Όταν ο πίνακας δεν χρειάζεται, αποδεσµεύεται η µνήµη πουχρησιµοποιείται µε τηνfree. Σηµείωση: αυτή η τεχνική ισχύει για την υλοποίηση ανοιχτών πινάκων οποιουδήποτε τύπου T. Προγραµµατισµός Ι lalis@inf.uth.gr 12

#include <stdlib.h> char *t; int tlen; void init_array() { t=null; tlen=0; void trim_array(int len) { t=(char*)realloc(t,len*sizeof(char)); tlen=len; void write_array(int pos, char v) { if (pos >= tlen) { trim(pos+1); t[pos]=v; char read_array(int pos) { return(t[pos]); void destroy_array() { trim(0); t=null; Προγραµµατισµός Ι lalis@inf.uth.gr 13

#include <stdlib.h> void **t; int tlen; void init_array() { t=null; tlen=0; void trim_array(int len) { t=(void**)realloc(t,len*sizeof(void*)); tlen=len; void write_array(int pos, void *v) { if (pos >= tlen) { trim(pos+1); t[pos]=v; void *read_array(int pos) { return(t[pos]); void destroy_array() { trim(0); t=null; Προγραµµατισµός Ι lalis@inf.uth.gr 14

int main(int argc, char *argv[]) { char s[256],*p; int i; init_array(); i = 0; do { scanf("%255s",s); write_array(i,(void*)strdup(s)); i++; while (strcmp(s,"end")); for (; i>0; i--) { p = (char*)read_array(i); printf("%s\n",p); free(p); destroy_array(); ελευθερώνει τη (δυναµική) µνήµη που δεσµεύτηκε δηµιουργεί αντίγραφο του αλφαριθµητικού (σε δυναµική µνήµη) type cast (από char * που επιστρέφεται) σε void * που αναµένει η συνάρτηση write type cast (από void * που επιστρέφεται) σε char * που είναι οτύποςτηςp Προγραµµατισµός Ι lalis@inf.uth.gr 15

υναµική δέσµευση δοµών δεδοµένων Με χρήση δυναµικής µνήµης µπορεί να δεσµευτούν χώροι µνήµης για την αποθήκευση struct/union κατά την διάρκεια της εκτέλεσης του προγράµµατος. Ηδέσµευση και αποδέσµευση δυναµικής µνήµης ακολουθεί τους ίδιους κανόνες που ισχύουν και για τους βασικούς τύπους δεδοµένων. Κατά την δέσµευση πρέπει να δίνεται το επιθυµητό µέγεθος, µέσω sizeof, και η δεσµευµένη µνήµη πρέπει να αποδεσµεύεται όταν δεν είναι αναγκαία. Πρόσβαση στην δυναµικά δεσµευµένη µνήµη γίνεται µέσω µεταβλητών δεικτών που πρέπει να αρχικοποιούνται κατάλληλα. Προγραµµατισµός Ι lalis@inf.uth.gr 16

Παρένθεση (βάση δεδοµένων µε δυναµικό πίνακα) Προγραµµατισµός Ι lalis@inf.uth.gr 17

Πρόβληµα Ζητούµενο: επιθυµούµε να διαχειριστούµε τα περιεχόµενα της τηλεφωνικής µας αντζέντας, µε αντίστοιχες λειτουργίες προσθήκης, αποµάκρυνσης και αναζήτησης. Προσέγγιση ορίζουµε δοµή κατάλληλη για την οµαδοποίηση των δεδοµένων που ανήκουν σε µια «εισαγωγής» κρατάµε ταδεδοµένα σε ανοιχτό πίνακα από τέτοιες δοµές Οι λειτουργίες πρέπει να υλοποιηθούν σύµφωνα µε κατάλληλες εσωτερικές συµβάσεις για την διαχείριση των στοιχείων του πίνακα. Προγραµµατισµός Ι lalis@inf.uth.gr 18

το µέγεθος του πίνακα αλλάζει δυναµικά ως συνέπεια των λειτουργιών προσθήκης ή/και αποµάκρυνσης δεδοµένων αποµάκρυνση n προσθήκη στοιχεία υπό χρήση Προγραµµατισµός Ι lalis@inf.uth.gr 19

int main(int argc, char *argv[]) { int s,res; char name[64],phone[64]; phonebook_init(); do { printf("1. Add\n"); printf("2. Remove\n"); printf("3. Find\n"); printf("4. Exit\n"); printf("> "); scanf("%d",&s); switch (s) { case 1: { printf("name & phone:"); scanf("%63s %63s",name,phone); res=phonebook_add(name,phone); printf("res=%d\n",res); break; case 2: { printf("name:"); scanf("%63s",name); phonebook_rmv(name); break; case 3: { printf("name:"); scanf("%63s",name); res=phonebook_find(name,phone); printf("res=%d\n",res); if (res) { printf("phone: %s\n",phone); break; Προγραµµατισµός Ι lalis@inf.uth.gr 20 while (s!=4);

#include <stdio.h> #include <string.h> #include <stdlib.h> typedef { char name[64]; char phone[64]; Entry; η µεταβλητή entries είναι δείκτης σε Entry, και χρησιµεύει ως η αρχή ενός δυναµικού πίνακα από δοµές Entry Entry *entries; int n; void phonebook_init() { entries=null; n=0; Προγραµµατισµός Ι lalis@inf.uth.gr 21

int internal_find(const char name[]) { int i; for (i=0; (i<n) && (strcmp(entries[i].name,name)); i++); return(i); int phonebook_find(const char name[], char phone[]) { int i; i=internal_find(name); if (i == n) { return(0); else { strcpy(phone,entries[i].phone); return(1); void phonebook_rmv(const char name[]) { int i; i=internal_find(name); if (i < n) { memcopy(&entries[i],&entries[n-1],sizeof(entry)); n--; entries=(entry *) realloc(entries,n*sizeof(entry)); Προγραµµατισµός Ι lalis@inf.uth.gr 22

int phonebook_add(const char name[], const char phone[]) { int i; i=internal_find(name); if (i < n) { strcpy(entries[i].phone,phone); return(-1); /* replace */ n++; entries=(entry *) realloc(entries,n*sizeof(entry)); strcpy(entries[n-1].name,name); strcpy(entries[n-1].phone,phone); return(1); /* done */ Προγραµµατισµός Ι lalis@inf.uth.gr 23

Σχόλιο Κάθε φορά που αποµακρύνεται ένα στοιχείο, γίνεται µια αντιγραφή δεδοµένων από την τελευταία θέση του πίνακα στην θέση που ελευθερώθηκε. Αυτό µπορεί να είναι ιδιαίτερα χρονοβόρο (αν τα περιεχόµενα της δοµής είναι µεγάλα σε µέγεθος). Μπορούµε νααποφύγουµε αυτή την αντιγραφή δεδοµένων, χρησιµοποιώντας ένα πίνακα από δείκτες σε (αυτόνοµα) αντικείµενα δεδοµένων η µνήµη των οποίων δεσµεύεται και αποδεσµεύεται δυναµικάκατάτηνπροσθήκη/ αποµάκρυνση τους. Με αυτό το τρόπο ο πίνακας µετατρέπεται σε ένα ευρετήριο από δείκτες σε αντικείµενα, επιτρέποντας πολύ γρήγορες «αντιµεταθέσεις» στοιχείων. Προγραµµατισµός Ι lalis@inf.uth.gr 24

n Προγραµµατισµός Ι lalis@inf.uth.gr 25

#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { char name[64]; char phone[64]; Entry; η µεταβλητή entries είναι δείκτης σε δείκτη σε Entry, και χρησιµεύει ως η αρχή ενός δυναµικού πίνακα από δείκτες σε Entry Entry **entries; int n; void phonebook_init() { entries=null; n=0; Προγραµµατισµός Ι lalis@inf.uth.gr 26

int internal_find(const char name[]) { int i; for (i=0; (i<n) && (strcmp(entries[i]->name,name); i++); return(i); int phonebook_find(const char name[], char phone[]) { int i; i=internal_find(name); if (i == n) { return(0); else { strcpy(phone,entries[i]->phone); return(1); void phonebook_rmv(const char name[]) { int i; i=internal_find(name); if (i < n) { free(entries[i]); entries[i] = entries[n-1]; n--; entries=(entry **) realloc(entries,n*sizeof(entry *)); Προγραµµατισµός Ι lalis@inf.uth.gr 27

int phonebook_add(const char name[], const char phone[]) { int i; i=internal_find(name); if (i < n) { strcpy(entries[i]->phone,phone); return(-1); /* replace */ n++; entries=(entry **) realloc(entries,n*sizeof(entry *)); entries[n-1] = (Entry *) malloc(sizeof(entry)); strcpy(entries[n-1]->name,name); strcpy(entries[n-1]->phone,phone); return(1); /* done */ Προγραµµατισµός Ι lalis@inf.uth.gr 28

Παρένθεση (βάση δεδοµένων µε δυναµικό πίνακα) Προγραµµατισµός Ι lalis@inf.uth.gr 29