SlideShare a Scribd company logo
1 of 37
Download to read offline
Παιγνίδια με
Πίνακες και Δείκτες
Δομημένος Προγραμματισμός
Τσαγκατάκης Ιωάννης
2
Πως λύνουμε ένα πρόβλημα ;
Σχεδιασμός
Αλγορίθμου
Κώδικας
(υλοποίηση)
Profit !
3
Test Driven Development
●
Σπάω το πρόβλημα σε
μικρότερα και απλούστερα
●
Βεβαιώνομε πως κάθε τι
είναι σωστό
●
Ο αλγόριθμος προκύπτει
●
Προκύπτει κώδικας
εύκολος στην κατανόηση
και την αλλαγή
4
Μια λύση της Εργασίας
●
Με μοντέρνα C
– Χρησιμοποιώντας πράγματα που ίσως δεν ξέρετε
– Άρα δεν είναι αυτό που θα έπρεπε να παραδώσετε
●
Με χρήση μικρών συναρτήσεων
●
Μια καλή επανάληψη
5
Ο λογικός τύπος bool
// Old C
typedef int bool;
#define true 1
#define false 0
// C99
#include <stdbool.h>
6
Μεταβλητές και δείκτες
Όνομα Τύπος Μέγεθος Διεύθυνση
Μνήμης
Τιμή
var int sizeof(int)
4
0x7FF..02C 42
pVar int * sizeof(int*)
8
0X7FF..030 0x7FF..02C
int main() {
int var = 42;
int *pVar = &var;
assert(*pVar == 42);
}
Symbol Table
● Η τιμή μιας μεταβλητής: var, pVar
● Η διεύθυνση μνήμης : &var, &pVar
● Η τιμή, που δείχνει ένας δείκτης: *pVar
● Όλοι οι δείκτες πιάνουν το ίδιο χώρο στη μνήμη
sizeof(int *) == sizeof(void *)
Ένας δείκτης σε δείκτη που
δείχνει στην μνήμη της var
όπου ή var έχει την τιμή 42
H εικόνα φτιάχτηκε με την βοήθεια του ddd (GNU data display debugger)
7
Η αναπαράσταση ενός πίνακα
●
Ένας πίνακας έχει
– Ένα μέγιστο μήκος Ν
– Ένα μέγεθος
– Τιμές
●
Αν ξέραμε δομές
#define TRUE 1
#define FALSE 0
const int N = 10;
int main() {
int a[N];
int aSize = 0;
for(int i=0; i<aSize; i++) a[i]=-99;
fillArray_partial(a, &aSize);
assert(aSize <= N);
printf("%4s", "A:");
printArray(a, aSize);
printf(" (size=%d)n", aSize);
return 0;
}
struct partialArray {
int *arr;
int size;
int maxSize;
};
8
Ο Πίνακας στην μνήμη
●
Σύνολο στοιχείων: 10 / 20, size == 10
●
Βασική συνθήκη (αναλλοίωτο): (size <= maxSize) && (size >= 0) size <= maxSize) && (size <= maxSize) && (size >= 0) size >= 0)
●
Πρώτη τιμή : array[0]
●
Τελευταία τιμή : array[size-1]
●
Δεν “υπάρχει” το : array[size] !
●
Συνολικό μέγεθος σε bytes: maxSize * sizeof(size <= maxSize) && (size >= 0) int)
876543210 9
maxSize = 20
size
Κάπου στην στοίβα ο πίνακας int array[maxSize]
assert(a == &a[0]);
a[4] = 42;
assert(a[4] == *(a + 4));
assert(&a[4] == a+4);
*(a+4) = 24;
assert(a[4]==24);
sizeof(int)
1 2 4 5 42 9 10 12 13 22 ?? ??
To index 4, η τιμή 42
Η διεύθυνση μνήμης
(size <= maxSize) && (size >= 0) a+4) ή &a[4]
9
Μια πρώτη συνάρτηση
●
Μικρές συναρτήσεις κάνουν τον κώδικα μας καλύτερο
int getRandom() {
const int maxValue = 12;
int random_value = rand() % (maxValue + 1);
return random_value;
}
Τύπος εξόδου
ή void
Κενή είσοδος
Τιμή Επιστροφής
10
Μια συνάρτηση με είσοδο
●
Πριν η C χρησιμοποιήσει μια συνάρτηση θα πρέπει να ξέρει την “υπογραφή” της σε μια δήλωση (declaration).
– Το όνομα της
– Τον τύπο δεδομένων των εισόδων της (αν υπάρχουν)
– Τον τύπο δεδομένων της μιας μοναδικής εξόδου ή τίποτα (void)
●
Ο κώδικας της συνάρτησης υπάρχει στον ορισμό της (definition).
●
Τα Header Files περιέχουν τα declarations των συναρτήσεων που χρησιμοποιούμε.
– Τα ενσωματώνουμε με την εντολή #include include του προ-επεξεργαστή
#include <stdlib.h>
int getRandomMax(int maxValue);
int getRandomMax(int maxValue) {
maxValue++;
int random_value = rand() % maxValue ;
return random_value;
}
Declaration
Definition
Είσοδος με τιμή
Θα περάσει αντίγραφο της
τιμής στην στοίβα.
Τοπική αλλαγή !
11
Τυχαίοι αριθμοί (κλειστό διάστημα)
#include <stdlib.h>
int getRandom() {
// Values at closed [min,max]
const int minValue = 10;
const int maxValue = 19;
// range = 10
int range = maxValue - minValue + 1;
// From 0 ... 9
int random_value = rand() % range ;
int result = random_value + minValue;
return result;
}
12
Πίνακες, δείκτες και συναρτήσεις
●
Στενή σχέση μεταξύ πίνακα και δείκτη
●
Κατάρρευση τύπου από πίνακα σε δείκτη.
●
Οι πίνακες περνάνε σαν αναφορά και όχι σαν
αντίγραφο των στοιχείων τους.
– Μικρή χρήση μνήμης
– Αλλά μπορεί ο πίνακας να αλλάξει
●
Ακόμα και αν δεν θέλουμε
– H C99 υποστηρίζει const
void printArray(int const* arr, int size)
●
Ο τύπος που δείχνει ένας δείκτης είναι
σημαντικός για την αριθμητική των δεικτών.
●
Δεν ξέρω πόσο μεγάλος είναι ο πίνακας!
– Περνάω το size σαν τιμή ή δείκτη (αναφορά).
void printArray(int* arr, int size) {
for (int pos = 0; pos < size; pos++) {
char* comma = ( (pos == (size – 1) ) ? "" : ",");
printf("%2d%s", arr[pos], comma);
}
}
Πέρασμα πίνακα σαν
διεύθυνση μνήμης
(δείκτης)
Χρήση δείκτη
σαν να είναι
πίνακας
Τριαδικός τελεστής
Περιττές παρενθέσεις ;
13
14
Περιττές παρενθέσεις;
comma = pos == size - 1 ? "" : ", ";
●
Θα κάνει αυτό που πρέπει να κάνει
Εκτός βέβαια αν δεν το κάνει
●
Βάζουμε παρενθέσεις
●
Για τεκμηρίωση
●
Για σιγουριά
●
Αλλά συνήθως θα κάνει αυτό που πρέπει να κάνει
●
C idioms από βιβλία
15
Κόλπο: Διαβάζοντας δηλώσεις
Από τα δεξιά προς τα αριστερά!
const int *pci;
Είναι ακριβώς το ίδιο
const int *p;
const int* p;
int const *p;
int * const p;
The p is a constant pointer to an int
16
17
Πέρασμα τιμής με αναφορά
●
Οι μικρές συναρτήσεις κάνουν τον αλγόριθμο ευανάγνωστο
void fillArray_partial(int* a, int* aLoc) {
for (int pos = 0; pos < N; pos++) {
int newValue, isValueExist;
newValue = getRandom();
isValueExist = findInArray(a, *aLoc, newValue);
if (isValueExist == FALSE) {
insertValue(a, aLoc, newValue);
}
}
}
fillArray_partial(a, &aSize);
Δίνω την διεύθυνση μνήμης μου
Η τιμή μου μπορεί να αλλάξει
Η τιμή (*aLoc) που έχει
η διεύθυνση μνήμης
που δείχνει o δείκτης aLoc
Χρήση
ᅠΠέρασμα σαν διεύθυνση μνήμης
ώστε η τιμή να μπορεί να αλλάξει
18
Πέρασμα τιμών σε συναρτήσεις
●
Σαν τιμή
– Θα δημιουργηθεί ένα αντίγραφο της τιμής στην στοίβα
– Δεν βολεύει όταν τα δεδομένα είναι μεγάλα σε χώρο μνήμης
●
Σαν αναφορά μνήμης
– Θα περάσει η διεύθυνση της μνήμης σαν ένας δείκτης (*var)
– Οι δείκτης αυτός μπορεί να είναι κενός (size <= maxSize) && (size >= 0) NULL)
– Η συνάρτηση μπορεί να αλλάξει την τιμή (πχ scanf)
– Εκτός αν ο δείκτης δηλωθεί σαν const (C99)
– Στην C++ μια τιμή μπορεί να περάσει και σαν reference (&var)
●
Όταν λέμε πέρασμα με αναφορά εννοούμε είτε pointers είτε αυτό
●
Οι περισσότερες γνωστές γλώσσες προγραμματισμού περνάνε τιμές μόνο με αναφορά
19
Βρόχοι
void fillArray_full(int* a, int* aLoc) {
for (int pos = 0; pos < N; pos++) {
int newValue, isValueExist;
// Get unique Value
do {
newValue = getRandom();
isValueExist = findInArray(a, *aLoc, newValue);
} while (isValueExist == TRUE);
insertValue(a, aLoc, newValue);
}
}
Σπάζοντας τον κώδικα σε συναρτήσεις οι
αλλαγές είναι εύκολες
Τα ονόματα των μεταβλητών λένε ιστορίες
Θα τρέξω
τουλάχιστον
μια φορά
20
Βροχοι: break and continue
21
Συναρτήσεις: Επιστρέφοντας τιμές
// Find if a value exist on Array
int findInArray(const int a[], int size, int value) {
int found = FALSE;
for (int sPos = 0; sPos < size; sPos++) {
if (a[sPos] == value) {
found = TRUE;
break;
}
}
return found;
}
for (int sPos = 0; sPos < size; sPos++) {
if (a[sPos] == value) {
return true;
}
}
return false;
Εναλλακτική υλοποίηση
Πολλαπλά σημεία εξόδου
22
Ας διαχωρίσουμε αρμοδιότητες
●
Μια συνάρτηση πρέπει να
κάνει ένα πράγμα μόνο
●
Μια συνάρτηση να παράγει
πολλαπλές τιμές
●
Μια να τις εισάγει στον πίνακα.
●
Θέλω η insert να
– Βάζει την τιμή στην σωστή θέση
– Αν η τιμή δεν υπάρχει
– Η πιθανά κάποιο άλλο κριτήριο
που μπορεί να προκύψει στο
μέλλον
void fillArray_simple(int* a, int* aLoc) {
for (int pos = 0; pos < N; pos++) {
int newValue = getRandom();
insertValue(a, aLoc, newValue);
}
}
void insertValue(int* a, int* aLoc, int value) {
a[*aLoc] = value;
*aLoc = *aLoc + 1;
}
fillArray_simple(a, &aSize);
printArray(a, aSize);
printf(" (size=%d)n", aSize);
23
Μια πρώτη προσπάθεια
Τα assert σώζουν ζωές !
void insertValue(int* a, int* aLoc, int value) {
assert(*aLoc < N);
if( findInArray(a, *aLoc, value) == FALSE) {
a[*aLoc] = value;
*aLoc = *aLoc + 1;
}
assert(*aLoc <= N);
}
Η θέση είναι λάθος
Αρκεί να μπει στην
σωστή θέση
Προϋπόθεση συμβολαίου (pre condition)
Αναλλοίωτο
Post Condition
24
Και τέλος η insertValue
void insertValue(int value, int* array, int* size) {
// assert(*size < N);
bool exists = isValueExist(value, array, *size);
if (exists == false) {
int pos = findPosInArray(value, array, *size);
if (pos != *size) {
// Make space
for(int i=*size; i>pos; i--) {
array[i]=array[i-1];
}
}
array[pos]=value;
*size = *size + 1;
}
// assert(*size <= N);
}
25
Και τέλος η insertValue
void insertValue(int value, int* array, int* size) {
// assert(*size < N);
bool exists = isValueExist(value, array, *size);
if (exists == false) {
int pos = findPosInArray(value, array, *size);
if (pos != *size) {
// Make space
for(int i=*size; i>pos; i--) {
array[i]=array[i-1];
}
}
array[pos]=value;
*size = *size + 1;
}
// assert(*size <= N);
}
Έχει νόημα να γίνει
μια χωριστή συνάρτηση
arrayShiftRightAt(..)
Πέρασμα του πίνακα 2 φορές;
26
Παίρνοντας και την θέση εισαγωγής
●
Προσοχή στις τιμές
των φρουρών
●
Υπάρχουν πολλοί
άλλοι τρόποι να
δηλώσεις αποτυχία
#include <limits.h>
const int guard1 = -9999999;
const int guard = INT_MIN;
// Return the position of a value in an array
int findPosInArray(int value, const int* a, int size) {
for (int sPos = 0; sPos < size; sPos++) {
if (a[sPos] == value) {
return sPos;
}
}
return guard;
}
Άσκηση για το σπίτι
Υλοποιήστε αυτή την λύση κάνοντας
τις απαραίτητες τροποποιήσεις
27
Ο αλγόριθμος βήμα βήμα
Insert value: 13 at position 0, that is the end of array
-> 13 (size=1)
Insert value: 16 at position 1, that is the end of array
-> 13, 16 (size=2)
Insert value: 17 at position 2, that is the end of array
-> 13, 16, 17 (size=3)
Insert value: 15 at position 1, making space
-> 13, 15, 16, 17 (size=4)
Insert value: 13, value already exists skipping.
Insert value: 15, value already exists skipping.
Insert value: 16, value already exists skipping.
Insert value: 12 at position 0, making space
-> 12, 13, 15, 16, 17 (size=5)
Insert value: 19 at position 5, that is the end of array
-> 12, 13, 15, 16, 17, 19 (size=6)
Insert value: 11 at position 0, making space
-> 11, 12, 13, 15, 16, 17, 19 (size=7)
A: 11, 12, 13, 15, 16, 17, 19 (size=7)
13
16
17
13
16
17
17
13
16
16
17
13
15
16
17
115
size=3
size=4
28
Συνδέοντας τους πίνακες
●
Έκπληξη!! το merge έχει ήδη φτιαχτεί !!!
int a[N], b[N], c[N+N];
int aSize = 0, bSize=0, cSize=0;
fillArray(a, &aSize); fillArray(b, &bSize);
for(int i=0; i<aSize; i++) {
insertValue(a[i], c, &cSize);
}
for(int j=0; j<bSize; j++) {
insertValue(b[j], c, &cSize);
}
29
Τελικό αποτέλεσμα
A: 0, 1, 3, 4, 7, 9, 11, 12 (size=8)
B: 0, 1, 2, 3, 4, 9, 10, 11, 12 (size=9)
C: 0, 1, 2, 3, 4, 7, 9, 10, 11, 12 (size=10)
30
Ο Τελικός κώδικας
Σχεδιασμός
Αλγορίθμου
Κώδικας
(υλοποίηση)
Profit !
31
Μια “καλή” συνάρτηση
●
Χωράει σε ένα slide
●
Έχει ένα καλό περιγραφικό όνομα (δύσκολο)
●
Κρατάει τα αναλλοίωτα
●
Κάνει ένα μόνο πράγμα (και το κάνει σωστά)
●
Δεν έχει παρενέργειες (side effects)
– Ίδιες τιμές εισόδου δίνουν την ίδια τιμή εξόδου
– Δεν χρησιμοποιεί global μεταβλητές
●
Είναι εύκολο να ελεγχθεί μόνη της
●
Γενική: Μπορεί να χρησιμοποιηθεί σε ένα άλλο πρόγραμμα
rand() ???
32
Η δομή του κώδικα
33
void fillArray(int a[], int *size)
void fillArray(int* array, int* size) {
for (int pos = 0; pos < N; pos++) {
int newValue = getRandom();
insertValue(newValue, array, size);
}
}
Καλή
συνάρτηση;
34
bool isValueExist(int value, const int *a, int size)
bool isValueExist(int value, const int a[], int size) {
for (int sPos = 0; sPos < size; sPos++) {
if (a[sPos] == value) {
return true;
}
}
return false;
}
35
int findPosInArray(int value, const int array[], int size);
// Return the position of a value in an array
int findPosInArray(int value, const int array[], int size) {
int position;
for (position = 0; position < size; position++) {
if (array[position] >= value) {
break;
}
}
return position;
}
Βρες το
λάθος
36
void printRevArray(int const* arr, int size);
// Print array in reverse order
void printRevArray(int const* arr, int size) {
for (int pos = size - 1; pos >= 0; pos--) {
char* comma = pos == 0 ? "" : ", ";
printf("%2d%s", arr[pos], comma);
}
}
37
Ήταν δύσκολο;
“Πονάει πάντα η πρώτη φορά”
Γιάννης Αγγελάκας, Τρύπες

