ΜΑΘΗΜΑ 4 ο

52
4-1 ΜΑΘΗΜΑ 4 ο Πολυδιάστατοι Πίνακες, Δομές, Ενώσεις

description

ΜΑΘΗΜΑ 4 ο. Πολυδιάστατοι Πίνακες, Δομές, Ενώσεις. Πίνακες ως ΑΤΔ( i ). Βασική πράξη: προσπέλαση στοιχείου a[i] Συνήθως υλοποιούνται με κάποιο ΣΤΔ πινάκων ( arrays) Κόστος προσπέλασης: O(1) Ο ΣΤΔ του μονοδιάστατου πίνακα επαρκεί για την υλοποίηση κάθε ΑΤΔ πίνακα - PowerPoint PPT Presentation

Transcript of ΜΑΘΗΜΑ 4 ο

4-1

ΜΑΘΗΜΑ 4ο

Πολυδιάστατοι Πίνακες, Δομές,

Ενώσεις

4-2

Πίνακες ως ΑΤΔ (i)

• Βασική πράξη: προσπέλαση στοιχείου

a[i]

• Συνήθως υλοποιούνται με κάποιο ΣΤΔ πινάκων (arrays)

– Κόστος προσπέλασης: O(1)

• Ο ΣΤΔ του μονοδιάστατου πίνακα επαρκεί για την υλοποίηση

κάθε ΑΤΔ πίνακα

– Συνάρτηση loc υπολογίζει τη θέση ενός στοιχείου του ΑΤΔ

πίνακα στο μονοδιάστατο ΣΤΔ πίνακα της υλοποίησης

4-3

Πίνακες ως ΑΤΔ (ii)

• ΑΤΔ πίνακα δύο διαστάσεων n m

loc (n, m, i, j) = m (i – 1) + j – 1

• Αρίθμηση κατά στήλες

loc (n, m, i, j) = n (j – 1) + i – 1

0 1 2 3 4 5

6 7 8 9 10 11

12 13 14 15 16 17

i = 1

i = 2

i = 3

j = 1 2 4 5 63

n = 3

m = 6

4-4

Πίνακες ως ΑΤΔ (iii)

• ΑΤΔ κάτω τριγωνικού πίνακα n n

loc (n, i, j) = i (i – 1) / 2 + j – 1

• Ομοίως για συμμετρικούς πίνακες

0

1 2

3 4 5

i = 1

i = 2

i = 3

j = 1 2 4 53

n = 5

6 7 8 9

10 11 12 13 14

i = 4

i = 5

4-5

Πίνακες ως ΑΤΔ (iv)

• ΑΤΔ τριδιαγώνιου πίνακα n n

loc (n, i, j) = 2 i + j – 3

0 1

2 3 4

5 6 7

i = 1

i = 2

i = 3

j = 1 2 4 53

n = 5

8 9 10

11 12

i = 4

i = 5

4-6

Πίνακες ως ΑΤΔ (v)

• ΑΤΔ αραιού πίνακα n m

– Υλοποίηση με δυαδικό πίνακα

– Υλοποίηση με τρεις πίνακες

row = [ 1, 2, 3, 3, 4 ] col = [ 1, 3, 2, 3, 5 ]

val = [ a1, a2, a3, a4, a5 ]

a1

a2

a3 a4

i = 1

i = 2

i = 3

j = 1 2 4 53

n = 4

a5i = 4

m = 5

4-7

ΠΑΡΑΔΕΙΓΜΑ ΜΕ ΠΟΛΥΔΙΑΣΤΑΤΑ ΔΙΑΝΥΣΜΑΤΑ

• Στη C τα πολυδιάστατα διανύσματα αποθηκεύονται στη μνήμη σειριακά κατά σειρά (row-major order)

• Ένα παράδειγμα χρήσης πολυδιάστατου (2 διαστάσεις) πίνακα είναι

#define N 10

float ident_matrix[N][N]

int row, col;

for (row = 0; row < N; row++)

for(col=0; col <N; col++)

if(row == col)

ident_matrix[row][col] = 1.0;

else

ident_matrix[row][col] = 0.0

4-8

ΑΡΧΙΚΕΣ ΤΙΜΕΣ ΔΙΑΝΥΣΜΑΤΟΣ

