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

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

  • Upload
    sheera

  • View
    48

  • Download
    4

Embed Size (px)

DESCRIPTION

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

Citation preview

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

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

Γλώσσα C & UnixΤμήμα Πληροφορικής, ΑΠΘB’ εξάμηνο

lpis.csd.auth.gr/curriculum/C+Unix/UNCL202.html

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

2

Σύνθετοι Τύποι Δεδομένων

structure (δομή): ομαδοποίηση πολλών μεταβλητών κάτω από ένα κοινό όνομα Π.χ. εγγραφή αρχείου Π.χ. γραμμή σε βάση δεδομένων

union (ένωση): επιτρέπει το ίδιο μέρος της μνήμης να οριστεί ως δύο ή παραπάνω διαφορετικούς τύπους μεταβλητών

enumeration (απαρίθμηση): λίστα συμβόλων

typedef: δημιουργία νέων ονομάτων τύπων δεδομένων

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

3

Δομή (structure)

Ομαδοποίηση πολλών μεταβλητών κάτω από ένα κοινό όνομα Κρατιούνται μαζί τα δεδομένα που σχετίζονται

μεταξύ τους Η δήλωση μιας δομής ορίζει ένα πρότυπο

Μπορεί να χρησιμοποιηθεί για τη δημιουργία μεταβλητών αυτού του προτύπου

Οι μεταβλητές που απαρτίζουν μια δομή λέγονται στοιχεία ή μέλη (members) της δομής Όλα τα στοιχεία μιας δομής πρέπει να σχετίζονται

λογικά μεταξύ τους Π.χ. όνομα, επώνυμο και διεύθυνση ενός ατόμου

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

4

Δήλωση Δομής

Δομή για την αναπαράσταση των στοιχείων ενός μαθητή

struct mathitis { char onoma[15]; char eponymo[25]; short int apousies; short int vathmos;

}; Πληροφορεί τον μεταγλωττιστή της C ότι ξεκινά η δήλωση μιας δομής (ή μιας μεταβλητής δομής).

Όνομα της δομής

Δηλώσεις στοιχείων

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

5

Χρήση Δομής

Ακόμα δεν έχει δημιουργηθεί καμία μεταβλητή

Το mathitis είναι ένας καινούριος τύπος δεδομένων

Μπορεί να χρησιμοποιηθεί για τη δήλωση μεταβλητών αυτού του τύπου

struct mathitis x1;

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

6

Ταυτόχρονη Δήλωση και Χρήση Δομής

Μπορούμε να δηλώσουμε μεταβλητές ταυτόχρονα με τη δήλωση μιας δομής

struct mathitis {

char onoma[15];

char eponymo[25];

unsigned short int apousies;

unsigned short int vathmos;

} x1, x2, x3;

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

7

Ανώνυμες Δομές Όταν δηλώνουμε μεταβλητές μαζί με

τη δομή μπορούμε να μη δώσουμε όνομα στη δομή Όταν δεν πρόκειται να δηλώσουμε

επιπλέον μεταβλητές αυτού του τύπου

struct { char onoma[15]; char eponymo[25]; unsigned short int apousies; unsigned short int vathmos;} x1, x2, x3;

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

8

Προσπέλαση Στοιχείων Δομής

Τα στοιχεία μιας μεταβλητής δομής, μπορούν να προσπελαστούν με τον τελεστή τελεία “.”

Γενική μορφή:struct_var_name.member_name

Παράδειγμα: x1.apousies = 2;

printf("%d", x1.apousies);

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

9

Σύνθετες Δομές

struct mathitis { char onoma[15]; ...

struct date birthday;} x1;struct date {

int day;int month;int year;

};

•Πρόσβαση στοιχείων «εσωτερικής» δομής

x1.birthday.year;

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

10

Πίνακες από Δομές

Η πιο συνηθισμένη χρήση των δομών, είναι σε πίνακες πολλών μεταβλητών δομής

Για να δηλωθεί ένας πίνακας από δομές, πρέπει να δηλωθούν: η δομή, και μετά ένας πίνακας από αυτές τις δομές

Παράδειγμα:struct mathitis m[100];

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

11

Πίνακες από Δομές – Προσπέλαση Στοιχείων

Για να προσπελαστεί ένα στοιχείο μέσα στον πίνακα πρέπει να χρησιμοποιηθεί ο αύξων

αριθμός του στοιχείου στον πίνακα

Π.χ. εκτύπωση ονόματος του τρίτου μαθητή:

printf("%s", m[2].onoma);

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

12

Δομές και Συναρτήσεις

Πέρασμα μεμονωμένου στοιχείου δομής ως παράμετρο σε συνάρτηση

Πέρασμα ολόκληρης δομής Κλήση με τιμή

Πέρασμα διεύθυνσης μνήμης δομής Κλήση με αναφορά

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

13

Στοιχεία Δομής ως Παράμετροι Συναρτήσεων

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

Παράδειγμα δομής:struct paradeigma { char c; int i; float f; char s[10];} x;

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