More Related Content

What's hot

Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣ
Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣΗ ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣ
Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣDimitris Psounis
 
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝ
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝ
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝDimitris Psounis
 
Eισαγωγή στο TDD
Eισαγωγή στο TDDEισαγωγή στο TDD
Eισαγωγή στο TDDjtsagata
 
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣ
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣ
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣDimitris Psounis
 
Aepp kef02 7-82
Aepp kef02 7-82Aepp kef02 7-82
Aepp kef02 7-82mnikol
 
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣ
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣΗ ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣ
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣDimitris Psounis
 
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣ
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣ
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣDimitris Psounis
 

What's hot (18)

ΠΛΗ10 ΜΑΘΗΜΑ 1.4
ΠΛΗ10 ΜΑΘΗΜΑ 1.4ΠΛΗ10 ΜΑΘΗΜΑ 1.4
ΠΛΗ10 ΜΑΘΗΜΑ 1.4
 
ΠΛΗ10 ΤΕΣΤ 23
ΠΛΗ10 ΤΕΣΤ 23ΠΛΗ10 ΤΕΣΤ 23
ΠΛΗ10 ΤΕΣΤ 23
 
ΠΛΗ10 ΤΕΣΤ 25
ΠΛΗ10 ΤΕΣΤ 25ΠΛΗ10 ΤΕΣΤ 25
ΠΛΗ10 ΤΕΣΤ 25
 
Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣ
Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣΗ ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣ
Η ΓΛΩΣΣΑ C - ΜΑΘΗΜΑ 13 - ΔΟΜΕΣ
 
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝ
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝ
ΠΛΗ30.ΚΑΡΤΑ - ΑΝΑΛΥΣΗ ΔΙΑΔΙΚΑΣΤΙΚΩΝ ΑΛΓΟΡΙΘΜΩΝ
 
