10 η Διάλεξη C++ - Πίνακες Δρ. Χρήστος Δρόσος ΑΕΙ ΠΕΙΡΑΙΑ ΤΤ ΤΜΗΜΑ ΑΥΤΟΜΑΤΙΣΜΟΥ
Ανακεφαλαίωση Κατά την κλήση μιας συνάρτησης κατ αξία οι τιμές των ορισμάτων αντιγράφονται στις αντίστοιχες τυπικές παραμέτρους της συνάρτησης Μια αναφορική μεταβλητή αναφέρεται σε μια άλλη μεταβλητή η οποία της ανατίθεται κατά τη δήλωσή της. Μια αναφορική μεταβλητή δηλώνεται με το πρόθεμα & πριν το όνομά της Η κλήση μιας συνάρτησης με αναφορά γίνεται με τη χρήση αναφορικών μεταβλητών στις τυπικές παραμέτρους της συνάρτησης. Στην κλήση μιας συνάρτησης με αναφορά η συνάρτηση μπορεί να μεταβάλει τις τιμές των μεταβλητών με τις οποίες κλήθηκε Οι αναφορικές παράμετροι δίνουν τη δυνατότητα σε συναρτήσεις να επιστρέφουν περισσότερες από μία τιμές στων κώδικα που τις καλεί. Μια συνάρτηση μπορεί να επιστρέψει ως τιμή έναν δείκτη. Δηλώνεται όπως και οι υπόλοιπες με τον τελεστή * πριν το όνομά της Πχ char *test()
Ανακεφαλαίωση Ένας δείκτης σε συνάρτηση περιέχει τη διεύθυνση της πρώτης θέσης μνήμης στην οποία ο μεταγλωττιστής έχει τοποθετήσει τον κώδικα της συνάρτησης Ένας δείκτης σε συνάρτηση δείχνει πάντα σε συναρτήσεις με συγκεκριμένο αποτύπωμα, δηλαδή σε συναρτήσεις ίδιου τύπου και με ίδιο αριθμό και τύπο παραμέτρων Η αριθμητική δεικτών δεν εφαρμόζεται σε δείκτες σε συναρτήσεις Μια εμβόλιμη συνάρτηση τη δηλώνουμε βάζοντας πριν από το τύπο της το πρόθεμα inline. Όταν ο μεταγλωττιστής συναντήσει τη κλήση αυτής της συνάρτησης παρεμβάλει το κώδικα της στο σημείο κλήσης της. Αν καλείται περισσότερες από μια φορές, σε κάθε σημείο της κλήσης παρεμβάλλεται ολόκληρος ο κώδικας της συνάρτησης Είναι απόφαση του μεταγλωττιστή αν θα αντιμετωπίσει μια εμβόλιμη συνάρτηση ως εμβόλιμη ή όχι
Πίνακες Ένας πίνακας είναι μια ομάδα θέσεων μνήμης στις οποίες γίνεται αναφορά με ένα κοινό όνομα. Μια συγκεκριμένη θέση μνήμης αυτής της ομάδας καθορίζεται από έναν ή περισσότερους αριθμοδείκτες. Πίνακας 1 διάστασης Πίνακας 2 διαστάσεων Πίνακας 3 διαστάσεων
Πίνακες μιας διάστασης Όλες οι θέσεις μνήμης ενός πίνακα έχουν τον ίδιο τύπο με αυτόν που χρησιμοποιήθηκε στη πρόταση δήλωσης του ίδιου πίνακα. Δήλωση πίνακα 1 διάστασης: τύπος όνομα[μέγεθος] int a[10] δηλώνει ένα πίνακα 10 θέσεων από a[0] έως a[9] cin >> m; //δηλώνουμε τη διάσταση του πίνακα int b[m]; // Για να προσδιορίσουμε μια θέση μνήμης ενός πίνακα μιας διάστασης χρησιμοποιούμε μια μεταβλητή. Αν αλλάξουμε την τιμή της μεταβλητής, μπορούμε να έχουμε πρόσβαση σε μια διαφορετική θέση μνήμης. i=5; a[i]=45; //καταχωρεί στη θέση 5 του πίνακα τον αριθμό 45 For(i=0;i<=9;i++) a[i]=5; // θα γεμίσει όλες τις θέσεις του πίνακα a[10] με τον αριθμό 5
Πίνακες μιας διάστασης Η διάσχιση ενός πίνακα μιας διάστασης γίνεται συνήθως με μια επαναληπτική δομή for. Η μεταβλητή που χρησιμοποιείται για τον έλεγχο της for χρησιμοποιείται επίσης και για να προσδιορίσει τη θέση μνήμης του πίνακα
Στις 10 θέσεις του πίνακα καταχωρούνται τυχαίοι αριθμοί Στην οθόνη εμφανίζονται οι αριθμοί του πίνακα με αντίστροφη σειρά Υπολογίζει και εμφανίζει το πλήθος των ζυγών αριθμών
Δημιουργία πίνακα 100 θέσεων, γέμισμα με τυχαίους αριθμούς και υπολογισμός του αθροίσματος των στοιχείων του και εύρεση δοθέντος αριθμού Στης 100 θέσεις του πίνακα καταχωρούνται τυχαίοι αριθμοί Εμφάνιση στην οθόνη των στοιχείων του πίνακα Υπολογισμός αθροίσματος των στοιχείων Εύρεση αριθμού
Δημιουργία πίνακα 10 θέσεων με αριθμούς που πληκτρολογεί ο χρήστης. Εύρεση του μεγαλύτερου και του μικρότερου αριθμού καθώς και των θέσεων στις οποίες βρίσκονται
Πίνακες και συμβολοσειρές Για την αποθήκευση μιας συμβολοσειράς χρησιμοποιείται ένας μονοδιάστατος πίνακας χαρακτήρων. Το σύνολο χαρακτήρων τερματίζεται πάντα με το χαρακτήρα τερματισμού \0. Επομένως ο πίνακας στον οποίο θα αποθηκευτεί μια συμβολοσειρά πρέπει να έχει μια θέση περισσότερη από το πλήθος των χαρακτήρων που θέλουμε να αποθηκεύσουμε. Μαζί με τη δήλωση ενός πίνακα χαρακτήρων είναι δυνατό να του δοθεί ταυτόχρονα και ένα σύνολο χαρακτήρων ως αρχική τιμή: char lex[12]= CHRISTOS ; // δηλώνει ένα πίνακα 12 θέσεων και καταχωρεί 9 χαρακτήρες μαζί με το \0
Αρχικές τιμές πίνακα μιας διάστασης int a[10]={0,1,2,3,4,5,6,7,8,9}; int a[10]={0,1,2,3}; Οι αρχικές τιμές χωρίζονται με κόμματα και περικλείονται από {} Ειδικά στους πίνακες χαρακτήρων η ανάθεση αρχικής τιμής γίνεται ως εξής: char test[20]= I like c++ ; Στη c++ μπορούμε να δηλώσουμε έναν πίνακα χωρίς να καθορίσουμε το μέγεθός του αρκεί να δώσουμε στη δήλωσή του αρχικές τιμές int a[]={0,1,2,3,4}//δημιουργεί έναν πίνακα 5 θέσεων δίνοντάς του αρχικές τιμές
Οι εντολές cin και cout σε πίνακες χαρακτήρων Το πρόγραμμα ζητάει από το χρήστη να πληκτρολογήσει μια φράση, την καταχωρεί στο πίνακα Lex και μετά την εμφανίζει στην οθόνη. Παρατηρούμε ότι αν πληκτρολογήσουμε μια φράση που περιέχει κενά στον πίνακα καταχωρείται μόνο το πρώτο τμήμα της
Δείκτες σε πίνακες μιας διάστασης Το όνομα ενός πίνακα είναι ένας δείκτης ο οποίος περιέχει τη διεύθυνση της πρώτης από τις θέσεις μνήμης του. Τις θέσεις μνήμης ενός πίνακα μπορούμε να τις προσπελάζουμε είτε χρησιμοποιώντας τον αριθμοδείκτη τους μέσα στο πίνακα (a[3]) είτε με δείκτες: a[0]=12 ή *a=12 a[1]=10 ή *(a+1)=5 a[2]=3 ή *(a+2)=10 Στη c++ ο έλεγχος των ορίων ενός πίνακα είναι ευθύνη του προγραμματιστή.
Μεταβίβαση πίνακα μιας διάστασης σε συνάρτηση Ο προκαθορισμένος τρόπος μεταβίβασης παραμέτρων σε μια συνάρτηση είναι by value. Στην περίπτωση όμως που η παράμετρος είναι ένας πίνακας δεν μεταβιβάζονται ολόκληρα τα περιεχόμενα του πίνακα αλλά η διεύθυνση της πρώτης θέσης μνήμης του. Επομένως η τυπική παράμετρος της συνάρτησης πρέπει να είναι ένας δείκτης του ίδιου τύπου όπως ο τύπος του πίνακα: Το μέγεθος δεν λαμβάνετε υπόψη
Μεταβίβαση πίνακα μιας διάστασης σε συνάρτηση Η τυπική παράμετρος της συνάρτησης στην οποία θα μεταβιβαστεί η διεύθυνση ενός μονοδιάστατου πίνακα πρέπει να είναι ένα πίνακας (ή ένας δείκτης) ίδιου τύπου, χωρίς να χρειάζεται να ορίζεται το μέγεθός του. Μέσα στη συνάρτηση η χρήση του πίνακα γίνεται κανονικά μέσω της τυπικής παραμέτρου
Στο επόμενο πρόγραμμα η συνάρτηση find_star() εντοπίζει τον πρώτο χαρακτήρα * του πίνακα lexi και επιστρέφει ως τιμή έναν δείκτη ο οποίος δείχνει στη θέση μνήμης που τον εντόπισε.
Πολυδιαστασιακοί πίνακες Η δήλωση τέτοιων πινάκων γίνεται ως εξής: int pinakas[5][5][10]; // Δημιουργείται ένας πίνακας 3 διαστάσεων Ο πίνακας έχει συνολικά 5χ5χ10=500 θέσεις μνήμης Όταν θέλουμε να προσπελάσουμε ένα πίνακα πολλών διαστάσεων χρησιμοποιούμε ένθετους βρόγχους for:
Πίνακες 2 διαστάσεων Είναι οι πιο συχνά χρησιμοποιούμενοι. int pinakas[5][2]; // δημιουργεί ένα πίνακα 5 γραμμών και 2 στηλών Η προσπέλαση γίνεται με τη χρήση 2 αριθμοδεικτών για τον προσδιορισμό της γραμμής και της στήλης που βρίσκεται ένα στοιχείο. Για να προσπελάσουμε όλες τις θέσεις μνήμης του πίνακα 2 διαστάσεων χρησιμοποιούμε 2 ένθετος for Μπορούμε να τον προσπελάσουμε ανά γραμμή ή ανά στήλη
Πίνακες 2 διαστάσεων
Άθροισμα στοιχείων πίνακα 2 διαστάσεων
Εύρεση μεγαλύτερης και μικρότερης τιμής σε 2 διαστάσεων πίνακα
Εύρεση αθροίσματος κάθε γραμμής καθώς και της μεγαλύτερης τιμής κάθε στήλης ενός 2 στατου πίνακα
Αρχικές τιμές πίνακα 2 διαστάσεων Κατά τον ίδιο τρόπο όπως και στους μονοδιάστατους πίνακες μπορούν να δοθούν αρχικές τιμές σε ένα πίνακα 2 διαστάσεων int pinakas[3][4]={1,2,3,4,4,5,7,9,2,4,20,3} 1 2 3 4 4 5 7 9 2 4 20 3
Πίνακες 2 διαστάσεων και δείκτες Για να υπολογίσει τη διεύθυνση μιας θέσης μνήμης ενός πίνακα 2 διαστάσεων η C++ χρειάζεται τις συντεταγμένες στις οποίες βρίσκεται (γραμμή και στήλη) τη διεύθυνση της 1 ης θέσης του πίνακα αλλά και την τιμή της 2 ης διάστασής του Ο pinakas μεταβιβάζεται στην τυπική παράμετρο x της συνάρτησης, αλλά πρέπει οπωσδήποτε να δηλωθεί και η τιμή της 2 ης διάστασης του pinaka
Πίνακες πολλών διαστάσεων Ένα πίνακα 3 διαστάσεων μπορούμε να τον φανταστούμε σαν θέσεις μνήμης διατεταγμένες σε γραμμές στήλες αλλά και επίπεδα Έναν πίνακα παραπάνω διαστάσεων μπορούμε να τον φανταστούμε σαν ένα ανάποδο δέντρο που ξεκινώντας από τη ριζά πάμε προς τα κλαδιά και τα φύλλα. Για να φτάσουμε σε ένα φύλο (θέση μνήμης) πρέπει να επιλέξουμε μια διαδρομή μέσα από μια σειρά διακλαδώσεων. Σε κάθε διακλάδωση που επιλέγουμε μια διαδρομή είναι και η τιμή της συγκεκριμένης διάστασης του πίνακα.
Πίνακες πολλών διαστάσεων http://www.instructables.com/id/creating-and-using- Multidimensional-Arrays-in-C/
Μεταβίβαση πινάκων πολλών διαστάσεων σε συναρτήσεις
sizeof Ο τελεστής sizeof επισρέφει το συνολικό μέγεθος ενός πίνακα σε byte. int a[5] ; sizeof(a);// θα επιστρέψει 4*5=20 bytew sizeof(a[0]);// θα επιστρέψει 4 byte sizeof(a)/sizeof(a[0]); // θα επιστρέψει τη τιμή 10 των αριθμό των θέσεων μνήμης του πίνακα και αποτελεί έναν εύκολο τρόπο υπολογισμού των θέσεων μνήμης του πίνακα όταν γνωρίζουμε μόνο το όνομά του
Παράδειγμα: καταχώριση των θερμοκρασιών 100 πόλεων μιας χώρας για κάθε ώρα της ημέρας και για έναν μήνα Γενικά το πλήθος των διαστάσεων ενός πίνακα καθορίζεται από τη δομή των δεδομένων τα οποία θέλουμε να αποθηκεύσουμε
Πίνακες δεικτών Δηλώνει ένα πίνακα δεικτών σε char 5 θέσεων και με το πρόθεμα const αποτρέπουμε την τροποποίηση των περιεχομένων
Δείκτες σε πίνακες Η γενική πρόταση δήλωσης δείκτη σε πίνακα είναι: Τύπος (*όνομα_δείκτη)[δ1][δ2] [Δ Ν ] int (*diktis)[5][4]; //δηλώνει ένα δείκτη με το όνομα diktis ο οποίος δείχνει σε πίνακες 2 διαστάσεων 5χ4 To (*ptr)[i][j] είναι ισοδύναμο με a[i][j] Η συνάρτηση συμπληρώνει το πίνακα που της μεταβιβάζεται μέσο της παραμέτρου p, με τυχαίους αριθμούς από το 0 μέχρι το 99
Πίνακες δεικτών σε πίνακες Δήλωση πίνακα δεικτών 3 θέσεων με όνομα ptr σε πίνακες int 5x7
Πίνακες δεικτών σε συναρτήσεις Επιτρέπουν στα προγράμματα να καλούν διαφορετικές συναρτήσεις ανάλογα με την τιμή του αριθμοδείκτη του πίνακα. void (*ptr[4]) (double x, double y); // δηλώνει ένα πίνακα δεικτών σε συναρτήσεις τύπου void με 2 παραμέτρους τύπου double Συνήθως ένας πίνακας δεικτών σε συναρτήσεις χρησιμοποιείται όταν θέλουμε να ομαδοποιήσουμε κάποιες συναρτήσεις ώστε να εκτελούνται η μια μετά την άλλη χωρίς να χρειάζεται να τις καλούμε μια-μια ξεχωριστά
Πίνακες δεικτών σε συναρτήσεις Κλήση των 4 συναρτήσεων με ορίσματα 10 και 23 μέσω των δεικτών του πίνακα ptr[]