14

Παραδείγματα Κλήσης με Τιμή

func_v1(x.c);

func_v2(x.i);

func_v3(x.f);

func_v4(x.s[2]);

struct paradeigma { char c; int i; float f; char s[10];} x;

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

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;

ο τελεστής διεύθυνσης & τοποθετείται πριν από το όνομα της μεταβλητής δομής

όχι πριν από την μεταβλητή του στοιχείου της δομής

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

16

Παραδείγματα Κλήσης με Αναφορά

func_r4(x.s);

struct paradeigma { char c; int i; float f; char s[10];} x;

Επειδή το όνομα ενός πίνακα χαρακτήρων είναι η διεύθυνση του πρώτου στοιχείου του πίνακα, παραλείπουμε τελείως τον τελεστή &

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

17

Παραδείγματα Κλήσης με Αναφορά

func_r5(&x.s[2]);

struct paradeigma { char c; int i; float f; char s[10];} x;

Όταν θέλουμε να δώσουμε τη διεύθυνση κάποιου συγκεκριμένου στοιχείου του πίνακα (εκτός του πρώτου) τότε πρέπει να χρησιμοποιήσουμε τον τελεστή &

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

18

Παραδείγματα Κλήσης με Αναφορά

func_r5((x.s)+2);

struct paradeigma { char c; int i; float f; char s[10];} x;

Εναλλακτικά θα μπορούσε να είχε χρησιμοποιηθεί αριθμητική δεικτών

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

19

Κλήση Συνάρτησης με Τιμή μιας Ολόκληρης Δομής

Όταν μια μεταβλητή δομής δίνεται ως παράμετρος σε μια συνάρτηση, τότε γίνεται μια τυπική κλήση της συνάρτησης με τιμή.

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

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

20

Κλήση Συνάρτησης με Τιμή μιας Ολόκληρης Δομής

Ο τύπος της τυπικής παραμέτρου της συνάρτησης πρέπει να είναι ίδιος με τον τύπο της μεταβλητής-παραμέτρου

Η δομή πρέπει να δηλωθεί ως καθολικός τύπος δεδομένων

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

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

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);}

Καθολικός τύπος δεδομένων

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

22

Κλήση Συνάρτησης με Αναφορά σε μία Ολόκληρη Δομή

Μπορούμε να περνάμε τη διεύθυνση μνήμης μιας μεταβλητής δομής ως παράμετρο σε συνάρτηση

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

δομής στη μνήμη έχουμε κλήση της συνάρτησης με αναφοράΠ

λεο

νέκτη

μα

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

23

Κλήση Συνάρτησης με Αναφορά σε μία Ολόκληρη Δομή

Η εκτέλεση της συνάρτησης

επιταχύνεται δραστικάΔεν δημιουργείται αντίγραφο της

μεταβλητής δομής στη μνήμη για

χρήση μόνο μέσα στην συνάρτηση

Έχουμε απευθείας προσπέλαση

στη μνήμη

Πλεο

νέκτη

μα

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

24

Δήλωση Δείκτη σε Δομή

Γενική μορφή:

struct onoma_domis *onoma_deikti Θα πρέπει να έχει προηγηθεί η δήλωση

του structure με όνομα onoma_domis Υπάρχουν κάποια σημεία

διαφοροποίησης από τους υπόλοιπους δείκτες

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

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;}

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

26

Τελεστής Βέλος (->)

Δεν μπορεί να χρησιμοποιηθεί ο τελεστής τελεία (.) για προσπέλαση των στοιχείων της δομής

Πρέπει να χρησιμοποιηθεί ένας καινούργιος τελεστής, ο τελεστής βέλος (->)

Π.χ. για προσπέλαση του στοιχείου apousies μέσω του δείκτη p:

p->apousies = 2;

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

27

Εναλλακτική Προσπέλαση Στοιχείου Δομής από Δείκτη

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

(*p).apousies = 2;

p->apousies = 2;

Η χρήση των παρενθέσεων είναι απαραίτητη λόγω χαμηλότερης προτεραιότητας του τελεστή *

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

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;

}

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

29

Συναρτήσεις που Επιστρέφουν Δομές

void main(void){

struct mathitis x;

char first[]=“John”;char last[]=“Smith”;

x = make_student(first,last);}

Επιτρέπεται η ανάθεση τιμής σε ολόκληρη τη δομή (αντιγραφή)

Δεν επιτρέπεται σύγκριση δομών

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

30

Εφαρμογή – Μέτρηση Συχνότητας Εμφάνισης Λέξεων σε Κείμενο

Έχουμε ένα μεγάλο κείμενο και ψάχνουμε μέσα σε αυτό να βρούμε πόσες φορές εμφανίζονται συγκεκριμένες λέξεις-κλειδιά

Χρειαζόμαστε 2 πίνακες Για την αποθήκευση των λέξεων-κλειδιών

char *keyword[NKEYS]; Για την αποθήκευση της συχνότητας

εμφάνισης της κάθε λέξης