Eισαγωγή στο TDD
Eισαγωγή στο TDDEισαγωγή στο TDD
Eισαγωγή στο TDD
 
ΠΛΗ10 ΤΕΣΤ 30
ΠΛΗ10 ΤΕΣΤ 30ΠΛΗ10 ΤΕΣΤ 30
ΠΛΗ10 ΤΕΣΤ 30
 
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣ
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣ
ΠΛΗ10 ΜΑΘΗΜΑ 2.3: ΤΕΛΕΣΤΕΣ ΚΑΙ Η ΕΝΤΟΛΗ ΑΠΟΦΑΣΗΣ
 
ΠΛΗ10 ΜΑΘΗΜΑ 2.4
ΠΛΗ10 ΜΑΘΗΜΑ 2.4ΠΛΗ10 ΜΑΘΗΜΑ 2.4
ΠΛΗ10 ΜΑΘΗΜΑ 2.4
 
Aepp kef02 7-82
Aepp kef02 7-82Aepp kef02 7-82
Aepp kef02 7-82
 
ΠΛΗ10 ΤΕΣΤ 24
ΠΛΗ10 ΤΕΣΤ 24ΠΛΗ10 ΤΕΣΤ 24
ΠΛΗ10 ΤΕΣΤ 24
 
ΠΛΗ10 ΜΑΘΗΜΑ 2.2
ΠΛΗ10 ΜΑΘΗΜΑ 2.2ΠΛΗ10 ΜΑΘΗΜΑ 2.2
ΠΛΗ10 ΜΑΘΗΜΑ 2.2
 