• Εάν το διάνυσμα δεν είναι μεγάλο τότε μπορούμε να του δώσουμε αρχικές τιμές με τον παρακάτω τρόπο:

int A[3][4] = { {1, 3, 5, 2},

{6, 10, 9, 12},

{4, 3, 1}

}

Ό,τι στοιχεία μπορεί να λείπουν από μία γραμμή παίρνουν αρχική τιμή 0.

4-9

ΠΑΡΑΔΕΙΓΜΑΤΑ ΧΡΗΣΗΣ

• Ένα τυπικό παράδειγμα της χρήσης διανυσμάτων είναι η ταξινόμηση στοιχείων

• Στο πρόβλημα της ταξινόμησης θέλουμε να οργανώσουμε μια λίστα αριθμών ή γραμμάτων σε αύξουσα ή φθίνουσα σειρά

• Ένας απλός (αλλά αργός) αλγόριθμος ταξινόμησης είναι ο bubble sort

• Ο αλγόριθμος δουλεύει ώς εξής:

– Σαρώνοντας τη λίστα, κάθε φορά που δύο στοιχεία είναι εκτός σειράς, ενάλλαξέ τα:

– Επανέλαβε μέχρι να μην υπάρχει η δυνατότητα εναλλαγής των στοιχείων

4-10

BUBBLE SORT

#include <stdio.h>

void main() {

int notDone = 1;

int list[10];

int unSortedCount = sizeof(list) /sizeof(list[0]);

int N = unSortedCount;

/*Διαβάζουμε αριθμούς */

printf(“Enter %d numbers:”,N);

for (int j=0; i<N; j++)

scanf(“%d”, &list[j]);

printf(“\n”);

/* Ταξινομούμε */while( unSortedCount > 1 && notDone) { notDone = 0; for (int i = 0; i < unSortedCount -1; ++i) if (list[i] > list[i+1]) { temp = list[i] list[i] = list[i+1]; list[i+1] = temp; notDone = 1; } unSortedCount--; }}

4-11

Αναζήτηση σε πίνακες (i)

• Σειριακή αναζήτηση

– Τα στοιχεία διατρέχονται κατά σειρά

– Κόστος: O(n)

12 9 72 22 42 99 14 61n = 8x = 42

(1) (3)(2) (4) (5)

– Βελτίωση: στοιχείο “φρουρός” (sentinel)

12 9 72 22 42 99 14 61n = 8x = 77

4-12

Αναζήτηση σε πίνακες (ii)

• Υλοποίηση σε C

int ssearch (int a[], int n, int x)

{

int i;

for (i = 0; i < n; i++)

if (a[i] == x)

return i;

return -1;

}

4-13

Αναζήτηση σε πίνακες (iii)

• Υλοποίηση σε C με φρουρό

int ssearch_s (int a[], int n, int x)

{

int i;

a[n] = x;

for (i = 0; a[i] != x; i++);

return (i < n) ? i : -1;

}

4-14

Αναζήτηση σε πίνακες (iv)

• Δυαδική αναζήτηση

– Ο πίνακας πρέπει να είναι ταξινομημένος

– Κόστος: O(logn)

3 7 14 22 42 61 72 99n = 8x = 42

(1) (3) (2)

• Άλλες μέθοδοι αναζήτησης

– Μικρότερο κόστος περισσότερος χώρος

– Πίνακες κατακερματισμού (hash tables)

4-15

ΕΠΙΣΚΟΠΗΣΗ - ΣΥΝΑΡΤΗΣΕΙΣ

• Στη C ο όρος «συνάρτηση» ορίζει μία ακολουθία εντολών που έχουν ομαδοποιηθεί, και ταξινομηθεί μ’ένα συμβολικό όνομα

• Στη C κάθε συνάρτηση είναι ουσιαστικά ένα μικρό πρόγραμμα, με τις δικές του δηλώσεις μεταβλητών, και τις δικές του εντολές.

• Δηλαδή μια συνάρτηση είναι – κατανομασμένη, – ανεξάρτητη, – εκτελεί συγκεκριμένη εργασία, και – μπορεί να επιστρέψει κάποιο αποτέλεσμα

