10. Δομές δεδομένων

Πολλές εργασίες προγραμματισμού απλοποιούνται με τη επεξεργασία  δεδομένων ενός νέου τύπου της γλώσσας προγραμματισμού C που λέγεται δομή. Μια δομή είναι μια συλλογή μιας ή περισσοτέρων μεταβλητών ομαδοποιημένων με ένα κοινό όνομα για εύκολο χειρισμό. Οι μεταβλητές – μέλη μιας δομής, σε αντίθεση με εκείνες ενός πίνακα, μπορούν να είναι διαφορετικών τύπων. Μια δομή μπορεί να περιέχει οποιουδήποτε τύπους δεδομένων της C συμπεριλαμβανομένων των πινάκων και άλλων δομών.

Θεωρούμε την διαδικασία μέτρησης της θερμοκρασίας μέσα και έξω από ένα κτίριο κάθε ημέρα. Στην περίπτωση που θέλουμε να αποθηκεύσουμε τις τιμές της θερμοκρασίας στη μνήμη, ένας τρόπος να το κάνουμε είναι να δημιουργούμε μεταβλητές στις οποίες να της εκχωρούμε τις τιμές της θερμοκρασίας που μετράμε. Στην περίπτωση που κάνουμε μετρήσεις θερμοκρασίας για πολλές ημέρες, αυτός  ο τρόπος αποθήκευσης τιμών σε μεμονωμένες μεταβλητές μπορεί να προκαλέσει προβλήματα. Ένας πιο εύχρηστος τρόπος διαχείρισης δεδομένων είναι οι δομές.

Μπορούμε να ορίσουμε μια δομή με όνομα temperature που να περιέχει τις εξής μεταβλητές – μέλη: την ημερομηνία char date[30]; την εσωτερική θερμοκρασία int indoortemp; και την εξωτερική θερμοκρασία int outdoortemp;  έως εξής:

struct temperature {
       char date[30];
       int indoortemp;
       int  outdoortemp;
}

Η λέξη κλειδί struct προσδιορίζει την αρχή ενός ορισμού δομής, που πρέπει να ακολουθείται άμεσα από το όνομα της δομής (ετικέτα), η οποία πρέπει να ακολουθεί τους ίδιους κανόνες που ισχύουν για τις μεταβλητές. Μέσα στα άγκιστρα που έπονται του ονόματος της δομής, υπάρχει μια λίστα των μελών μεταβλητών της δομής. Πρέπει να δίνετε ένα τύπο μεταβλητής και ένα όνομα για κάθε μέλος.

Οι προηγούμενες προτάσεις δηλώνουν ένα τύπο δομής χωρίς να δεσμεύουν χώρο στη μνήμη. Με τον ορισμό στιγμιότυπων  δεσμεύεται μνήμη για την αποθήκευση δεδομένων των μεταβλητών τύπου δομής.

Υπάρχουν δυο τρόποι για τον ορισμό στιγμιότυπων μιας δομής. Ο ένας είναι με μια λίστα μεταβλητών δομής, τοποθετούμενης μετά τον ορισμό της δομής, όπως παρακάτω:

struct temperature {
       char date[30];
       int indoortemp;
       int  outdoortemp;
} morning, evening;

Αυτές οι προτάσεις ορίζουν την δομή με όνομα temperature που περιέχει τρεις μεταβλητές την ημερομηνία date[], την εσωτερική θερμοκρασία indoortemp; και την εξωτερική θερμοκρασία outdoortemp; Οι όροι morning και evening είναι στιγμιότυπα τύπου temperature. Αυτός ο τρόπος συνδυάζει την δήλωση της δομής με τον ορισμό των στιγμιοτύπων της δομής.

Ο δεύτερος τρόπος είναι η δήλωση μεταβλητών τύπου δομής σε μια διαφορετική θέση στον πηγαίο κώδικα από εκείνη της δήλωσης της δομής.

struct temperature {
       char date[30];
       int indoortemp;
       int  outdoortemp;
}
/* Εδώ μπορεί να υπάρχει πρόσθετος κώδικας */
struct temperature morning, evening;

Πρόσβαση Μελών Δομών

