Δομές (structs)

Δομές (structs)


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

Στο παρακάτω παράδειγμα θέλουμε να φτιάξουμε έναν τύπο μεταβλητής που να αντιπροσωπεύει τους φοιτητές. Στο πρόγραμμά μας για κάθε φοιτητή θεωρούμε ότι χρειάζεται να κρατάμε τα εξής στοιχεία: Όνομα (ένα αλφαριθμητικό το πολύ 20 γραμμάτων), Επώνυμο (ένα αλφαριθμητικό το πολύ 20 γραμμάτων), Ηλικία (ένας δεκαδικός) και ΑΜ (ένας ακέραιος). Η δομή θα ονομαστεί student. Στο κυρίως πρόγραμμα θα δηλώσουμε 2 μεταβλητές τύπου student, και θα τις αρχικοποιήσουμε. Για το δεύτερο φοιτητή θα εκτυπώσουμε το όνομά του και θα ζητήσουμε από το χρήστη να δώσει το ΑΜ.

#include <stdio.h>

// Δήλωση της δομής
struct student
{
  char onoma[20];
  char epwnymo[20];
  float age;
  int AM;
};

main () {
  struct student nikos = {“nikos”, “nikou”, 20, 4321};
  struct student foit2 = {“kostas”, “papanikolaou”, 0, 0};
  foit2.age = nikos.age;
 
  printf(“To onoma tou 2ou foititi einai %s \n”, foit2.onoma);
  printf(“Dwste to AM tou 2ou foititi\n”);
  scanf(“%d”, &foit2.AM);
}

Παρατηρούμε ότι στη main μπορούμε να δηλώσουμε τις μεταβλητές nikos και foit2 οι οποίες είναι τύπου student. Στην ουσία οι μεταβλητές nikos και foit2 είναι σύνθετες μεταβλητές (σαν πακέτα) που περιέχουν από 2 αλφαριθμητικά, 1 δεκαδικό και 1 ακέραιο η κάθε μια (ό,τι δηλαδή έχουμε δηλώσει ότι περιέχει το struct).
Η δήλωση μεταβλητών τύπου struct γίνεται όπως ακριβώς δηλώνεται οποιαδήποτε απλή μεταβλητή, μόνο που αντί για int, float κλπ. γράφουμε struct και το όνομα που έχουμε δώσει στη δομή, π.χ. struct student.

Στο παρακάτω παράδειγμα δηλώνουμε μία δομή που ονομάζουμε migadikos και αποτελείται από 2 δεκαδικές μεταβλητές. Σκοπός μας είναι να αναπαραστήσουμε τους μιγαδικούς αριθμούς που αποτελούνται από το πραγματικό και το φανταστικό μέρος. Στη συνέχεια στο κυρίως πρόγραμμα δηλώνουμε έναν δείκτη σε μεταβλητή τύπου migadikos (τον migPtr) και κατόπιν δεσμεύουμε δυναμικά 100 θέσεις μιγαδικών στο σωρό με τη χρήση της malloc. Τέλος βάζουμε κάποιες τιμές στις 2 πρώτες θέσεις που μόλις δεσμεύσαμε.

#include <stdio.h>
#include <stdlib.h>

// Δήλωση της δομής
struct migadikos
{
  float pragm;
  float fant;
};

main () {
  struct migadikos * migPtr;  //Δείκτης σε δομή

  migPtr = malloc (100 * sizeof(struct migadikos));  // Δυναμική δέσμευση μνήμης

  migPtr[0].pragm = 3;
  migPtr[0].fant = 10.2;

  migPtr[1].pragm = 5.5;
  migPtr[1].fant = -7.2;
}

Όταν έχουμε δείκτη σε δομή (όπως τον migPtr) μπορούμε είτε να χρησιμοποιήσουμε το δείκτη ως πίνακα, όπως κάνουμε παραπάνω, εφόσον με τη malloc ο δείκτης δείχνει στην αρχή ενός πίνακα 100 θέσεων, είτε μπορούμε να πάρουμε το περιεχόμενο στο οποίο δείχνει ο δείκτης με τη χρήση του αστερίσκου (*). Έτσι οι παρακάτω εντολές είναι ισοδύναμες:

migPtr[0].pragm = 3;

και

(*migPtr).pragm = 3;

Η C μας δίνει και τον τελεστή -> που είναι ισοδύναμος με το συνδυασμό αστερίσκου και τελείας (*migPtr.), δηλαδή μας επιτρέπει να προσπελάσουμε μια μεταβλητή που περιέχεται στη δομή που δείχνει ο δείκτης. Επομένως η παραπάνω εντολή μπορεί να γραφτεί ισοδύναμα και ως εξής:


migPtr->pragm = 3;