• Η ιδέα είναι ότι ένα σύνθετος αλγόριθμος μπορεί να διασπασθεί σε μικρότερα κομμάτια τα οποία είναι ευκολότερα να κατανοηθούν, να υλοποιηθούν, και να συντηρηθούν (ας θυμηθούμε την έννοια της αναλυτικής - top-down - σχεδίασης αλγορίθμων)

• Κάθε τέτοιο κομμάτι μπορεί να υλοποιηθεί σαν μία συνάρτηση

4-16

ΑΝΑΛΥΤΙΚΗ (ΚΑΘΕΤΗ – top down) ΜΕΘΟΔΟΛΟΓΙΑ ΕΠΙΛΥΣΗΣ ΠΡΟΒΛΗΜΑΤΩΝ

Σύνθετο Πρόβλημα

Υπο-Πρόβλημα 1

Υπο-Πρόβλημα 2

Υπο-Πρόβλημα 3

Υπο-Πρόβλημα 1-1

Υπο-Πρόβλημα 1-2

Υπο-Πρόβλημα 2-1

Υπο-Πρόβλημα 3-1

Υπο-Πρόβλημα 3-2

4-17

ΟΡΓΑΝΩΣΗ ΠΡΟΓΡΑΜΜΑΤΟΣ

main

Συνάρτηση-1 Συνάρτηση-2 Συνάρτηση-3

Συνάρτηση-1.1 Συνάρτηση-1.2 Συνάρτηση-2.1 Συνάρτηση-3.1 Συνάρτηση-3.2

4-18

ΔΟΜΗ ΠΡΟΓΡΑΜΜΑΤΟΣ

#include <stdio.h>………………….#define ……..

Δηλώσεις τύπωνΔηλώσεις πρωτότυπων Δηλώσεις μεταβλητών-α

void main() { Δηλώσεις τοπικών μεταβλητών-β ........................... ........................... κλήση συνάρτηση-1(..); ......................... κλήση συνάρτηση-2(..); ......................... κλήση συνάρτηση-3(..); .........................}

}

Τύπος συνάρτηση-1(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-γ ..................................... ..................................... κλήση συνάρτηση-1.1(..) ...................................... κλήση συνάρτηση-1.2(...) }

Τύπος συνάρτηση-1.1(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-δ ..................................... ..................................... } .................................... ....................................Τύπος συνάρτηση-2(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-ε ..................................... ..................................... }

4-19

ΡΟΗ ΠΡΟΓΡΑΜΜΑΤΟΣ

void main() { ……… κλήση συνάρτηση-1 (..); ..................................... κλήση συνάρτηση-2(..); ..................................... κλήση συνάρτηση-3(..); .....................................}

τύπος συνάρτηση-1(..) { ..................................... κλήση συνάρτηση-1.1(..); .................................. κλήση συνάρτηση-1.2(..); .................................}

τύπος συνάρτηση-1.1(..) { ..................................... .....................................}

4-20

ΟΡΟΛΟΓΙΑ ΣΧΕΤΙΚΗ ΜΕ ΣΥΝΑΡΤΗΣΕΙΣ

• Πρωτότυπο συνάρτησης (function declarations)

• Δήλωση συνάρτησης (function definitions)

• Παράμετροι συνάρτησης (formal parameters)

• Ορίσματα συνάρτησης (actual parameters)

• Σώμα συνάρτησης (function body)

• Κλήση συνάρτησης (function call)

– Επιστροφή τιμών (return values)

– Διοχέτευση ορισμάτων (parameter passing)• By value• By reference

4-21

ΠΡΩΤΟΤΥΠΟ ΣΥΝΑΡΤΗΣΗΣ

• Οι συναρτήσεις είναι και αυτές στοιχεία και κατασκευές της γλώσσας και σαν τέτοια πρέπει να δηλωθούν

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

• Το πρωτότυπο μίας συνάρτησης είναι μια «προ-δήλωση» κατά κάποιο τρόπο που παρέχει στον μεταγλωττιστή την πληροφορία ότι κάπου αργότερα στο πρόγραμμα η συνάρτηση θα δηλωθεί

• Το πρωτότυπο περιλαμβάνει το όνομα της συνάρτησης, τον τύπο του αποτελέσματος που επιστρέφει (αν επιστρέφει κάποιο αποτέλεσμα), το τύπο και (προαιρετικά) το όνομα κάθε παραμέτρου.