Microworld[1]
Microworld[1]Microworld[1]
Microworld[1]
 
ΠΛΗ10 ΤΕΣΤ 15
ΠΛΗ10 ΤΕΣΤ 15ΠΛΗ10 ΤΕΣΤ 15
ΠΛΗ10 ΤΕΣΤ 15
 
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣ
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣΗ ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣ
Η ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 4 - ΚΛΑΣΕΙΣ ΚΑΙ ΑΝΑΦΟΡΕΣ
 
ΠΛΗ30 ΜΑΘΗΜΑ 4.3
ΠΛΗ30 ΜΑΘΗΜΑ 4.3ΠΛΗ30 ΜΑΘΗΜΑ 4.3
ΠΛΗ30 ΜΑΘΗΜΑ 4.3
 
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣ
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣ
ΓΛΩΣΣΑ C++ - ΜΑΘΗΜΑ 3 - ΚΛΑΣΕΙΣ ΚΑΙ ΔΕΙΚΤΕΣ
 
Little man computer
Little man computerLittle man computer
Little man computer
 

Similar to Παιγνίδια με Πίνακες και Δείκτες

77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...
77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...
77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...Panagiotis Kanavos
 
13 Προγράμματα Pascal
13 Προγράμματα Pascal13 Προγράμματα Pascal
13 Προγράμματα PascalStathis Gourzis
 
