Δυναμική κατανομή μνήμης Ιωάννης Γ. Τσ ούλος 2014 1 Χρήσ η δεικτών Οι δείκτες μπορούν να χρησ ιμοποιηθούν προκειμένου να αναφερθούν σ ε διευθύνσ εις μεταβλητών και όχι απευθείας σ τις ίδιες τις μεταβλητές. Με αυτόν τον τρόπο μπορούν να επισ τρέψουν από σ υνάρτησ η παραμέτρους με διαφορετικές τιμές από ότι έχουν σ την είσ οδο όπως παρουσ ιάζεται και σ το επόμενο παράδειγμα. 2 using namespace s t d ; 3 void swap1 ( int x, int y ) 4 { 5 int t=x ; 6 x=y ; 7 y=t ; 8 } 9 10 void swap2 ( int x, int y ) 11 { 12 int t= x ; 13 x= y ; 14 y=t ; 15 } 16 17 int main ( ) 18 { 19 int a =100, b=200; 20 cout<<" B e f o r e swap "<<a<<" "<<b<<e n d l ; 21 swap1 ( a, b ) ; 22 cout<<" A f t e r swap1 "<<a<<" "<<b<<e n d l ; 23 swap2(&a,&b ) ; 24 cout<<" A f t e r swap2 "<<a<<" "<<b<<e n d l ; 25 return 0 ; 26 } 1
2 Δυναμικοί πίνακες Επιπλέον μπορούμε να χρησ ιμοποιήσ ουμε δείκτες και σ την δυναμική δημιουργία μεταβλητών. Συνήθως αυτό γίνεται για την δημιουργία δυναμικών πινάκων, όπως παρουσ ιάζεται και σ το επόμενο παράδειγμα, σ το οποίο δημιουργούμε έναν δυναμικό πίνακα, διαβάζουμε τα σ τοιχεία του, βρίσ κουμε το μεγαλύτερο σ τοιχείο σ τον πίνακα και εμφανίζουμε τον πίνακα και το μεγαλύτερο σ τοιχείο σ ε αυτόν. 2 using namespace s t d ; 3 4 void readarray ( int x, int s i z e ) 5 { 6 int i ; 7 for ( i =0; i <s i z e ; i ++) 8 { 9 cout<<" Enter element at "<<i <<e n d l ; 10 c in >>x [ i ] ; 11 } 12 } 13 14 void p r i n t A r r a y ( int x, int s i z e ) 15 { 16 int i ; 17 for ( i =0; i <s i z e ; i ++) 18 cout<<"x [ "<<i <<"]="<<x [ i ]<< e n d l ; 19 } 20 21 int maxarray ( int x, int s i z e ) 22 { 23 int i ; 24 int max=x [ 0 ] ; 25 for ( i =1; i <s i z e ; i ++) 26 i f ( x [ i ]>max) 27 max=x [ i ] ; 28 return max ; 29 } 30 31 int main ( ) 32 { 33 int mytable ; 34 int N; 35 int max ; 36 cout<<"how many e l e m e n t s? " ; 37 c in >>N; 38 mytable=new int [ N ] ; 2
39 readarray ( mytable,n) ; 40 max=maxarray ( mytable,n) ; 41 p r i n t A r r a y ( mytable,n) ; 42 cout<<"maximume element i s "<<max<<e n d l ; 43 delete [ ] mytable ; 44 return 0 ; 45 } Η διαγραφή δυναμικών πινάκων γίνεται πάντοτε με την χρήσ η του τελεσ τή delete[]. 3 Κατηγορία με δυναμικά πεδία Στην σ υνέχεια παρουσ ιάζεται μια κατηγορία με το όνομα Person για την περιγραφή ανθρώπων. Στα ιδιωτικά πεδία της κατηγορίας υπάρχουν το όνομα και το επίθετο του ατόμου σ ε μορφή δυναμικού πίνακα. Χρησ ιμοποιείται η βιβλιοθήκη string.h με τις αντίσ τοιχες σ υναρτήσ εις: strlen(x) επισ τρέφει το μήκος του αλφαριθμητικού x strcpy(x,y) αναθέτει σ το αλφαριθμητικό x το αλφαριθμητικό y strcmp(x,y) αν τα δύο αλφαριθμητικά είναι ίδια επισ τρέφει 0, αν το πρώτο είναι πιο μετά (λεξικογραφικά) επισ τρέφει θετικό αριθμό αλλιώς αρνητικό αριθμό. 2 # include <s t r i n g. h> 3 using namespace s t d ; 4 5 class Person 6 { 7 private : 8 char name, lastname ; 9 public : 10 Person ( char n, char l ) ; 11 char getname ( ) const ; 12 char getlastname ( ) const ; 13 void d i s p l a y P e r s o n ( ) const ; 14 bool compareperson ( Person &o t h e r ) ; 15 ~Person ( ) ; 16 } ; 17 18 Person : : Person ( char n, char l ) 19 { 20 name=new char [ s t r l e n ( n ) + 1 ] ; 21 lastname=new char [ s t r l e n ( l ) + 1 ] ; 22 s t r c p y ( name, n ) ; 3
23 s t r c p y ( lastname, l ) ; 24 } 25 26 char Person : : getname ( ) const 27 { 28 return name ; 29 } 30 31 char Person : : getlastname ( ) const 32 { 33 return lastname ; 34 } 35 36 37 void Person : : d i s p l a y P e r s o n ( ) const 38 { 39 cout<<"name : "<<name<<", lastname : "<<lastname<<e n d l ; 40 } 41 42 bool Person : : compareperson ( Person &o t h e r ) 43 { 44 i f (! strcmp ( name, o t h e r. getname ( ) ) 45 &&! strcmp ( lastname, o t h e r. getlastname ( ) ) ) 46 return true ; 47 else 48 return f a l s e ; 49 } 50 51 Person : : ~ Person ( ) 52 { 53 delete [ ] name ; 54 delete [ ] lastname ; 55 } 56 57 int main ( ) 58 { 59 Person p e r s o n 1 ( " G i a n n i s ", " T s o u l o s " ) ; 60 Person p e r s o n 2 ( " G i a n n i s ", " Pappas " ) ; 61 p e r s o n 1. d i s p l a y P e r s o n ( ) ; 62 p e r s o n 2. d i s p l a y P e r s o n ( ) ; 63 i f ( p e r s o n 1. compareperson ( p e r s o n 2 ) ) 64 cout<<"same p e r s o n s "<<e n d l ; 65 else 66 cout<<" D i f f e r e n t p e r s o n s "<<e n d l ; 67 return 0 ; 68 } 4
4 Δυναμικά αντικείμενα Στην σ υνέχεια παρουσ ιάζεται η χρήσ η δεικτών για την υλοποίησ η δυναμικών αντικειμένων. Και πάλι χρησ ιμοποιείται ο τελεσ τής new (χωρίς τα [ ]) για την δημιουργία του δυναμικού αντικειμένου και ο τελεσ τής delete ( χωρίς τα [ ]) για την διαγραφή των αντικειμένων. Για την πρόσ βασ η σ τις μεθόδους της κατηγορίας χρησ ιμοποιείται ο τελεσ τής ->. 2 # include <s t r i n g. h> 3 using namespace s t d ; 4 5 class Employee 6 { 7 private : 8 char name ; 9 char lastname ; 10 double s a l a r y ; 11 public : 12 Employee ( char n, char l, double s ) ; 13 double g e t S a l a r y ( ) const ; 14 void p r i n t ( ) ; 15 ~Employee ( ) ; 16 } ; 17 18 Employee : : Employee ( char n, char l, double s ) 19 { 20 name=new char [ s t r l e n ( n ) + 1 ] ; 21 lastname=new char [ s t r l e n ( l ) + 1 ] ; 22 s t r c p y ( name, n ) ; 23 s t r c p y ( lastname, l ) ; 24 s a l a r y=s ; 25 } 26 27 double Employee : : g e t S a l a r y ( ) const 28 { 29 return s a l a r y ; 30 } 31 32 void Employee : : p r i n t ( ) 33 { 34 cout<<"name : "<<name<<" l as t na me : "<<lastname<< 35 " s a l a r y : "<<s a l a r y <<e n d l ; 36 } 37 38 Employee : : ~ Employee ( ) 5
39 { 40 delete [ ] name ; 41 delete [ ] lastname ; 42 } 43 44 int main ( ) 45 { 46 Employee emp [ 5 ] ; 47 int i ; 48 double a v e r a g e = 0. 0 ; 49 char name [ 8 0 ] ; 50 char lastname [ 8 0 ] ; 51 double s a l a r y ; 52 53 for ( i =0; i <5; i ++) 54 { 55 cout<<" Enter name "<<e n d l ; 56 c in >>name ; 57 cout<<" Enter lastname "<<e n d l ; 58 c in >>lastname ; 59 cout<<" Enter s a l a r y "<<e n d l ; 60 c in >>s a l a r y ; 61 emp [ i ]=new Employee ( name, lastname, s a l a r y ) ; 62 a v e r a g e=a v e r a g e+emp [ i ] > g e t S a l a r y ( ) ; 63 } 64 a v e r a g e=a v e r a g e / 5 ; 65 cout<<" Average s a l a r y i s "<<average<<e n d l ; 66 for ( i =0; i <5; i ++) 67 { 68 delete emp [ i ] ; 69 } 70 return 0 ; 71 } 5 Κατηγορία δυναμικού αλφαριθμητικού Στην σ υνέχεια παρουσ ιάζεται μια ολοκληρωμένη υλοποίησ η του δυναμικού αλφαριθμητικού με μια σ ειρά από μεθόδους. 2 # include <s t r i n g. h> 3 using namespace s t d ; 4 5 class S t r i n g 6 { 6
7 private : 8 char data ; 9 public : 10 S t r i n g ( ) ; 11 S t r i n g ( char d ) ; 12 int s i z e ( ) const ; 13 char charat ( int pos ) const ; 14 char getdata ( ) const ; 15 bool e q u a l s ( S t r i n g &o t h e r ) ; 16 S t r i n g s u b S t r i n g ( int s t a r t, int end ) ; 17 void p r i n t ( ) ; 18 ~ S t r i n g ( ) ; 19 } ; 20 21 S t r i n g : : S t r i n g ( ) 22 { 23 data=new char [ 2 ] ; 24 s t r c p y ( data, "" ) ; 25 } 26 27 S t r i n g : : S t r i n g ( char d ) 28 { 29 data=new char [ s t r l e n ( d ) + 1 ] ; 30 s t r c p y ( data, d ) ; 31 } 32 33 int S t r i n g : : s i z e ( ) const 34 { 35 return s t r l e n ( data ) ; 36 } 37 38 char S t r i n g : : charat ( int pos ) const 39 { 40 i f ( pos <0 pos>=s t r l e n ( data ) ) return ' ' ; 41 return data [ pos ] ; 42 } 43 44 char S t r i n g : : getdata ( ) const 45 { 46 return data ; 47 } 48 49 bool S t r i n g : : e q u a l s ( S t r i n g &o t h e r ) 50 { 51 i f (! strcmp ( data, o t h e r. getdata ( ) ) ) return true ; 52 else 7
53 return f a l s e ; 54 } 55 56 57 S t r i n g S t r i n g : : s u b S t r i n g ( int s t a r t, int end ) 58 { 59 char newdata=new char [ end s t a r t + 2 ] ; 60 int i c o u n t =0, i ; 61 for ( i=s t a r t ; i<=end ; i ++) 62 { 63 newdata [ i c o u n t ]= data [ i ] ; 64 i c o u n t ++; 65 } 66 newdata [ i c o u n t ] = 0 ; 67 return new S t r i n g ( newdata ) ; 68 } 69 70 void S t r i n g : : p r i n t ( ) 71 { 72 cout<<" S t r i n g i s "<<data<<e n d l ; 73 } 74 75 S t r i n g : : ~ S t r i n g ( ) 76 { 77 delete [ ] data ; 78 } 79 80 int main ( ) 81 { 82 S t r i n g a ( " g i a n n i s " ) ; 83 S t r i n g b=a. s u b S t r i n g ( 2, 4 ) ; 84 a. p r i n t ( ) ; 85 b >p r i n t ( ) ; 86 return 0 ; 87 } 8