1 / 44

Δομές στην C ( επανάληψη )

Δομές στην C ( επανάληψη ). Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο. lpis . csd . auth . gr / curriculum / C + Unix / UNCL 202. html. Σύνθετοι Τύποι Δεδομένων. structure (δομή): ομαδοποίηση πολλών μεταβλητών κάτω από ένα κοινό όνομα Π.χ. εγγραφή αρχείου

sheera
Download Presentation

Δομές στην C ( επανάληψη )

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Δομές στην C (επανάληψη) Γλώσσα C & Unix Τμήμα Πληροφορικής, ΑΠΘ B’ εξάμηνο lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html

  2. Σύνθετοι Τύποι Δεδομένων • structure (δομή): ομαδοποίηση πολλών μεταβλητών κάτω από ένα κοινό όνομα • Π.χ. εγγραφή αρχείου • Π.χ. γραμμή σε βάση δεδομένων • union (ένωση): επιτρέπει το ίδιο μέρος της μνήμης να οριστεί ως δύο ή παραπάνω διαφορετικούς τύπους μεταβλητών • enumeration (απαρίθμηση): λίστα συμβόλων • typedef: δημιουργία νέων ονομάτων τύπων δεδομένων

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

  4. Δήλωση Δομής • Δομή για την αναπαράσταση των στοιχείων ενός μαθητή struct mathitis { char onoma[15]; char eponymo[25]; short int apousies; short int vathmos; }; • Όνομα της δομής • Δηλώσεις στοιχείων • Πληροφορεί τον μεταγλωττιστή της C ότι ξεκινά η δήλωση μιας δομής (ή μιας μεταβλητής δομής).

  5. Χρήση Δομής • Ακόμα δεν έχει δημιουργηθεί καμία μεταβλητή • Το mathitis είναι ένας καινούριος τύπος δεδομένων • Μπορεί να χρησιμοποιηθεί για τη δήλωση μεταβλητών αυτού του τύπου struct mathitis x1;

  6. Ταυτόχρονη Δήλωση και Χρήση Δομής • Μπορούμε να δηλώσουμε μεταβλητές ταυτόχρονα με τη δήλωση μιας δομής struct mathitis { char onoma[15]; char eponymo[25]; unsigned short int apousies; unsigned short int vathmos;} x1, x2, x3;

  7. Ανώνυμες Δομές • Όταν δηλώνουμε μεταβλητές μαζί με τη δομή μπορούμε να μη δώσουμε όνομα στη δομή • Όταν δεν πρόκειται να δηλώσουμε επιπλέον μεταβλητές αυτού του τύπου struct { char onoma[15]; char eponymo[25]; unsigned short int apousies; unsigned short int vathmos;} x1, x2, x3;

  8. Προσπέλαση Στοιχείων Δομής • Τα στοιχεία μιας μεταβλητής δομής, μπορούν να προσπελαστούν με τον τελεστή τελεία “.” • Γενική μορφή: struct_var_name.member_name • Παράδειγμα: x1.apousies = 2; printf("%d", x1.apousies);

  9. Σύνθετες Δομές struct mathitis { char onoma[15]; ... struct date birthday; } x1; struct date { int day; int month; int year; }; • Πρόσβαση στοιχείων «εσωτερικής» δομής • x1.birthday.year;

  10. Πίνακες από Δομές • Η πιο συνηθισμένη χρήση των δομών, είναι σε πίνακες πολλών μεταβλητών δομής • Για να δηλωθεί ένας πίνακας από δομές, πρέπει να δηλωθούν: • η δομή, και μετά • ένας πίνακας από αυτές τις δομές • Παράδειγμα: struct mathitis m[100];

  11. Πίνακες από Δομές – Προσπέλαση Στοιχείων • Για να προσπελαστεί ένα στοιχείο μέσα στον πίνακα • πρέπει να χρησιμοποιηθεί ο αύξων αριθμός του στοιχείου στον πίνακα • Π.χ. εκτύπωση ονόματος του τρίτου μαθητή: printf("%s", m[2].onoma);

  12. Δομές και Συναρτήσεις • Πέρασμα μεμονωμένου στοιχείου δομής ως παράμετρο σε συνάρτηση • Πέρασμα ολόκληρης δομής • Κλήση με τιμή • Πέρασμα διεύθυνσης μνήμης δομής • Κλήση με αναφορά

  13. Στοιχεία Δομής ως Παράμετροι Συναρτήσεων • Οι μεταβλητές που αποτελούν τα στοιχεία μιας δομής μπορούν να δοθούν σε μια συνάρτηση • ως τιμές • ως δείκτες προς τη διεύθυνση τους • Παράδειγμα δομής: struct paradeigma { char c; int i; float f; char s[10];} x;

  14. Παραδείγματα Κλήσης με Τιμή struct paradeigma { char c; int i; float f; char s[10];} x; func_v1(x.c);func_v2(x.i);func_v3(x.f);func_v4(x.s[2]);

  15. Παραδείγματα Κλήσης με Αναφορά • ο τελεστής διεύθυνσης & τοποθετείται πριν από το όνομα της μεταβλητής δομής • όχι πριν από την μεταβλητή του στοιχείου της δομής func_r1(&x.c);func_r2(&x.i);func_r3(&x.f); struct paradeigma { char c; int i; float f; char s[10];} x;

  16. Παραδείγματα Κλήσης με Αναφορά • Επειδή το όνομα ενός πίνακα χαρακτήρων είναι η διεύθυνση του πρώτου στοιχείου του πίνακα, παραλείπουμε τελείως τον τελεστή & func_r4(x.s); struct paradeigma { char c; int i; float f; char s[10];} x;

  17. Παραδείγματα Κλήσης με Αναφορά • Όταν θέλουμε να δώσουμε τη διεύθυνση κάποιου συγκεκριμένου στοιχείου του πίνακα (εκτός του πρώτου) τότε πρέπει να χρησιμοποιήσουμε τον τελεστή & func_r5(&x.s[2]); struct paradeigma { char c; int i; float f; char s[10];} x;

  18. Παραδείγματα Κλήσης με Αναφορά • Εναλλακτικά θα μπορούσε να είχε χρησιμοποιηθεί αριθμητική δεικτών func_r5((x.s)+2); struct paradeigma { char c; int i; float f; char s[10];} x;

  19. Κλήση Συνάρτησης με Τιμή μιας Ολόκληρης Δομής • Όταν μια μεταβλητή δομής δίνεται ως παράμετρος σε μια συνάρτηση, τότε γίνεται μια τυπική κλήση της συνάρτησης με τιμή. • Οποιεσδήποτε αλλαγές γίνουν στα στοιχεία της μεταβλητής δομής μέσα στην συνάρτηση, δεν θα είναι μόνιμες.

  20. Κλήση Συνάρτησης με Τιμή μιας Ολόκληρης Δομής • Ο τύπος της τυπικής παραμέτρου της συνάρτησης πρέπει να είναι ίδιος με τον τύπο της μεταβλητής-παραμέτρου • Η δομή πρέπει να δηλωθεί ως καθολικός τύπος δεδομένων • Το όνομα της δομής πρέπει να χρησιμοποιηθεί για τη δήλωση των • τοπικών μεταβλητών δομής • τυπικών παραμέτρων των συναρτήσεων

  21. Κλήση Συνάρτησης με Τιμή μιας Ολόκληρης Δομής - Παράδειγμα #include <stdio.h>struct test { int a, b; char ch;}; void main(void) { struct test x1; x1.a = 1000; f1(x1);} • Καθολικός τύπος δεδομένων void f1(struct test p) { printf("%d", p.a);}

  22. Κλήση Συνάρτησης με Αναφορά σε μία Ολόκληρη Δομή • Μπορούμε να περνάμε τη διεύθυνση μνήμης μιας μεταβλητής δομής ως παράμετρο σε συνάρτηση • Μπορούμε να κάνουμε μόνιμες αλλαγές στα στοιχεία της μεταβλητής δομής μέσα στη συνάρτηση • Δίνοντας τη διεύθυνση της μεταβλητής δομής στη μνήμη έχουμε κλήση της συνάρτησης με αναφορά Πλεονέκτημα

  23. Κλήση Συνάρτησης με Αναφορά σε μία Ολόκληρη Δομή • Η εκτέλεση της συνάρτησης επιταχύνεται δραστικά • Δεν δημιουργείται αντίγραφο της μεταβλητής δομής στη μνήμη για χρήση μόνο μέσα στην συνάρτηση • Έχουμε απευθείας προσπέλαση στη μνήμη Πλεονέκτημα

  24. Δήλωση Δείκτη σε Δομή • Γενική μορφή: struct onoma_domis *onoma_deikti • Θα πρέπει να έχει προηγηθεί η δήλωση του structure με όνομα onoma_domis • Υπάρχουν κάποια σημεία διαφοροποίησης από τους υπόλοιπους δείκτες

  25. Χρήση Δείκτη σε Δομή struct mathitis { char onoma[15]; char eponymo[25]; unsigned short int apousies; unsigned short int vathmos;};void main(void){ struct mathitis x, *p; p = &x;}

  26. Τελεστής Βέλος (->) • Δεν μπορεί να χρησιμοποιηθεί ο τελεστής τελεία (.) για προσπέλαση των στοιχείων της δομής • Πρέπει να χρησιμοποιηθεί ένας καινούργιος τελεστής, ο τελεστής βέλος (->) • Π.χ. για προσπέλαση του στοιχείου apousies μέσω του δείκτη p: p->apousies = 2;

  27. Εναλλακτική Προσπέλαση Στοιχείου Δομής από Δείκτη • Ένας πιο δύσχρηστος τρόπος για προσπέλαση ενός στοιχείου μιας δομής, μέσω του τελεστή τελεία: (*p).apousies = 2; p->apousies = 2; • Η χρήση των παρενθέσεων είναι απαραίτητη λόγω χαμηλότερης προτεραιότητας του τελεστή *

  28. Συναρτήσεις που Επιστρέφουν Δομές struct mathitis make_student( char *first, char *last) { struct mathitis temp; strcpy(temp.onoma,first); strcpy(temp.eponymo,last); temp.apousies=0; temp.vathmos=0; return temp; }

  29. Συναρτήσεις που Επιστρέφουν Δομές void main(void){ struct mathitis x; char first[]=“John”; char last[]=“Smith”; x = make_student(first,last);} • Επιτρέπεται η ανάθεση τιμής σε ολόκληρη τη δομή (αντιγραφή) • Δεν επιτρέπεται σύγκριση δομών

  30. Εφαρμογή – Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο • Έχουμε ένα μεγάλο κείμενο και ψάχνουμε μέσα σε αυτό να βρούμε πόσες φορές εμφανίζονται συγκεκριμένες λέξεις-κλειδιά • Χρειαζόμαστε 2 πίνακες • Για την αποθήκευση των λέξεων-κλειδιών char *keyword[NKEYS]; • Για την αποθήκευση της συχνότητας εμφάνισης της κάθε λέξης int keycount[NKEYS];

  31. Χρήση Πίνακα Δομών • Υπάρχει 1-1 αντιστοιχία μεταξύ των 2 πινάκων, το πιο «κομψό» θα ήταν να χρησιμοποιηθεί 1 πίνακας δομών struct key { char *word; int count; }; struct key keytab[NKEYS];

  32. Αρχικοποίηση Πίνακα Δομών • Ο πίνακας θα χρησιμοποιείται σε πολλά σημεία του προγράμματος • Ορίζεται ως εξωτερική (global) μεταβλητή struct key keytab[] = { {"account",0}, ... {"programming",0}, {"unix",0} }; • Κάθε ζεύγος αντι-στοιχεί στα στοι-χεία μιας δομής • Τα εσωτερικά άγκιστρα δεν είναι υποχρε-ωτικά

  33. Δομή Προγράμματος • Η συνάρτηση mainκαλεί συνεχώς τη συνάρτηση getword • Διαβάζει από την είσοδο μία λέξη τη φορά • Κάθε λέξη αναζητείται μέσα στον πίνακα keytabχρησιμοποιώντας «δυαδική αναζήτηση» (binary search) • Η λίστα των λέξεων-κλειδιών πρέπει να είναι ταξινομημένη σε αύξουσα σειρά

  34. Συνάρτηση main Δυαδική αναζήτηση του string word στον πίνακα keytab Κάθε κλήση στην getwordβρίσκει μια λέξη και την αντιγράφει στον πίνακα word main(){ int n; char word[MAXWORD]; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) if ((n = binsearch(word,keytab,NKEYS)) >= 0) keytab[n].count++; for (n = 0; n < NKEYS; n++) if (keytab[n].count > 0) printf("%4d %s\n", keytab[n].count, keytab[n].word); getchar(); //Για να προλάβουμε να δούμε τα αποτελέσματα } Αυξάνεται ο αντί-στοιχος counter Εκτύπωση αποτελεσμάτων

  35. Επικεφαλίδες #include <stdio.h> #include <ctype.h> #include <string.h> #define MAXWORD 100 • Μέγεθος ολόκλη-ρου του πίνακα • Αριθμός λέξεων-κλειδιών #define NKEYS (sizeof keytab / sizeof(struct key)) • Τελεστής compile-time • Επιστρέφει το μέγεθος μιας δομής δεδομένων • Μέγεθος ενός στοιχείου του πίνακα

  36. Συνάρτηση binsearch int binsearch(char *word, struct key tab[], int n){ int cond, low, high, mid; low = 0;high = n - 1; while (low <= high) { mid = (low+high) / 2; if ((cond = strcmp(word,tab[mid].word)) < 0) high = mid - 1; else if (cond > 0) low = mid + 1; else return mid; } return -1; } • Αρχικά πρόκειται για το μέσο του πίνακα • Αν το word είναι μικρότερο, η επόμενη αναζήτηση θα γίνει στο μέσο του μισού πίνακα (προς τα κάτω) • Αν το word είναι μεγαλύτερο, η επόμενη αναζήτηση θα γίνει στο μέσο του μισού πίνακα (προς τα πάνω) • Αλλιώς, βρέθηκε • Συγκρίνω το string word με το string στη θέση mid του πίνακα • Αν το «κάτω» ξεπεράσει το «πάνω», τότε δεν βρέθηκε

  37. Συνάρτηση getword int getword(char *word, int lim){ int c;char *w = word; while (isspace(c = getchar())); if (c != EOF)*w++ = c; if (!isalpha(c)) { *w = '\0'; return c; } for ( ; --lim > 0; w++) if (!isalnum(*w = getchar())) { ungetch(*w); break; } *w = '\0'; return word[0]; } • Αγνοεί τα αρχικά κενά • Διαβάζει χαρακτήρες σε έναν buffer και επιστρέφει τον πρώτο χαρακτήρα του buffer • Διαβάστηκε κάποιος «σωστός» χαρακτήρας • Επιστρέφει έναν χαρακτήρα πίσω στο buffer • Αν δε διαβάστηκε γράμμα σταμάτα • Κύριος βρόχος ανάγνωσης, μέχρι να συναντηθεί μη-αλφαριθμητικός χαρακτήρας

  38. Εναλλακτικό πρόγραμμα – Χρήση Δεικτών σε Δομές - main main(){ char word[MAXWORD]; struct key *p; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) if ((p=binsearch(word,keytab,NKEYS)) != NULL) p->count++; for (p = keytab; p < keytab + NKEYS; p++) if (p->count > 0) printf("%4d %s\n", p->count, p->word); }

  39. Εναλλακτικό πρόγραμμα – Χρήση Δεικτών σε Δομές - binsearch struct key*binsearch(char *word,struct key *tab,int n){ int cond; struct key *low = &tab[0]; struct key *high = &tab[n]; struct key *mid; while (low < high) { mid = low+(high-low)/2; if ((cond = strcmp(word, mid->word)) < 0) high = mid; else if (cond > 0) low = mid + 1; else return mid; } return NULL; } • Αρχικά εκτός ορίων πίνακα • Η αριθμητικές πρά-ξεις δεικτών εξα-σφαλίζουν σωστό αποτέλεσμα • Η προσπέλαση στοι-χείων του keytabγίνεται πλέον με δείκτες • Η συνάρτηση πλέον επιστρέφει pointers και όχι ακεραίους

  40. Ένωση (union) • Είναι μια θέση μνήμης που μπορεί να χρησιμοποιηθεί από πολλές μεταβλητές διαφορετικού τύπου • Δήλωση παρόμοια με τη δήλωση μιας δομής union paradeigma { int i; char ch;};

  41. Μεταβλητές union • Μια μεταβλητή union μπορεί να δηλωθεί • τοποθετώντας το όνομα της μαζί με τη δήλωση του union, ή • Μετά, σαν μια ξεχωριστή δήλωση union paradeigma x1;

  42. Μεταβλητές union και Μνήμη • Ο ακέραιος i και ο χαρακτήρας ch μοιράζονται τον ίδιο χώρο μνήμης. • Ο i καταλαμβάνει 2 bytes ενώ ο ch 1

  43. Μεταβλητές union και Μνήμη • Όταν δηλώνεται ένα union, ο μεταγλωττιστής αυτόματα κρατάει χώρο στη μνήμη για τον μεγαλύτερο τύπο μεταβλητής που υπάρχει μέσα στο union.

  44. Προσπέλαση στοιχείων union • Παρόμοια με τις δομές • Αν χρησιμοποιούμε απευθείας μεταβλητή union, χρησιμοποιούμε τον τελεστή τελεία • Αν χρησιμοποιούμε δείκτη προς union, τότε χρησιμοποιούμε τον τελεστή βέλος • Π.χ., για ανάθεση της τιμής 10 στην ακέραια μεταβλητή i: x1.i = 10;

More Related