• Η σύνταξη πρωτότυπου συνάρτησης είναι:

<τύπος επιστροφής> <ονομα_συνάρτησης> (τύπος1 παραμετρος1, ... τύποςκ παραμετροςκ)

4-22

ΠΡΟΤΟΤΥΠΟ - ΣΧΗΜΑΤΙΚΑ

#include <stdio.h>………………….#define ……..

Δηλώσεις τύπωνΔηλώσεις προτοτύπων Δηλώσεις μεταβλητών-α

void main() { Δηλώσεις τοπικών μεταβλητών-β ........................... ........................... κλήση συνάρτηση-1(..); ......................... κλήση συνάρτηση-2(..); ......................... κλήση συνάρτηση-3(..); .........................}

}

Τύπος συνάρτηση-1(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-γ ..................................... ..................................... κλήση συνάρτηση-1.1(..) ...................................... κλήση συνάρτηση-1.2(...) }

Τύπος συνάρτηση-1.1(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-δ ..................................... ..................................... } .................................... ....................................Τύπος συνάρτηση-2(τύπος παράμετρος, ....) { Δηλώσεις τοπικών μεταβλητών-ε ..................................... ..................................... }

4-23

ΟΡΙΣΜΟΣ ΣΥΝΑΡΤΗΣΗΣ

• Η κάθε συνάρτηση έχει σαν σκοπό να υλοποιήσει και να εκτελέσει ένα συγκεκριμένο κομμάτι ενός αλγόριθμου

• Συνεπώς ο προγραμματιστής θα πρέπει να γράψει τον κώδικα που αντιστοιχεί στην υλοποίηση αυτού του κομματιού

• Αυτό γίνεται με τον ορισμό της συνάρτησης που έχει τη μορφή

<τύπος επιστροφής> <ονομα_συνάρησης> (τύπος1 παραμετρος1, ... τύποςκ παραμετροςκ) {

...........................................

κώδικας

...........................................

}

4-24

ΠΑΡΑΔΕΙΓΜΑ

#include <stdio.h>

int sum(int, int);

int i, j, k;

void main() {

printf(“Enter two numbers:”);

scanf(“%d %d”, &i, &j);

k = sum(i,j);

printf(“The sum of %d, %d is: %d”, I, j, k);

}

int sum(int number1, int number2) {

int m;

m = number1 + number2;

return(m);

}

Πρωτότυπο Συνάρτησης

Δήλωση Συνάρτησης

4-25

ΠΑΡΑΔΕΙΓΜΑ

#include <stdio.h>

int sum(int, int);

int i, j, k;

void main() {

printf(“Enter two numbers:”);

scanf(“%d %d”, &i, &j);

k = sum(i,j);

printf(“The sum of %d, %d is: %d”, ι, j, k);

}

int sum(int number1, int number2) {

int m;

m = number1 + number2;

return(m);

}

Σώμα Συνάρτησης

4-26

ΠΑΡΑΜΕΤΡΟΙ & ΟΡΙΣΜΑΤΑ

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

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

• Τα ορίσματα της συνάρτησης είναι οι «παράμετροι» που βρίσκονται στη κλήση της συνάρτησης, σε κάποιο σημείο του προγράμματος

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

4-27

ΚΛΗΣΗ ΤΗΣ ΣΥΝΑΡΤΗΣΗΣ

• Μία συνάρτηση μπορεί να κληθεί με δύο τρόπους:

1. χρησιμοποιώντας το όνομά της και τη λίστα των ορισμάτων της σε μια αυτόνομη πρόταση π.χ.

.............................. wait(12); …………………….

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

2. χρησιμοποιώντας το όνομά της και τη λίστα των ορισμάτων της σε μια έκφραση π.χ.

..............................

k = sum(2, 10); ……………………. Εδώ θεωρούμε ότι η συνάρτηση επιστρέφει κάποιο αποτέλεσμα που αποτίθεται

στη μεταβλητή k

4-28

ΜΗΧΑΝΙΣΜΟΣ ΚΛΗΣΗΣ

• Ο μηχανισμός κλήσης μιάς συνάρτησης βασίζεται:

1. Στην συσχέτιση του ονόματος της συνάρτησης στο σημείο ορισμού της με το όνομα της συνάρτησης στο σημείο κλήσης

2. Στη συσχέτιση του πλήθους των παραμέτρων της συνάρτησης στο σημείο ορισμού της με το πλήθος των παραμέτρων της συνάρτησης στο σημείο κλήσης

3. Στη συσχέτιση του τύπου επιστροφής της συνάρτησης στο σημείο ορισμού της με τη χρήση του αποτελέσματος της συνάρτησης στο έκφραση που υπάρχει η κλήση της συνάρτησης

• Θα δούμε αργότερα ότι υπάρχουν δύο τρόποι διοχέτευσης ορισμάτων

– Με μετάδοση τιμής – απόθεση (By value)

– Με απ’ευθείας χρήση (By reference)

4-29

ΠΑΡΑΔΕΙΓΜΑ

#include <stdio.h>

int sum(int, int);

int i, j, k;

void main() {

printf(“Enter two numbers:”);

scanf(“%d %d”, &i, &j);

k = sum( i, j );

printf(“The sum of %d, %d is: %d”, ι, j, k);

}

int sum(int number1, int number2) {

int m;

m = number1 + number2;

return(m);

}

Παράμετροι – (number1, number2)

Ορίσματα – (i, j)

4-30

ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ

• Στο σώμα μίας συνάρτησης μπορούμε να ορίσουμε μεταβλητές

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

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

• Είναι γενικά κακό προγραμματιστικό στυλ να χρησιμοποιούμε το ίδιο όνομα για μία τοπική μεταβλητή (local variable) και μία ολική (global variable)

4-31

ΠΑΡΑΔΕΙΓΜΑ

#include <stdio.h>

int sum(int, int);

int i, j, k;

void main() {

printf(“Enter two numbers:”);

scanf(“%d %d”, &i, &j);

for(int j=0; j<5; j++)

printf(“Processing…\n”);

k = sum( i, j );

printf(“The sum of %d, %d is: %d”, ι, j, k);

}

int sum(int number1, int number2) {

int m;

m = number1 + number2;

return(m); }

Τοπικής εμβέλειας μεταβλητή – m

Ολικής εμβέλειας μεταβλητές – i, j, k

Τοπικής εμβέλειας μεταβλητή – j (ισχύει όσο τρέχειη εντολή for)

4-32

Static Μεταβλητές

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

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

• Εάν για κάποιο λόγο χρειάζεται να κρατάμε τη τιμή μιας «τοπικής» μεταβλητής ανάμεσα σε διαδοχικές κλήσεις τότε τη δηλώνουμε σαν static. Παρακάτω δίνουμε κάποια παραδείγματα που επεξηγούν τη χρήση των μεταβλητών static

4-33

Παράδειγμα

#include <stdio.h>

void TestFunction(void);

Int main() {

testFunction();

testFunction();

testFunction();

return 0;

}

void testFunction() {

static int alreadyCalled = 0;

if (!alreadyCalled)

printf(“First Time call of testFunction\n”);

alreadyCalled=1;

}

Output:

First Time cal of Test Function

4-34

Παράδειγμα

#include <stdio.h>

void TestFunction(void);

Int main() {

testFunction();

testFunction();

testFunction();

return 0;

}

void testFunction() {

int alreadyCalled = 0; /* Όχι static */

if (!alreadyCalled)

printf(“First Time call of testFunction\n”);

alreadyCalled=1;

}

Output:

First Time cal of Test Function

First Time cal of Test Function

First Time cal of Test Function

4-35

Extern Μεταβλητές

• Ας υποθέσουμε ότι γράφουμε ένα πρόγραμμα με περισσότερα από ένα αρχεία πηγαίου κώδικα (πχ, με δύο αρχεία F1.c, και F2.c, όπου στο F1.c έχουμε τo main και στο F2.c μια συνάρτηση του προγράμματος).

• Εάν σε αυτή τη περίπτωση θελήσουμε κάποια ή κάποιες μεταβλητές που έχουν γενική εμβέλεια στο F1.c να έχουν γενική εμβέλεια και στο F2.c τότε δηλώνονται σαν extern στο F2.c. Το παρακάτω παράδειγμα επεξηγεί τη χρήση των μεταβλητών extern.