Microsoft Access Θεωρία 3/6
Microsoft Access Θεωρία 3/6Microsoft Access Θεωρία 3/6
Microsoft Access Θεωρία 3/6Michael Ntallas
 
Επίλυση προβλήματος με προγραμματισμό (Scratch)
Επίλυση προβλήματος με προγραμματισμό (Scratch)Επίλυση προβλήματος με προγραμματισμό (Scratch)
Επίλυση προβλήματος με προγραμματισμό (Scratch)pasxelfstone
 
Advanced Notes on Pointers
Advanced Notes on PointersAdvanced Notes on Pointers
Advanced Notes on Pointersjtsagata
 

Similar to Παιγνίδια με Πίνακες και Δείκτες (6)

77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...
77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...
77o dotNETZone Meetup: Pattern matching expressions. One small step for one l...
 
13 Προγράμματα Pascal
13 Προγράμματα Pascal13 Προγράμματα Pascal
13 Προγράμματα Pascal
 
Microsoft Access Θεωρία 3/6
Microsoft Access Θεωρία 3/6Microsoft Access Θεωρία 3/6
Microsoft Access Θεωρία 3/6
 
Επίλυση προβλήματος με προγραμματισμό (Scratch)
Επίλυση προβλήματος με προγραμματισμό (Scratch)Επίλυση προβλήματος με προγραμματισμό (Scratch)
Επίλυση προβλήματος με προγραμματισμό (Scratch)
 
Advanced Notes on Pointers
Advanced Notes on PointersAdvanced Notes on Pointers
Advanced Notes on Pointers
 
ΛΟΓΙΣΤΙΚΑ ΦΥΛΛΑ
ΛΟΓΙΣΤΙΚΑ ΦΥΛΛΑΛΟΓΙΣΤΙΚΑ ΦΥΛΛΑ
ΛΟΓΙΣΤΙΚΑ ΦΥΛΛΑ
 

More from jtsagata

GPGPU Computation
GPGPU ComputationGPGPU Computation
GPGPU Computationjtsagata
 
Linux and C
Linux and CLinux and C
Linux and Cjtsagata
 
Greek utf8
Greek utf8Greek utf8
Greek utf8jtsagata
 
Why computers can' compute
Why computers can' computeWhy computers can' compute
Why computers can' computejtsagata
 
Τι είναι υπολογισμός
Τι είναι υπολογισμόςΤι είναι υπολογισμός
Τι είναι υπολογισμόςjtsagata
 
IEEE 754 Floating point
IEEE 754 Floating pointIEEE 754 Floating point
IEEE 754 Floating pointjtsagata
 
Η Τέχνη του TeX/LaTeX
Η Τέχνη του TeX/LaTeXΗ Τέχνη του TeX/LaTeX
Η Τέχνη του TeX/LaTeXjtsagata
 
Unikernels
UnikernelsUnikernels
Unikernelsjtsagata
 
FPGA on the Cloud
FPGA on the Cloud FPGA on the Cloud
FPGA on the Cloud jtsagata
 
Evolutionary keyboard Layout
Evolutionary keyboard LayoutEvolutionary keyboard Layout
Evolutionary keyboard Layoutjtsagata
 
Το εργαλείο
Το εργαλείοΤο εργαλείο
Το εργαλείοjtsagata
 

More from jtsagata (14)

C locales
C localesC locales
C locales
 
GPGPU Computation
GPGPU ComputationGPGPU Computation
GPGPU Computation
 
Linux and C
Linux and CLinux and C
Linux and C
 
Git intro
Git introGit intro
Git intro
 
Greek utf8
Greek utf8Greek utf8
Greek utf8
 
Why computers can' compute
Why computers can' computeWhy computers can' compute
Why computers can' compute
 
Τι είναι υπολογισμός
Τι είναι υπολογισμόςΤι είναι υπολογισμός
Τι είναι υπολογισμός
 
IEEE 754 Floating point
IEEE 754 Floating pointIEEE 754 Floating point
IEEE 754 Floating point
 
Η Τέχνη του TeX/LaTeX
Η Τέχνη του TeX/LaTeXΗ Τέχνη του TeX/LaTeX
Η Τέχνη του TeX/LaTeX
 
Unikernels
UnikernelsUnikernels
Unikernels
 
FPGA on the Cloud
FPGA on the Cloud FPGA on the Cloud
FPGA on the Cloud
 
Evolutionary keyboard Layout
Evolutionary keyboard LayoutEvolutionary keyboard Layout
Evolutionary keyboard Layout
 
Omilia
OmiliaOmilia
Omilia
 
Το εργαλείο
Το εργαλείοΤο εργαλείο
Το εργαλείο
 