Τα μεμονωμένα μέλη δομών μπορούν να χρησιμοποιηθούν όπως και οι άλλες μεταβλητές του ιδίου τύπου. Τα μέλη δομών προσπελάζονται με χρήση του τελεστή μέλους δομής που λέγεται και τελεστής τελείας, που τοποθετείται ανάμεσα στο όνομα της δομής και στο όνομα μέλους. Έτσι για να ορίσουμε την δομή morning με τιμές που αναφέρονται στις θερμοκρασίες σε κάποια στιγμή της ημέρας μπορούμε να γράψουμε:

morning.date[ ]  = "12/4/18 – 9:10";
morning.indoortemp = 30;
morning.outdoortemp = 32;

Για να προβάλουμε τις θερμοκρασίες στο Serial Monitor θα πρέπει να γράψουμε:

Serial.print(morning.date );
Serial.print("Temperature inside:" );
Serial.print(morning.indoortemp );
Serial.print("Temperature outside:" );
Serial.print(morning.outside );

Σε αυτό το σημείο μπορεί να διερωτάστε ποιο είναι το πλεονέκτημα της χρήσης των δομών αντί των μεμονωμένων μεταβλητών. Ένα βασικό πλεονέκτημα είναι ότι μπορούμε να αντιγράφουμε πληροφορίες ανάμεσα στις δομές ίδιου τύπου με μια απλή πρόταση ισότητας. Συνεχίζοντας το προηγούμενο παράδειγμα και αφού δηλώσουμε ένα άλλο στιγμιότυπο δομής, έχουμε:

struct temperature copy_morning;

Η έκφραση:

copy_morning = morning;

ισοδυναμεί με τις προτάσεις:

copy_morning.date[ ]  =  morning.date[ ];
copy_morning.indoortemp = morning.indoortemp;
copy_morning.outdoortemp = morning.outdoortemp;

Όταν το πρόγραμμα μας χρησιμοποιεί πολύπλοκες δομές με πολλά μέλη αυτή η σημειογραφία των δομών μπορεί να βοηθήσει για ποιο ευέλικτο πρόγραμμα και να δώσει μεγάλα κέρδη χρόνου.

Πίνακας με στοιχεία δομών δεδομένων

Μπορούμε να δημιουργήσουμε πίνακες που τα στοιχεία τους να είναι δομές δεδομένων. Συνεχίζουμε το προηγούμενο παράδειγμα ορίζοντας ένα πίνακα με το όνομα week που τα στοιχεία του να είναι στιγμιότυπα δομής δεδομένων, ως εξής:

struct temperature week[7];

Όπου ο δείκτης από 0 έως 6 να αντιστοιχεί και από μια ημέρα της εβδομάδας αρχίζοντας από το μηδέν. Ειδικότερα για την ημέρα της Κυριακής που αντιστοιχεί στο δείκτη 0 δημιουργούνται τα παρακάτω δεδομένα:

week[0].date[ ] = "8/2/18 – 9:20";
week[0].intdoortemp = 26;
week[0].outdoortemp = 28;

Δομές δεδομένων με στοιχεία πινάκων

Είναι δυνατό να ορίσουμε μια δομή που να έχει μεταβλητές μέλη πίνακες στοιχείων οποιοδήποτε τύπου. Στη δομή που δημιουργήσαμε πριν, δηλαδή την:

struct temperature {
       char date[30];
       int indoortemp;
       int outdoortemp;
}

η μεταβλητή μέλους  char date[30]; είναι ένας πίνακας χαρακτήρων με μέγιστο 30 χαρακτήρων.

Δίνοντας αρχικές τιμές σε μια δομή

Στη δομή του παραδείγματος μπορούμε να δώσουμε αρχικές τιμές για ένα στιγμιοτυπο της δομής, μετά τον ορισμό της, όπως παρακάτω:

struct temperature {
       char date[30];
       int indoortemp;
       int  outdoortemp;
} noon = {"18/9/20", 22, 20};

Πράγματι το στιγμιότυπο noon της δομής temperature έχει μέλη με τιμές, τις ακόλουθες:

date[ ] = "18/9/20";
indoortemp = 22;
outdoortemp = 20;