int keycount[NKEYS];

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

31

Χρήση Πίνακα Δομών

Υπάρχει 1-1 αντιστοιχία μεταξύ των 2 πινάκων, το πιο «κομψό» θα ήταν να χρησιμοποιηθεί 1 πίνακας δομών

struct key { char *word;

int count;

};

struct key keytab[NKEYS];

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

32

Αρχικοποίηση Πίνακα Δομών

Ο πίνακας θα χρησιμοποιείται σε πολλά σημεία του προγράμματος Ορίζεται ως εξωτερική (global) μεταβλητή

struct key keytab[] = { {"account",0}, ... {"programming",0}, {"unix",0}

};

Κάθε ζεύγος αντι-στοιχεί στα στοι-χεία μιας δομής Τα εσωτερικά

άγκιστρα δεν είναι υποχρε-ωτικά

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

33

Δομή Προγράμματος

Η συνάρτηση main καλεί συνεχώς τη συνάρτηση getword Διαβάζει από την είσοδο μία λέξη τη φορά

Κάθε λέξη αναζητείται μέσα στον πίνακα keytab χρησιμοποιώντας «δυαδική αναζήτηση» (binary search)

Η λίστα των λέξεων-κλειδιών πρέπει να είναι ταξινομημένη σε αύξουσα σειρά

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

34

Συνάρτηση main

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(); //Για να προλάβουμε να δούμε τα αποτελέσματα

}

Κάθε κλήση στην getword βρίσκει μια λέξη και την αντιγράφει στον

πίνακα word

Δυαδική αναζήτηση του string word στον πίνακα keytab

Αυξάνεται ο αντί-στοιχος counter

Εκτύπωση αποτελεσμάτων

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

35

Επικεφαλίδες

#include <stdio.h>#include <ctype.h> #include <string.h>

#define MAXWORD 100

#define NKEYS (sizeof keytab / sizeof(struct key))

Τελεστής compile-time Επιστρέφει το μέγεθος μιας δομής

δεδομένων

Αριθμός λέξεων-κλειδιών

Μέγεθος ολόκλη-ρου του πίνακα

Μέγεθος ενός στοιχείου του πίνακα

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

36

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;

}

Συνάρτηση binsearch

• Συγκρίνω το string word με το string στη θέση mid του πίνακα

• Αρχικά πρόκειται για το μέσο του πίνακα

• Αν το word είναι μικρότερο, η επόμενη αναζήτηση θα γίνει στο μέσο του μισού πίνακα (προς τα κάτω)

• Αν το word είναι μεγαλύτερο, η επόμενη αναζήτηση θα γίνει στο μέσο του μισού πίνακα (προς τα πάνω)

• Αλλιώς, βρέθηκε

• Αν το «κάτω» ξεπεράσει το «πάνω», τότε δεν βρέθηκε

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

37

Συνάρτηση getwordint 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

Αγνοεί τα αρχικά κενά

Διαβάστηκε κάποιος «σωστός» χαρακτήρας

Αν δε διαβάστηκε γράμμα σταμάτα Κύριος βρόχος ανάγνωσης,

μέχρι να συναντηθεί μη-αλφαριθμητικός χαρακτήρας

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

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);

}

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

39

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;

}

Εναλλακτικό πρόγραμμα – Χρήση Δεικτών σε Δομές - binsearch

Η συνάρτηση πλέον επιστρέφει pointers και όχι ακεραίους

Η προσπέλαση στοι-χείων του keytab γίνεται πλέον με δείκτες

• Αρχικά εκτός ορίων πίνακα

• Η αριθμητικές πρά-ξεις δεικτών εξα-σφαλίζουν σωστό αποτέλεσμα

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

40

Ένωση (union)

Είναι μια θέση μνήμης που μπορεί να χρησιμοποιηθεί από πολλές μεταβλητές διαφορετικού τύπου

Δήλωση παρόμοια με τη δήλωση μιας δομής

union paradeigma { int i; char ch;};

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

41

Μεταβλητές union

Μια μεταβλητή union μπορεί να δηλωθεί τοποθετώντας το όνομα της μαζί

με τη δήλωση του union, ήΜετά, σαν μια ξεχωριστή δήλωση

union paradeigma x1;

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

42

Μεταβλητές union και Μνήμη

Ο ακέραιος i και ο χαρακτήρας ch μοιράζονται τον ίδιο χώρο μνήμης.

Ο i καταλαμβάνει 2 bytes ενώ ο ch 1

Byte 0 Byte 1

i

ch

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

43

Μεταβλητές union και Μνήμη

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

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

44

Προσπέλαση στοιχείων union

Παρόμοια με τις δομές Αν χρησιμοποιούμε απευθείας μεταβλητή

union, χρησιμοποιούμε τον τελεστή τελεία

Αν χρησιμοποιούμε δείκτη προς union, τότε χρησιμοποιούμε τον τελεστή βέλος

Π.χ., για ανάθεση της τιμής 10 στην ακέραια μεταβλητή i:

x1.i = 10;