Παιγνίδια με Πίνακες και Δείκτες

  • 1. Παιγνίδια με Πίνακες και Δείκτες Δομημένος Προγραμματισμός Τσαγκατάκης Ιωάννης
  • 2. 2 Πως λύνουμε ένα πρόβλημα ; Σχεδιασμός Αλγορίθμου Κώδικας (υλοποίηση) Profit !
  • 3. 3 Test Driven Development ● Σπάω το πρόβλημα σε μικρότερα και απλούστερα ● Βεβαιώνομε πως κάθε τι είναι σωστό ● Ο αλγόριθμος προκύπτει ● Προκύπτει κώδικας εύκολος στην κατανόηση και την αλλαγή
  • 4. 4 Μια λύση της Εργασίας ● Με μοντέρνα C – Χρησιμοποιώντας πράγματα που ίσως δεν ξέρετε – Άρα δεν είναι αυτό που θα έπρεπε να παραδώσετε ● Με χρήση μικρών συναρτήσεων ● Μια καλή επανάληψη
  • 5. 5 Ο λογικός τύπος bool // Old C typedef int bool; #define true 1 #define false 0 // C99 #include <stdbool.h>
  • 6. 6 Μεταβλητές και δείκτες Όνομα Τύπος Μέγεθος Διεύθυνση Μνήμης Τιμή var int sizeof(int) 4 0x7FF..02C 42 pVar int * sizeof(int*) 8 0X7FF..030 0x7FF..02C int main() { int var = 42; int *pVar = &var; assert(*pVar == 42); } Symbol Table ● Η τιμή μιας μεταβλητής: var, pVar ● Η διεύθυνση μνήμης : &var, &pVar ● Η τιμή, που δείχνει ένας δείκτης: *pVar ● Όλοι οι δείκτες πιάνουν το ίδιο χώρο στη μνήμη sizeof(int *) == sizeof(void *) Ένας δείκτης σε δείκτη που δείχνει στην μνήμη της var όπου ή var έχει την τιμή 42 H εικόνα φτιάχτηκε με την βοήθεια του ddd (GNU data display debugger)
  • 7. 7 Η αναπαράσταση ενός πίνακα ● Ένας πίνακας έχει – Ένα μέγιστο μήκος Ν – Ένα μέγεθος – Τιμές ● Αν ξέραμε δομές #define TRUE 1 #define FALSE 0 const int N = 10; int main() { int a[N]; int aSize = 0; for(int i=0; i<aSize; i++) a[i]=-99; fillArray_partial(a, &aSize); assert(aSize <= N); printf("%4s", "A:"); printArray(a, aSize); printf(" (size=%d)n", aSize); return 0; } struct partialArray { int *arr; int size; int maxSize; };
  • 8. 8 Ο Πίνακας στην μνήμη ● Σύνολο στοιχείων: 10 / 20, size == 10 ● Βασική συνθήκη (αναλλοίωτο): (size <= maxSize) && (size >= 0) size <= maxSize) && (size <= maxSize) && (size >= 0) size >= 0) ● Πρώτη τιμή : array[0] ● Τελευταία τιμή : array[size-1] ● Δεν “υπάρχει” το : array[size] ! ● Συνολικό μέγεθος σε bytes: maxSize * sizeof(size <= maxSize) && (size >= 0) int) 876543210 9 maxSize = 20 size Κάπου στην στοίβα ο πίνακας int array[maxSize] assert(a == &a[0]); a[4] = 42; assert(a[4] == *(a + 4)); assert(&a[4] == a+4); *(a+4) = 24; assert(a[4]==24); sizeof(int) 1 2 4 5 42 9 10 12 13 22 ?? ?? To index 4, η τιμή 42 Η διεύθυνση μνήμης (size <= maxSize) && (size >= 0) a+4) ή &a[4]
  • 9. 9 Μια πρώτη συνάρτηση ● Μικρές συναρτήσεις κάνουν τον κώδικα μας καλύτερο int getRandom() { const int maxValue = 12; int random_value = rand() % (maxValue + 1); return random_value; } Τύπος εξόδου ή void Κενή είσοδος Τιμή Επιστροφής
  • 10. 10 Μια συνάρτηση με είσοδο ● Πριν η C χρησιμοποιήσει μια συνάρτηση θα πρέπει να ξέρει την “υπογραφή” της σε μια δήλωση (declaration). – Το όνομα της – Τον τύπο δεδομένων των εισόδων της (αν υπάρχουν) – Τον τύπο δεδομένων της μιας μοναδικής εξόδου ή τίποτα (void) ● Ο κώδικας της συνάρτησης υπάρχει στον ορισμό της (definition). ● Τα Header Files περιέχουν τα declarations των συναρτήσεων που χρησιμοποιούμε. – Τα ενσωματώνουμε με την εντολή #include include του προ-επεξεργαστή #include <stdlib.h> int getRandomMax(int maxValue); int getRandomMax(int maxValue) { maxValue++; int random_value = rand() % maxValue ; return random_value; } Declaration Definition Είσοδος με τιμή Θα περάσει αντίγραφο της τιμής στην στοίβα. Τοπική αλλαγή !
  • 11. 11 Τυχαίοι αριθμοί (κλειστό διάστημα) #include <stdlib.h> int getRandom() { // Values at closed [min,max] const int minValue = 10; const int maxValue = 19; // range = 10 int range = maxValue - minValue + 1; // From 0 ... 9 int random_value = rand() % range ; int result = random_value + minValue; return result; }
  • 12. 12 Πίνακες, δείκτες και συναρτήσεις ● Στενή σχέση μεταξύ πίνακα και δείκτη ● Κατάρρευση τύπου από πίνακα σε δείκτη. ● Οι πίνακες περνάνε σαν αναφορά και όχι σαν αντίγραφο των στοιχείων τους. – Μικρή χρήση μνήμης – Αλλά μπορεί ο πίνακας να αλλάξει ● Ακόμα και αν δεν θέλουμε – H C99 υποστηρίζει const void printArray(int const* arr, int size) ● Ο τύπος που δείχνει ένας δείκτης είναι σημαντικός για την αριθμητική των δεικτών. ● Δεν ξέρω πόσο μεγάλος είναι ο πίνακας! – Περνάω το size σαν τιμή ή δείκτη (αναφορά). void printArray(int* arr, int size) { for (int pos = 0; pos < size; pos++) { char* comma = ( (pos == (size – 1) ) ? "" : ","); printf("%2d%s", arr[pos], comma); } } Πέρασμα πίνακα σαν διεύθυνση μνήμης (δείκτης) Χρήση δείκτη σαν να είναι πίνακας Τριαδικός τελεστής Περιττές παρενθέσεις ;
  • 13. 13
  • 14. 14 Περιττές παρενθέσεις; comma = pos == size - 1 ? "" : ", "; ● Θα κάνει αυτό που πρέπει να κάνει Εκτός βέβαια αν δεν το κάνει ● Βάζουμε παρενθέσεις ● Για τεκμηρίωση ● Για σιγουριά ● Αλλά συνήθως θα κάνει αυτό που πρέπει να κάνει ● C idioms από βιβλία
  • 15. 15 Κόλπο: Διαβάζοντας δηλώσεις Από τα δεξιά προς τα αριστερά! const int *pci; Είναι ακριβώς το ίδιο const int *p; const int* p; int const *p; int * const p; The p is a constant pointer to an int
  • 16. 16
  • 17. 17 Πέρασμα τιμής με αναφορά ● Οι μικρές συναρτήσεις κάνουν τον αλγόριθμο ευανάγνωστο void fillArray_partial(int* a, int* aLoc) { for (int pos = 0; pos < N; pos++) { int newValue, isValueExist; newValue = getRandom(); isValueExist = findInArray(a, *aLoc, newValue); if (isValueExist == FALSE) { insertValue(a, aLoc, newValue); } } } fillArray_partial(a, &aSize); Δίνω την διεύθυνση μνήμης μου Η τιμή μου μπορεί να αλλάξει Η τιμή (*aLoc) που έχει η διεύθυνση μνήμης που δείχνει o δείκτης aLoc Χρήση ᅠΠέρασμα σαν διεύθυνση μνήμης ώστε η τιμή να μπορεί να αλλάξει
  • 18. 18 Πέρασμα τιμών σε συναρτήσεις ● Σαν τιμή – Θα δημιουργηθεί ένα αντίγραφο της τιμής στην στοίβα – Δεν βολεύει όταν τα δεδομένα είναι μεγάλα σε χώρο μνήμης ● Σαν αναφορά μνήμης – Θα περάσει η διεύθυνση της μνήμης σαν ένας δείκτης (*var) – Οι δείκτης αυτός μπορεί να είναι κενός (size <= maxSize) && (size >= 0) NULL) – Η συνάρτηση μπορεί να αλλάξει την τιμή (πχ scanf) – Εκτός αν ο δείκτης δηλωθεί σαν const (C99) – Στην C++ μια τιμή μπορεί να περάσει και σαν reference (&var) ● Όταν λέμε πέρασμα με αναφορά εννοούμε είτε pointers είτε αυτό ● Οι περισσότερες γνωστές γλώσσες προγραμματισμού περνάνε τιμές μόνο με αναφορά
  • 19. 19 Βρόχοι void fillArray_full(int* a, int* aLoc) { for (int pos = 0; pos < N; pos++) { int newValue, isValueExist; // Get unique Value do { newValue = getRandom(); isValueExist = findInArray(a, *aLoc, newValue); } while (isValueExist == TRUE); insertValue(a, aLoc, newValue); } } Σπάζοντας τον κώδικα σε συναρτήσεις οι αλλαγές είναι εύκολες Τα ονόματα των μεταβλητών λένε ιστορίες Θα τρέξω τουλάχιστον μια φορά
  • 21. 21 Συναρτήσεις: Επιστρέφοντας τιμές // Find if a value exist on Array int findInArray(const int a[], int size, int value) { int found = FALSE; for (int sPos = 0; sPos < size; sPos++) { if (a[sPos] == value) { found = TRUE; break; } } return found; } for (int sPos = 0; sPos < size; sPos++) { if (a[sPos] == value) { return true; } } return false; Εναλλακτική υλοποίηση Πολλαπλά σημεία εξόδου
  • 22. 22 Ας διαχωρίσουμε αρμοδιότητες ● Μια συνάρτηση πρέπει να κάνει ένα πράγμα μόνο ● Μια συνάρτηση να παράγει πολλαπλές τιμές ● Μια να τις εισάγει στον πίνακα. ● Θέλω η insert να – Βάζει την τιμή στην σωστή θέση – Αν η τιμή δεν υπάρχει – Η πιθανά κάποιο άλλο κριτήριο που μπορεί να προκύψει στο μέλλον void fillArray_simple(int* a, int* aLoc) { for (int pos = 0; pos < N; pos++) { int newValue = getRandom(); insertValue(a, aLoc, newValue); } } void insertValue(int* a, int* aLoc, int value) { a[*aLoc] = value; *aLoc = *aLoc + 1; } fillArray_simple(a, &aSize); printArray(a, aSize); printf(" (size=%d)n", aSize);
  • 23. 23 Μια πρώτη προσπάθεια Τα assert σώζουν ζωές ! void insertValue(int* a, int* aLoc, int value) { assert(*aLoc < N); if( findInArray(a, *aLoc, value) == FALSE) { a[*aLoc] = value; *aLoc = *aLoc + 1; } assert(*aLoc <= N); } Η θέση είναι λάθος Αρκεί να μπει στην σωστή θέση Προϋπόθεση συμβολαίου (pre condition) Αναλλοίωτο Post Condition
  • 24. 24 Και τέλος η insertValue void insertValue(int value, int* array, int* size) { // assert(*size < N); bool exists = isValueExist(value, array, *size); if (exists == false) { int pos = findPosInArray(value, array, *size); if (pos != *size) { // Make space for(int i=*size; i>pos; i--) { array[i]=array[i-1]; } } array[pos]=value; *size = *size + 1; } // assert(*size <= N); }
  • 25. 25 Και τέλος η insertValue void insertValue(int value, int* array, int* size) { // assert(*size < N); bool exists = isValueExist(value, array, *size); if (exists == false) { int pos = findPosInArray(value, array, *size); if (pos != *size) { // Make space for(int i=*size; i>pos; i--) { array[i]=array[i-1]; } } array[pos]=value; *size = *size + 1; } // assert(*size <= N); } Έχει νόημα να γίνει μια χωριστή συνάρτηση arrayShiftRightAt(..) Πέρασμα του πίνακα 2 φορές;
  • 26. 26 Παίρνοντας και την θέση εισαγωγής ● Προσοχή στις τιμές των φρουρών ● Υπάρχουν πολλοί άλλοι τρόποι να δηλώσεις αποτυχία #include <limits.h> const int guard1 = -9999999; const int guard = INT_MIN; // Return the position of a value in an array int findPosInArray(int value, const int* a, int size) { for (int sPos = 0; sPos < size; sPos++) { if (a[sPos] == value) { return sPos; } } return guard; } Άσκηση για το σπίτι Υλοποιήστε αυτή την λύση κάνοντας τις απαραίτητες τροποποιήσεις
  • 27. 27 Ο αλγόριθμος βήμα βήμα Insert value: 13 at position 0, that is the end of array -> 13 (size=1) Insert value: 16 at position 1, that is the end of array -> 13, 16 (size=2) Insert value: 17 at position 2, that is the end of array -> 13, 16, 17 (size=3) Insert value: 15 at position 1, making space -> 13, 15, 16, 17 (size=4) Insert value: 13, value already exists skipping. Insert value: 15, value already exists skipping. Insert value: 16, value already exists skipping. Insert value: 12 at position 0, making space -> 12, 13, 15, 16, 17 (size=5) Insert value: 19 at position 5, that is the end of array -> 12, 13, 15, 16, 17, 19 (size=6) Insert value: 11 at position 0, making space -> 11, 12, 13, 15, 16, 17, 19 (size=7) A: 11, 12, 13, 15, 16, 17, 19 (size=7) 13 16 17 13 16 17 17 13 16 16 17 13 15 16 17 115 size=3 size=4
  • 28. 28 Συνδέοντας τους πίνακες ● Έκπληξη!! το merge έχει ήδη φτιαχτεί !!! int a[N], b[N], c[N+N]; int aSize = 0, bSize=0, cSize=0; fillArray(a, &aSize); fillArray(b, &bSize); for(int i=0; i<aSize; i++) { insertValue(a[i], c, &cSize); } for(int j=0; j<bSize; j++) { insertValue(b[j], c, &cSize); }
  • 29. 29 Τελικό αποτέλεσμα A: 0, 1, 3, 4, 7, 9, 11, 12 (size=8) B: 0, 1, 2, 3, 4, 9, 10, 11, 12 (size=9) C: 0, 1, 2, 3, 4, 7, 9, 10, 11, 12 (size=10)
  • 31. 31 Μια “καλή” συνάρτηση ● Χωράει σε ένα slide ● Έχει ένα καλό περιγραφικό όνομα (δύσκολο) ● Κρατάει τα αναλλοίωτα ● Κάνει ένα μόνο πράγμα (και το κάνει σωστά) ● Δεν έχει παρενέργειες (side effects) – Ίδιες τιμές εισόδου δίνουν την ίδια τιμή εξόδου – Δεν χρησιμοποιεί global μεταβλητές ● Είναι εύκολο να ελεγχθεί μόνη της ● Γενική: Μπορεί να χρησιμοποιηθεί σε ένα άλλο πρόγραμμα rand() ???
  • 32. 32 Η δομή του κώδικα
  • 33. 33 void fillArray(int a[], int *size) void fillArray(int* array, int* size) { for (int pos = 0; pos < N; pos++) { int newValue = getRandom(); insertValue(newValue, array, size); } } Καλή συνάρτηση;
  • 34. 34 bool isValueExist(int value, const int *a, int size) bool isValueExist(int value, const int a[], int size) { for (int sPos = 0; sPos < size; sPos++) { if (a[sPos] == value) { return true; } } return false; }
  • 35. 35 int findPosInArray(int value, const int array[], int size); // Return the position of a value in an array int findPosInArray(int value, const int array[], int size) { int position; for (position = 0; position < size; position++) { if (array[position] >= value) { break; } } return position; } Βρες το λάθος
  • 36. 36 void printRevArray(int const* arr, int size); // Print array in reverse order void printRevArray(int const* arr, int size) { for (int pos = size - 1; pos >= 0; pos--) { char* comma = pos == 0 ? "" : ", "; printf("%2d%s", arr[pos], comma); } }
  • 37. 37 Ήταν δύσκολο; “Πονάει πάντα η πρώτη φορά” Γιάννης Αγγελάκας, Τρύπες