4-36

Παράδειγμα

#include <stdio.h>

int i;

void TestFunction(void);

Int main() {

i=10;

printf(“The variable i is $d in main - first\n”);

testFunction();

printf(“The variable i $d in main - second\n”);

return 0;

}

Output:The variable i is 10 in main – first

The variable I is 20 in main – second

#include <stdio.h>

extern int i;

void testFunction() {

i = 20;

}

F1.c F2.c

4-37

Παράδειγμα

#include <stdio.h>

static int i; /* ΄Τώρα είναι static */

void TestFunction(void);

Int main() {

i=10;

printf(“The variable i is $d in main - first\n”);

testFunction();

printf(“The variable i $d in main - second\n”);

return 0;

}

H static έχει εμβέλεια μόνοι στο F1.c

#include <stdio.h>

extern int i;

void testFunction() {

i = 20;

}

F1.c F2.c

Link error

4-38

ΔΟΜΕΣ

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

βασικούς τύπους που υποστηρίζει η C (π.χ. ιnt, char, float κλπ.)

• Μια σχετική εξαίρεση ήταν τα διανύσματα που λίγο-πολύ μοιάζουν με

«δεξαμενές» που μπορούμε να αποθηκεύσουμε δεδομένα (ενός

συγκεκριμένου τύπου) σε μια ακολουθιακή μορφή

• Εδώ θα εξετάσουμε μια νέα μορφή μεταβλητής που και αυτή μοιάζει με

«δεξαμενή» αλλά:

1. Επιτρέπει να αποθηκευτούν δεδομένα διαφορετικών τύπων που έχουν κάποια «λογική»

σχέση μεταξύ τους

2. Είναι πιο δομημένη από την απλή ακολουθιακή μορφή των διανυσμάτων

4-39

ΠΑΡΑΔΕΙΓΜΑ

struct {

int number;

int sex;

char name[10];

char address[40];

int age;

} malePerson, femalePerson;

Τύπος Δομής

Μεταβλητές

4-40

ΠΑΡΑΔΕΙΓΜΑ

struct {

int number;

int sex;

char name[10];

char address[40];

int age;

} person1;

struct {

int number;

int name[10];

int yearsOfEmployment;

} employee1;

Διαφορετικές εμβέλειες

4-41

ΑΡΧΙΚΕΣ ΤΙΜΕΣ ΓΙΑ ΔΟΜΕΣ

• Όπως και στα διανύσματα, έτσι και μία δομή μπορεί να πάρει αρχικές τιμές κατά τη δήλωση της π.χ.

struct {

int number;

int sex;

char name[11];

} person1 = (154, 1, “John Smith”),

person2 = (180, 2, “Mary Jones”);

154

1

John Smith

4-42

ΛΕΙΤΟΥΡΓΙΕΣ ΣΕ ΔΟΜΕΣ

• Όπως και στα διανύσματα, έτσι και στις δομές, η πιο κοινή

λειτουργία είναι να βρούμε κάποιο στοιχείο της π.χ.

printf(“The name of person %d is %s”,

person1.number, person1.name);

Μέλος της ΔομήςΤελεστής Πρόσβασης

Δομή (μεταβλητή)

4-43

ΠΑΡΑΔΕΙΓΜΑ

scanf(“%d”, &pesron1.number);

/* Διαβάζουμε το μέλος number) */

person1 = person2;

/* Αποθέτουμε τις τιμές των μελών της person2, στην person1 */

Σημείωση: Αυτό δεν ήταν εφικτό στα διανύσματα

4-44

ΤΥΠΟΣ ΔΟΜΗΣ

• Μέχρι τώρα είδαμε πως να δηλώνουμε μεταβλητές που ήταν δομές. Ας υποθέσουμε ότι σε ένα πρόγραμμα θέλουμε να δηλώσουμε πολλές μεταβλητές που έχουν την ίδια δομή (ίδια μέλη). Εάν όλες αυτές οι μεταβλητές μπορούν να δηλωθούν μαζί τότε το πρόβλημα δεν είναι μεγάλο. Εάν όμως δηλώνονται σε διάφορα σημεία του προγράμματος τότε τα πράγματα είναι πιο δύσκολα (πρέπει να επαναλαμβάνουμε τη δήλωση της δομής).

