ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ( ΓΛΩΣΣΑ C ) ΠΙΝΑΚΕΣ (ARRAYS) Ανασκόπηση Διαχείριση πινάκων μέσω δεικτών (pointers) Συναρτήσεις και μονοδιάστατοι πίνακες Δισδιάστατοι πίνακες ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
1. Ανασκόπηση Ένα σύνολο συνεχόμενων θέσεων της μνήμης που χρησιμοποιούνται για την αποθήκευση μιας σειράς τιμών (συνήθως συσχετιζόμενων μεταξύ τους) Όλες οι τιμές των στοιχείων του πίνακα είναι του ίδιου τύπου δεδομένων Τα στοιχεία του πίνακα ξεκινούν από τη θέση με δείκτη 0 δηλαδή το στοιχείο με τιμή του δείκτη 0 είναι το πρώτο στοιχείο του πίνακα. Μεμονωμένες τιμές του πίνακα (με όνομα π.χ. array) μπορούν να προσπελαστούν μέσω μιας μεταβλητής τύπου int –αντιστοιχεί στον δείκτη του πίνακα (integer index): array[index] ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αριθμητικοί ΠΙΝΑΚΕΣ Δήλωση πίνακα Η πρώτη τιμή κάθε δείκτη είναι 0 Όνομα Μέγεθος Άμεσος καθορισμός μεγέθους Με χρήση σταθεράς (#define N 100) Τύπος στοιχείων Διάσταση Μονοδιάστατοι π.χ. w[25],v[m] Δισδιάστατοι κλπ π.χ. b[3][4], c[k][j] Η πρώτη τιμή κάθε δείκτη είναι 0 Η δήλωση a[3] περιλαμβάνει τα στοιχεία: a[0], a[1], a[2] ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αρχικοποίηση πίνακα Οι πίνακες μπορούν να αρχικοποιούνται με μια λίστα κατάλληλων τιμών. Δεν είναι απαραίτητος ο καθορισμός του πλήθους των στοιχείων σε μονοδιάστατους πίνακες. #include <stdio.h> void main() { int month; int table[12] = { 30, 40, 45, 95, 130, 220, 210, 185, 135, 80, 40, 45 }; printf("Enter month: "); scanf("%d", &month); } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αρχικοποίηση πίνακα Χρήση στοιχείων πίνακα χωρίς εκχώρηση αρχικής τιμής μεγέθους Χρήση δεικτών με τιμές εκτός των δηλωθέντων ορίων #include <stdio.h> int a[2]={11,22}; int b[]={77,88,99}; void main() { int i; for (i=0;i<=2;i++) printf("%4d ",a[i]); printf("\n"); for (i=0;i<=2;i++) printf("%4d ",b[i]); printf("\n\n DEIKTES EKTOS ORIWN\n"); for (i=0;i<=7;i++) printf("%6d ",a[i]); for (i=0;i<=8;i++) printf("%6d ",b[i]); } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Διαχείριση δείκτη (index) πίνακα Οι πίνακες έχουν σταθερό μέγεθος Δεν υπάρχει τρόπος (που να υποστηρίζεται αυτόματα από τη γλώσσα C) για τον έλεγχο αν ο δείκτης που χρησιμοποιούμε, για να διαχειριζόμαστε τα στοιχεία ενός πίνακα, είναι εντός των ορίων του πίνακα. Ο έλεγχος αυτός πρέπει να γίνεται από εμάς σε κάθε περίπτωση!!!! ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αποθήκευση στοιχείων πίνακα Τα στοιχεία ενός πίνακα αποθηκεύονται σε συνεχόμενες διευθύνσεις μνήμης, με το πρώτο στοιχείο να αποθηκεύεται στη χαμηλότερη διεύθυνση. Το είδος των στοιχείων του πίνακα (int, float, double, char) προσδιορίζει τις ακριβείς διευθύνσεις όλων των στοιχείων μετά από το πρώτο. Π.χ. int x[5] ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Ανάθεση τιμών στα στοιχεία πίνακα Χρήση της scanf Χρήση τυχαίων ή ψευδοτυχαίων αριθμών Συναρτήσεις: rand( ), srand( ) <stdlib.h>, <time.h> ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα - 1 #include <stdlib.h> #include <time.h> #include <stdio.h> void main() { int i, a[10]; srand((unsigned int)time(0)); for(i=0; i<10; i++) a[i]=rand()% 100; printf(“TEN RANDOM NUMBERS BETWEEN 0 AND 99\n\n"); for (i=0;i<10;i++) printf("%5d\n",a[i] ); } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα - 2 #include <stdio.h> #define RESPONSE_SIZE 40 /* define array sizes */ #define FREQUENCY_SIZE 11 /* function main begins program execution */ int main() { int answer; /* counter */ int rating; /* counter */ /* initialize frequency counters to 0 */ int frequency[ FREQUENCY_SIZE ] = { 0 }; /* place survey responses in array responses */ int responses[ RESPONSE_SIZE ] = { 1, 2, 6, 4, 8, 5, 9, 7, 8, 10, 1, 6, 3, 8, 6, 10, 3, 8, 2, 7, 6, 5, 7, 6, 8, 6, 7, 5, 6, 6, 5, 6, 7, 5, 6, 4, 8, 6, 8, 10 }; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
for ( answer = 0; answer < RESPONSE_SIZE; answer++ ) /* for each answer, select value of an element of array responses and use that value as subscript in array frequency to determine element to increment */ for ( answer = 0; answer < RESPONSE_SIZE; answer++ ) ++frequency[ responses [ answer ] ]; /* display results */ printf( "%s%17s\n", "Rating", "Frequency" ); /* output frequencies in tabular format */ for ( rating = 1; rating < FREQUENCY_SIZE; rating++ ) { printf( "%6d%17d\n", rating, frequency[ rating ] ); } /* end for */ return 0; /* indicates successful termination */ } /* end main */ ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα - 3 #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 7 int main() { int face; /* random number with value 1 - 6 */ int roll; /* roll counter */ int frequency[ SIZE ] = { 0 }; /* initialize array to 0 */ srand( time( NULL ) ); /* seed random-number generator */ /* roll die 6000 times */ for ( roll = 1; roll <= 6000; roll++ ) { face = rand() % 6 + 1; ++frequency[ face ]; } /* end for */ printf( "%s%17s\n", "Face", "Frequency" ); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
/* output frequency elements 1-6 in tabular format */ for ( face = 1; face < SIZE; face++ ) { printf( "%4d%17d\n", face, frequency[ face ] ); } /* end for */ return 0; /* indicates successful termination */ } /* end main */ ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
2. Διαχείριση πινάκων μέσω δεικτών (pointers) ΠΙΝΑΚΑΣ : Ένα σύνολο συνεχόμενων θέσεων της μνήμης που χρησιμοποιούνται για την αποθήκευση μιας σειράς τιμών (συνήθως συσχετιζόμενων μεταξύ τους). Δηλαδή τα στοιχεία ενός πίνακα αποθηκεύονται σε συνεχόμενες διευθύνσεις μνήμης, με το πρώτο στοιχείο να αποθηκεύεται στη χαμηλότερη διεύθυνση. Το είδος των στοιχείων του πίνακα (int, float, double, char) προσδιορίζει τις ακριβείς διευθύνσεις όλων των στοιχείων μετά από το πρώτο. Το όνομα του πίνακα είναι ένας δείκτης (pointer) στο πρώτο στοιχείο του πίνακα ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
int ia[6]; 1 2 3 4 5 ia ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
int ia[6]; 1 2 3 4 5 42 ia ia[4] = 42; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παραδείγματα int x[5] x==1000 (σύγκριση) &x[0]==1000 (σύγκριση) Οι παρακάτω σχέσεις είναι σωστές ; x==1000 (σύγκριση) &x[0]==1000 (σύγκριση) &x[1]=1002 (ανάθεση) Μπορεί να χρησιμοποιηθεί δείκτης για την προσπέλαση των στοιχείων του πίνακα; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αριθμητική δεικτών int i; int ia[MAX]; for(i = 0; i< MAX; i++) ia[i] = 0; int *ip; int ia[MAX]; for(ip = ia; ip < ia + MAX; ip++) *ip = 0; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Εύρεση μέγιστου – ελάχιστου με χρήση δεικτών ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Pointers και Πίνακες Το όνομα ενός πίνακα χωρίς [ ] είναι ένας δείκτης στο πρώτο στοιχείο του πίνακα π.χ. int a[100], *pa; …… pa =a; Η μεταβλητή δείκτης pa αρχικοποιείται με τη διεύθυνση του πρώτου στοιχείου του πίνακα a[ ] a είναι η διεύθυνση του πρώτου ακέραιου στοιχείου του πίνακα Οι εκφράσεις *a και a[0] είναι ακριβώς ίδιες ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
ΠΙΝΑΚΕΣ και ΔΕΙΚΤΕΣ Το όνομα ενός πίνακα είναι δείκτης στο πρώτο στοιχείο του πίνακα. #include <stdio.h> int arr[4] = {0,10,20,30}; int main() { printf( "\nAddress and value of array elements:\n"); for( int i = 0; i < 4; i++ ) printf("Address: %u",(arr+i)); // &arr[i] printf(" Value: %d\n" ,*(arr+i)); // arr[i] } return 0; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> int main(void) { int a[ ]={1,2,3,5,7,11,13,17,19}; int *p; printf("a[4] = %d\n", a[4]); printf("the address of the array = %p\n", &a); printf("the address of element nr. 0 of the array = %p\n", &a[0]); printf("the address of element nr. 4 of the array = %p\n", &a[4]); p = a; printf("the value of the pointer = %p\n", p); printf("the value the pointer points at = %d\n", *p); p += 4; printf("the value of the pointer now = %p\n", p); printf("the value the pointer now points at = %d\n", *p); return 0; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα // Incrementing a pointer to an array of integers #include <stdio.h> int main(void) { long multiple[] = {15L, 25L, 35L, 45L}; long *p = multiple; for(int i = 0; i < sizeof(multiple)/sizeof(multiple[0]); ++i) printf("address p+%d (&multiple[%d]): %llu *(p+%d) value: %d\n", i, i, (unsigned long long)(p+i), i, *(p+i)); printf("\n Type long occupies: %d bytes\n", (int)sizeof(long)); return 0; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ-ΓΛΩΣΣΑ C / 02
Ανάθεση τιμών στα στοιχεία πίνακα: Ανάγνωση δεδομένων από αρχείο Χρησιμοποιείται όταν Τα δεδομένα είναι πολλά Αποτελούν τιμές μετρήσεων Απαιτείται εκσφαλμάτωση (debugging) του προγράμματος Απαιτείται έλεγχος του προγράμματος με μεγάλο πλήθος δεδομένων ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
3. Συναρτήσεις και μονοδιάστατοι πίνακες Μεταβίβαση στοιχείων πίνακα Μεταβίβαση ολόκληρου του πίνακα με ή χωρίς περιορισμούς ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Πίνακες ως παράμετροι σε συναρτήσεις Ο πίνακας μεταβιβάζεται Ως ένας πίνακας χωρίς ορισμένο μέγεθος π.χ.int array[] ΕΙΤΕ Ως δείκτης (pointer) π.χ. int *array Οι αλλαγές στον πίνακα που γίνονται μέσα στη συνάρτηση επηρεάζουν άμεσα τον «πραγματικό» πίνακα. ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα - 1 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα - 2 #include <stdlib.h> #include <time.h> #include <stdio.h> /***********************/ /* Function Prototypes */ int RollOne( void ); void PrintRolls( int rolls[] ); void PrintX( int howMany ); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
srand((unsigned int)time(0)); for ( i=0; i<=12; i++ ) int main( void ) { int rolls[ 13 ], twoDice, i; srand((unsigned int)time(0)); for ( i=0; i<=12; i++ ) rolls[ i ] = 0; for ( i=1; i <= 1000; i++ ) twoDice = RollOne() + RollOne(); ++ rolls[ twoDice ]; } PrintRolls( rolls ); return 0; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
void PrintRolls( int rolls[] ) int i; for ( i=2; i<=12; i++ ) int RollOne( void ) { return (rand() % 6) + 1; } void PrintRolls( int rolls[] ) int i; for ( i=2; i<=12; i++ ) printf( “%2d (%3d): “, i, rolls[ i ] ); PrintX( rolls[ i ] / 10 ); printf( “\n” ); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
void PrintX( int howMany ) { int i; for ( i=1; i<=howMany; i++ ) printf( “x” ); } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα – 3 Να γραφεί μια συνάρτηση που βρίσκει το άθροισμα 5 ακεραίων αριθμών που εισάγονται με εντολές scanf στο κυρίως πρόγραμμα (συνάρτηση main() ). Εναλλακτικά οι αριθμοί μπορούν να δημιουργηθούν χρησιμοποιώντας τις συναρτήσεις rand() και srand(). ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
1η λύση #include <stdio.h> int addNumbers(int fiveNumbers[]); /* declare function */ int main() { int array[5]; int i; printf("Enter 5 integers separated by spaces: "); for(i=0 ; i<5 ; i++) { scanf("%d", &array[i]); } printf("\nTheir sum is: %d\n", addNumbers(array)); return 0; } int addNumbers(int fiveNumbers[]) { /* define function */ int i, sum = 0; for(i=0 ; i<5 ; i++) { sum+=fiveNumbers[i]; /* work out the total */ } return sum; /* return the total */ ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
2η λύση #include <stdio.h> int addNumbers(int *fiveNumbers); /* declare function */ int main() { int array[5]; int i; printf("Enter 5 integers separated by spaces: "); for(i=0 ; i<5 ; i++) { scanf("%d", &array[i]); } printf("\nTheir sum is: %d\n", addNumbers(array)); return 0; } int addNumbers(int *fiveNumbers) { /* define function */ int i, sum = 0; for(i=0 ; i<5 ; i++) { sum+=fiveNumbers[i]; /* work out the total */ } return sum; /* return the total */ ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
3η λύση #include <stdio.h> #define max 5 int addNumbers(int fiveNumbers[], int n); /* declare function */ int main() { int array[max]; int i; printf("Enter %3d integers separated by spaces \n ",max); for(i=0 ; i<max ; i++) { scanf("%d", &array[i]); } printf("\nTheir sum is: %d\n", addNumbers(array,max)); return 0; } int addNumbers(int fiveNumbers[], int n) { /* define function */ int i, sum = 0; for(i=0 ; i<n ; i++) { sum+=fiveNumbers[i]; /* work out the total */ } return sum; /* return the total */ } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
4η λύση #include <stdio.h> #define max 5 void addNumbers(int fiveNumbers[], int n, int *sum); /* declare function */ int main() { int array[max],i,s; printf("Enter %3d integers separated by spaces \n ",max); for(i=0 ; i<max ; i++) scanf("%d", &array[i]); addNumbers(array,max,&s); printf("\nTheir sum is: %d\n",s ); return 0; } void addNumbers(int fiveNumbers[], int n, int *sum) { /* define function */ int i; *sum=0; for (i=0 ; i<n ; i++) { *sum+=fiveNumbers[i]; /* work out the total */ } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
4. Δισδιάστατοι πίνακες στήλες 1 2 3 γραμμές 1 2 3 γραμμές ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Δήλωση πίνακα 2 διαστάσεων int ia[3][4]; Number of Columns Number of Rows Address Type ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Δήλωση και αρχικοποίηση (1) int grades[100][6]; /* 6 grades per student */ float rainfall[12][31]; /* daily rain for one year */ double table[100][200]; int students[][2] = {{201,75}, {202,90}, {203,77}}; int cube[][3][2] = { {{4,5}, {6,7}, {3,0}}, {{5,5}, {2,1}, {7,4}}, {{2,8}, {1,1}, {4,8}} }; ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Δήλωση και αρχικοποίηση (2) int temp[4][3] = {50, 70, 60, 48, 75, 62, 51, 69, 60, 52, 78, 63}; int temp[4][3] = {{50, 70, 60}, {48, 75, 62}, {51, 69, 60}, {52, 78, 63}}; int t2[7][4] = {{50, 70, 60}, {48, 75, 62}, {51, 69, 60}, {52, 78, 63}}; int temp[][3] = {{50, 70, 60}, {48, 75, 62}, {51, 69, 60}, {52, 78, 63}}; int temp[][3] = {50, 70, 60, 48, 75, 62, 51, 69, 60, 52, 78, 63};
Αρχικοποίηση πίνακα 2-διαστάσεων #define X_SIZE 60 #define Y_SIZE 30 /* A random matrix */ int matrix[X_SIZE][Y_SIZE]; void init_matrix(void) { int x,y; /* current element to zero */ for (x = 0; x < X_SIZE; ++x) { for (y = 0; y < Y_SIZE; ++y) { matrix[x][y] = -1; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
int matrix[X_SIZE][Y_SIZE]; void init_matrix(void) { #define X_SIZE 60 #define Y_SIZE 30 int matrix[X_SIZE][Y_SIZE]; void init_matrix(void) { int index; /* element counter */ int *matrix_ptr; matrix_ptr = &matrix[0][0]; for (index = 0; index < X_SIZE * Y_SIZE; ++index) *matrix_ptr = -1; ++matrix_ptr; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
int matrix[X_SIZE][Y_SIZE]; void init_matrix(void) { int *matrix_ptr; #define X_SIZE 60 #define Y_SIZE 30 int matrix[X_SIZE][Y_SIZE]; void init_matrix(void) { int *matrix_ptr; for (matrix_ptr = &matrix[0][0]; matrix_ptr <= &matrix[X_SIZE-1][Y_SIZE-1]; ++matrix_ptr) *matrix_ptr = -1; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Τρόπος αποθήκευσης 1 2 3 Column 0 Column 1 Column 2 Column 3 1 2 3 Τρόπος αποθήκευσης 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 Column 0 Column 1 Column 2 Column 3 Column Major Order 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 Row 0 Row 2 Row 1 Row Major Order ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Πλεονεκτήματα ia[1] ia[1][2] Η χρήση της Row Major Order επιτρέπει τη χρήση ενός δισδιάστατου πίνακα ως πίνακα πινάκων ia[1] ia[1][2] 0,0 0,1 0,2 0,3 1,0 1,1 1,2 1,3 2,0 2,1 2,2 2,3 1,2 0,0 0,1 0,2 0,3 1,0 1,1 1,3 2,0 2,1 2,2 2,3 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Οργάνωση ενός πίνακα 3Χ5 στη μνήμη ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα υπολογισμών μεγεθών σε πίνακα #include <stdio.h> #include <stdlib.h> int a[5][7]; void main() { printf("sizeof a = %d\n", sizeof a); printf("sizeof a[3] = %d\n", sizeof a[3]); printf("sizeof a[3][4] = %d\n", sizeof a[3][4]); } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Αποτελέσματα sizeof a = 140 sizeof a[3] = 28 sizeof a[3][4] = 4 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Παράδειγμα : Grading Multiple-Choice Test Write a program that grades multiple-choice test.
Παράδειγμα : ένας πίνακας ακεραίων (int) 4X3, έστω mat[4][3] : Ένας δισδιάστατος πίνακας (2D) στη γλώσσα C θεωρείται ως ένας μονοδιάστατος πίνακας (1D) τα στοιχεία του οποίου είναι μονοδιάστατοι πίνακες (1D). Παράδειγμα : ένας πίνακας ακεραίων (int) 4X3, έστω mat[4][3] : ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
mat= mat[0] mat[1] mat[2] mat[3] mat0,0 mat0,1 mat0,2 mat1,0 mat1,1 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Σύγκριση One Dimensional Array int ia[6]; Address of beginning of array: ia &ia[0] Two Dimensional Array int ia[3][6]; Address of beginning of array: ia &ia[0][0] also Address of row 0: ia[0] &ia[0][0] Address of row 1: ia[1] &ia[1][0] Address of row 2: ia[2] &ia[2][0] ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Τα στοιχεία διατάσσονται στη μνήμη ανά σειρά, έτσι η εξίσωση του πίνακα mat[m][n] , τύπου int, για το στοιχείο i,j είναι : address(mat[i][j]) = address(mat[0][0]) + (i * n + j) * size(int) address(mat[i][j])=address(mat[0][0]) + i*n*size(int) + j * size(int) address(mat[i][j])=address(mat[0][0])+i*size(row of int) + j*size(int) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> void main() { int i, j; int big[8][8], large[25][12]; for (i = 0 ; i < 8 ; i++) for (j = 0 ; j < 8 ; j++) big[i][j] = i * j; /* This is a multiplication table */ for (i = 0 ; i < 25 ; i++) for (j = 0 ; j < 12 ; j++) large[i][j] = i + j; /* This is an addition table */ big[2][6] = large[24][10] * 22; big[2][2] = 5; big[big[2][2]][big[2][2]] = 177; /* this is big[5][5] = 177; */ printf("%5d ", big[i][j]); printf("\n"); /* newline for each increase in i */ } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Δείκτες και πίνακες 2 διαστάσεων Έστω η δήλωση : int multi[5][10] και έστω ότι το υπογραμμισμένο τμήμα είναι το όνομα του πίνακα. Έτσι όμως έχουμε ένα πίνακα 10 ακεραίων στοιχείων. Επειδή όμως το όνομα multi[5] είναι επίσης πίνακας 5 στοιχείων το καθένα από τα οποία είναι πίνακας 10 ακεραίων έχουμε τελικά ένα πίνακα από 5 πίνακες των 10 θέσεων (ακεραίων). Ας γεμίσουμε τα στοιχεία του πίνακα : ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
{ multi[i][k]=n; n++; } n=0; for (i=0;i<5;i++) for (k=0;k<10;k++) { multi[i][k]=n; n++; } multi[0]= 1 2 3 4 5 6 7 8 9 multi[1]= 10 11 12 13 14 15 16 17 18 19 multi[2]= 20 21 22 23 24 25 26 27 28 29 multi[3]= 30 31 32 33 34 35 36 37 38 39 multi[4]= 40 41 42 43 44 45 46 47 48 49 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
&multi[3][0] ή *(multi+3) Τα στοιχεία κάθε πίνακα αποθηκεύονται σε συνεχόμενες θέσεις στην κεντρική μνήμη. Ο compiler διερμηνεύει το multi+1 ως διεύθυνση του 10 στην 2η σειρά. Δηλαδή προσθέτει το 10 (η 2η διάσταση του πίνακα) στον αριθμό των στηλών για να βρει τη θέση που δείχνει ο multi+1, δηλαδή υλοποιεί τη σχέση 10*sizeof(int). Ποια θα είναι η διεύθυνση του στοιχείου με τιμή 30 στην 4η σειρά; &multi[3][0] ή *(multi+3) Ποια θα είναι η διεύθυνση του στοιχείου με τιμή 31 στην 4η σειρά; *(*(multi+3)+1) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Οι εκφράσεις : Έστω multi[row][col] και *(*(multi+row)+col) Δίνουν τα ίδια ακριβώς αποτελέσματα Έστω #define ROWS 5 #define COLS 10 Η απόσταση μεταξύ των multi+row και multi+row+1 είναι COLS*sizeof(int) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> int main() { int list[][3] = { 1, 1, 1, 2, 2, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343}; printf("The size of list[][3] is %d bytes.\n", sizeof(list)); return 0; } ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> #define ROWS 5 #define COLS 10 void set_value(int m_array[][COLS]) { int row,col; for (row=0;row<ROWS;row++) for (col=0;col<COLS;col++) m_array[row][col]=1; } int multi[ROWS][COLS],i,j; void main() set_value(multi); for (i=0;i<ROWS;i++) printf("multi[%1d]= ",i); for (j=0;j<COLS;j++) printf("%3d ",multi[i][j]); printf("\n"); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> #define ROWS 5 #define COLS 10 int multi[ROWS][COLS]; int main(void) { int row, col; for (row = 0; row < ROWS; row++) for (col = 0; col < COLS; col++) multi[row][col] = row*col; printf("\n%4d ",multi[row][col]); printf("%4d ",*(*(multi + row) + col)); } return 0; 2darr-04.cpp ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
#include <stdio.h> void printArray(int array[][4]); /* declare function */ int main() { int array[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; printArray(array); return 0; } void printArray(int array[][4]) { /* define function */ int i, j; for(i=0 ; i<3 ; i++) { for(j=0 ; j<4 ; j++) printf("%2d ", array[i][j]); printf("\n"); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Βρείτε τι θα εμφανιστεί από την εκτέλεση του παρακάτω προγράμματος #include <stdio.h> int array[3][2] /* Array of numbers */ int main() { int x,y;/* Loop indicies */ array[0][0] = 0 * 10 + 0; array[0][1] = 0 * 10 + 1; array[1][0] = 1 * 10 + 0; array[1][1] = 1 * 10 + 1; array[2][0] = 2 * 10 + 0; array[2][1] = 2 * 10 + 1; printf("array[%d] ", 0); printf("%d ", array[0,0]); printf("%d ", array[0,1]); printf("\n"); printf("array[%d] ", 1); printf("%d ", array[1,0]); printf("%d ", array[1,1]); printf("array[%d] ", 2); printf("%d ", array[2,0]); printf("%d ", array[2,1]); return (0); ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Πίνακες πολλών διαστάσεων int a[10][3][2]; “ένας πίνακας με δέκα πίνακες με τρεις πίνακες που περιέχει ο καθένας τους 2 ακεραίους” Στη μνήμη 3 3 3 ... 2 2 2 2 2 2 2 2 2 10 ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
void examine( a[][3][2] ) { … } Η μεταβίβαση ενός πολυδιάστατου πίνακα ως όρισμα απαιτεί όλες τις διαστάσεις εκτός από την πρώτη int a[10][3][2]; void examine( a[][3][2] ) { … } Η διεύθυνση για την πρόσβαση στο στοιχείο a[i][j][k] είναι : a+k+2*(j+3*i) ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Χρήση πινάκων δεικτών για πολυδιάστατους πίνακες μεταβλητού μεγέθους. Απαιτείται η εκχώρηση θέσεων μνήμης και η αρχικοποίηση των πινάκων δεικτών. int ***a; a[3][5][4] αναλύεται ως *(*(*(a+3)+5)+4) int ***a Η τιμή int ** int * int ΔΠΘ- ΜΠΔ: ΔΟΜΗΜΕΝΟΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ / 03
Matrix Addition Algorithm Add two n x m matrices A, B; for each row i of A do for each column j of A do C[i][j] = A[i][j] + B[i][j]; Output matrices A, B and C.
matrixAdd2.cpp ... void main() { // Note: A, B and C have the same dimensions double A[NUM_ROWS][NUM_COLS] = { {3, 3}, {1, 1}, {2, 0} }; double B[NUM_ROWS][NUM_COLS] = { {3, 0}, {3, 0}, {0, 1} }; double C[NUM_ROWS][NUM_COLS]; add(A, B, C); printf("A = \n“); display(A); printf("B = \n“); display(B); printf("C = \n“); display(C); } What does this output?
matrixAdd2.cpp ... // GLOBAL CONSTANTS #define NUM_ROWS 3; // number of matrix rows #define NUM_COLS 2; // number of matrix columns // Function prototypes void add(const double M1[NUM_ROWS][NUM_COLS], const double M2[NUM_ROWS][NUM_COLS], double M3[NUM_ROWS][NUM_COLS]); void display(const double M[NUM_ROWS][NUM_COLS]); void main() { // Note: A, B and C have the same dimensions // Matrices double A[NUM_ROWS][NUM_COLS] = { {3, 3}, {1, 1}, {2, 0} }; double B[NUM_ROWS][NUM_COLS] = { {3, 0}, {3, 0}, {0, 1} }; double C[NUM_ROWS][NUM_COLS]; What does this output?
Function add() // Add two matrices // M1[][] = First matrix // M2[][] = Second matrix // M3[][] = M1[][] + M2[][] // Note: M1, M2 and M3 must have the same dimensions void add(const double M1[NUM_ROWS][NUM_COLS], const double M2[NUM_ROWS][NUM_COLS], double M3[NUM_ROWS][NUM_COLS]) { // M3 = M1 + M2 for (int i=0; i < NUM_ROWS; i++) for (int j=0; j<NUM_COLS; j++) M3[i][j] = M1[i][j] + M2[i][j]; } What does this output?
Function display() // Output matrix // M[][] = Matrix void display(const double M[NUM_ROWS][NUM_COLS]) { for (int i=0; i < NUM_ROWS; i++) for (int j=0; j < NUM_COLS; j++) printf(M[i][j]); //!! Format printf !!! } printf(“\n”); What does this output?
Άσκηση : Distance Matrix Algorithm Compute a matrix D storing distances to a point (x,y); Input: x, y for each row i of D do for each column j of D do D[i][j] = distance from (x,y) to (i,j) Output matrix D.
distanceMatrix.cpp for (int i=0; i<N_ROWS; i++) { ... // dimensions of distance matrix #define N_ROWS 8; #define N_COLS 12; double A[N_ROWS][N_COLS]; double x=0.0, y=0.0; printf("Enter (x,y) coordinates of center: “); scanf(“%lf %lf”, x, y); for (int i=0; i<N_ROWS; i++) { for (int j=0; j<N_COLS; j++) double dx = j-x; // Note: x represents columns double dy = i-y; // Note: y represents rows double dist = sqrt(dx*dx+dy*dy); A[i][j] = dist; } What does this output?
Common Programming Errors Addressing indices that are out of bounds of the array range. This will run-time crash or at the very least a logical error. Be careful especially when using expressions to compute the indices. Remember, indexing starts with 0, not 1!!! Forgetting to declare the array (either altogether or forgetting the []) Assuming the array is initialized (to zero.)