Επιστροφή στο
table2.cΛοιπόν, ένας από τους βασικότερους λόγους που το γυρίσαμε σε δομή είναι για να μπορούμε να διαχειριζόμαστε και πιο άμεσα και πιο εύκολα τα πεδία: buflen και bufmaxlen.
Το
bufmaxlen είναι το μέγιστο πλήθος στοιχείων του buffer μας, άρα είναι η ένδειξη που έχουμε για το ανώτατο όριο του πίνακά μας, ώστε ελέγχοντάς το να μπορούμε να αποτρέπουμε πιθανά buffer overflows.
Το
buflen θέλουμε ανά πάσα στιγμή να απεικονίζει της θέση του 1ου ΜΗ ΚΕΝΟΥ στοιχείου στο buffer, και όταν ισούται με bufmaxlen ξέρουμε πως ο πίνακάς μας είναι γεμάτος, δεν έχει χώρο να φιλοξενήσει άλλη τιμή (εκτός φυσικά αν σβήσουμε κάποιες από τις υπάρχουσες).
Από τα παραπάνω προκύπτει πως κάθε φορά που προσθέτουμε ή αφαιρούμε στοιχεία στο buffer, πρέπει να φροντίζουμε να ενημερώνουμε αμέσως και το πεδίο buflen. Το θέλουμε να είναι ενημερωμένο ΑΝΑ ΠΑΣΑ ΣΤΙΓΜΗ το χρειαστούμε!
Η χρησιμότητά του ποικίλει, μιας και όταν είναι ενημερωμένο μας βοηθάει σε πλειάδα περιπτώσεων.
Για παράδειγμα, αν δεν μας ενδιαφέρει τα στοιχεία να εισάγονται ταξινομημένα στον πίνακα, τότε η εισαγωγή κάθε νέου στοιχείου μπορεί να γίνει με μια απλή ανάθεση στη θέση που δείχνει το buflen, το οποίο οφείλουμε να το αυξάνουμε κατά 1 μετά από κάθε επιτυχημένη εισαγωγή.
Π.χ.
- Κώδικας: Επιλογή όλων
table->buffer[ table->buflen ] = new_element;
table->buflen++;
φυσικά πριν επιχειρήσουμε την εισαγωγή, πρέπει πρώτα να έχουμε ελέγξει πως ο πίνακας δεν ήταν ήδη γεμάτος (καθως επίσης κι αν το buffer μας ήταν δημιουργημένο: table->buffer != NULL
Μια άλλη περίπτωση που μας βοηθάει το ενημερωμένο buflen είναι στην αναζήτηση ενός υπάρχοντος στοιχείου του πίνακα. Με την προϋπόθεση πως έχουμε ήδη ταξινομήσει τα στοιχεία του πίνακα σε αύξουσα σειρά, τότε αν ο χρήστης μας ζητήσει ένα στοιχείο που βρίσκεται από τη μέση του πίνακα και μετά, τότε μπορούμε να ξεκινήσουμε το for-loop της αναζήτησης όχι με: for (i=0; i < buflen; i++) αλλά με: (i=buflen; i >-1; i--)
Να ξεκινήσουμε δηλαδή από το τέλος προς την αρχή, για να γλιτώσουμε περιττές επαναλήψεις.
Αν για παράδειγμα σε ένα πίνακα 100000 στοιχείων (bufmaxlen), εκ των οποίων τα 90000 είναι γεμάτα (buflen), το στοιχείο που ζητάμε βρίσκεται 3 θέσεις πριν το τέλος του πίνακα, θα το βρούμε σε 3 μόλις επαναλήψεις γιατί θα έχουμε ξεκινήσουμε από το buflen και όχι από το 0

Με λίγα λόγια, με λίγο έξτρα κόστος για να διατηρούμε ενημερωμένο το buflen, παίρνουμε ως αντάλλαγμα μεγάλο κέρδος σε διάφορες λειτουργίες.
Χρειάζεται λίγη προσοχή όμως κατά την ενημέρωση του buflen, γιατί στην C οι πίνακες ξεκινάνε από την θέση μηδέν. Οπότε, αν για παράδειγμα το bufmaxlen είναι 5 στοιχεία, τότε η συνθήκη που καθορίζει αν ο πίνακας είναι γεμάτος ή όχι είναι η...
- Κώδικας: Επιλογή όλων
if ( buflen == bufmaxlen )
Αυτό θέλει λίγη ανάλυση!
Ας πάρουμε έναν κενό πίνακα χωρητικότητας 5 στοιχείων, δηλαδή έχουμε: bufmaxlen = 5 και buflen = 0 (είπαμε πως το buflen δείχνει πάντα στο 1ο ΜΗ ΚΕΝΟ στοιχείο του πίνακα). Για να εισαγάγουμε π.χ. την τιμή 100 στο πίνακα, θέλουμε να τη βάλουμε στο 1ο μη κενό κελί του buffer, δηλαδή στη θέση 0 που δείχνει το buflen. Αμέσως μετά, κάνουμε το buflen++ για να δείχνει στη θέση 1, που είναι η νεα ΜΗ ΚΕΝΗ θέση του πίνακα.
Όταν το buflen φτάσει να δείχνει στη θέση 4 (που είναι η 5η θέση του πίνακα) εννοείται πως είναι κενή... βάζουμε λοιπόν κι εκεί ένα νέο στοιχείο και αυξάνουμε το buflen κατά 1, όπως είπαμε.
Άρα, το buflen τώρα ισούται με 5 κι ο πίνακας είναι γεμάτος. Με 5 όμως ισούται και maxbufen, Οπότε, όταν (buflen == bufmaxlen) σημαίνει πως ο πίνακας ΔΕΝ έχει άλλο χώρο, είναι γεμάτος!
Αυτά μου έρχονται στο μυαλό προς το παρόν για τη φιλοσοφία του μέχρι τώρα κώδικά μας. Αν δεν υπάρχουν απορίες, φτιάξτε τη συνάρτηση...
- Κώδικας: Επιλογή όλων
Bool table_fill_randomly( Table *table, const int maxval )
που είπαμε στο προηγούμενο post, για να πιάσουμε μετά 3 πολύ χρήσιμες και ιδιαίτερα ενδιαφέρουσες συναρτήσεις:
- Κώδικας: Επιλογή όλων
table_insert_element( ... );
table_delete_element( ... );
table_sort_ascending( ... );