• Ιδανικά, θα θέλαμε να έχουμε την ευχέρεια να δηλώσουμε τον δικό μας τύπο και απλά να χρησιμοποιούμε το όνομά του όπως θα χρησιμοποιούσαμε int, float, κλπ.

4-45

ΕΤΙΚΕΤΑ ΔΟΜΗΣ structure tag

• Η ετικέτα δομής είναι ένα συμβολικό όνομα που ορίζει μία συγκεκριμένη δομή π.χ.

struct sparePart {

int idNumber;

char descr[100];

int avail;

} ;

struct sparePart var1, var2;

Σημαντικό !!

Δήλωση μεταβλητών τύπου struct sparePart

4-46

ΔΗΛΩΣΗ ΤΥΠΟΥ ΔΟΜΗΣ

• Αντί να δηλώνουμε μία ετικέτα δομής μπορούμε να

δηλώσουμε τον δικό μας τύπο να του δώσουμε ένα όνομα

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

χρησιμοποιούσαμε κάθε άλλο τύπο που μας δίνει η C.

• Αυτό επιτυγχάνεται με την εντολή typedef

4-47

ΠΑΡΑΔΕΙΓΜΑ

typedef struct {

int idNumber;

char descr[100];

int avail;

} sparePartType;

sparePartType var1 = (123, “Wheel”, 1);

sparePartType var2;

var1.avail = 1;

strcpy(var2.descr, “Wheel”);

Το όνομα του Τύπου

Η κατασκευή του Τύπου

Δήλωση Τύπου Δομής

4-48

ΔΙΑΝΥΣΜΑΤΑ ΚΑΙ ΔΟΜΕΣ

• Οι δομές και τα διανύσματα μπορούν να συνδυασθούν χωρίς περιορισμούς π.χ.

typedef struct {

char firstName[10];

char lastName[10];

} personType;

struct student {

personType aPerson;

int id;

int age;

int sex;

} student1, student2;

Οπότε μπορούμε να γράψουμε

strcpy(student1.aPerson.firstName, “John”);

4-49

ΔΙΑΝΥΣΜΑΤΑ ΔΟΜΩΝ

• Προφανώς μπορούμε να έχουμε διανύσματα που τα στοιχεία τους είναι δομές !! Π.χ.

typedef struct {

char firstName[10];

char lastName[10];

} personType;

personType aDataBase[100];

Οπότε μπορούμε να γράψουμε

aDataBase[30].fisrtName[0] = ‘\0’ /* Άδεια συμβολοσειρά */

Διάνυσμα 100 ΔομώνΤύπου PersonType

4-50

Unions

• Οι τύποι union χρησιμοποιούνται για να ορίσουμε ένα block

μνήμης το οποίο μπορεί να προσπελασθεί από μεταβλητές

διαφορετικών τύπων

• Μοιάζει με τις δομές αλλά μπορούμε να χρησιμοποιήσουμε

μόνο ένα πεδίο κάθε φορά.

4-51

Ενώσεις (unions)

• Ο τύπος union

union number_tag {

int i;

double d;

};

union number_tag n;

d

in

n.d = 1.2;

printf("%lf\n", n.d);

n.i = 42;

printf("%d\n", n.i);

printf("%lf\n", n.d); /* wrong! */

4-52

Παράδειγμα

#include <stdio.h>

struct choice {

union { char *name; int age; };

int number;

};

int main() {

struct choice example;

char d[4];

printf("You can enter a name OR an age.\n");

printf("Would you like to enter a name? (Yes or No) : ");

gets(d);

if(d[0]=='y' || d[0]=='Y') {

printf("\nWhat's your name? ");

gets(example.name);

}

else {

printf("\nWhat's your age? ");

scanf("%d", &example.age);

}

printf("\nWhat's you favourite number? ");

scanf("%d", &example.number);

if(d[0]=='y' || d[0]=='Y') {

printf("\nYour name is %s ", example.name);

}

else {

printf("\nYour age is %d ", example.age);

}

printf("and your favourite number is %d.\n", example.number);

printf("The size of the struct is %d\n", sizeof(example));

return 0;

}