Συναρτήσεις Κληση/Επιστροφη Παραμετροι Περασμα/Επιστροφη δια αναφορας Δεικτες (τελεστες * και &) Εμβελεια Μεταβλητων (συναρτησεων) τοπικες/καθολικες/στατικες/αυτοματες Αναδρομη
πρωτοτυπο συναρτησης τυπικοι παραμετροι ορισμος συναρτησης ορισματα/ #include <stdio.h> float compute_area(float x, float y); float compute_area(float a, float b) { return (a * b); } int main() float length, width, area; printf(“Enter length and width: “); scanf(“%f%f”,&length, &width); area = compute_area(length, width); printf(“The area of a rectangle %f m by %f m is %f sq. m\n”, length, width, area); return 0; πρωτοτυπο συναρτησης τυπικοι παραμετροι ορισμος συναρτησης ορισματα/ πραγματικοι παραμετροι κληση συναρτησης
Σημασία Κλήσης Κατανομη μνημης για παραμετρους και τοπικες μεταβλητες της συναρτησης (εαν υπαρχουν) Αντιγραφη των τιμων των ορισματων στις παραμετρους (εαν υπαρχουν παραμετροι) Ξεκινα εκτελεσης απο την πρωτη εντολη της συναρτησης
Σημασία Επιστροφής Αποτιμηση της εκφρασης που ακολουθει το return και αντιγραφη της τιμης στο σημειο κλησης (εαν επιστρεφεται τιμη) Συνεχιση εκτελεσης με την εντολη που ακολουθει την κληση
9 5 4 9 sum a b sum #include <stdio.h> int compute_sum(int x, int y); int compute_sum(int a, int b) { int sum; sum = a + b; return sum; } int main() int sum=0; sum = compute_sum(5, 4); printf(“The sum of %d and %d is %d\n”,4, 5, sum); return(0); sum 9 a 5 b 4 sum 9
9 sum #include <stdio.h> int compute_sum(int x, int y); int compute_sum(int a, int b) { int sum; sum = a + b; return sum; } int main() int sum=0; sum = compute_sum(5, 4); printf(“The sum of %d and %d is %d\n”,4, 5, sum); return(0); sum 9
Παραμέτροι Επιτρεπουν την επικοινωνια μεταξυ συναρτησεων περασμα δια τιμης (τιμή) Διοχετευση πληροφοριων προς στην συναρτηση Μεταβλητη στην συναρτηση κλησης δεν επηρεαζεται - αντιγραφεται η τιμη της περασμα/επιστροφη δια αναφορας (διεύθυνση) Διοχετευση πληροφοριων απο την συναρτηση (και εισοδο) Μεταβλητη στην συναρτηση κλησης μπορει να της ανατεθουν τιμες στην καλουμενη συναρτηση (scanf με τελεστη διευθυνσης) Επιστροφη πολλων τιμων μεσο διευθυνσεων
4 6 6 4 4 6 4 a c a b temp #include <stdio.h> int swap(int x, int y); void swap(int a, int b) { int temp; temp = a; a = b; b = temp; } int main() int a=4, c=6; printf(“a: %d, b: %d\n”,a,c); swap(a, c); return(0); a c 4 6 a b temp 6 4 6 4 4
6 4 4 6 4 a c a b temp #include <stdio.h> int swap(int *x, int *y); void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int main() int a=4, c=6; printf(“a: %d, c: %d\n”,a,c); swap(&a, &c); return(0); a c 4 6 6 4 a b temp 4
6 4 4 6 a c #include <stdio.h> int swap(int *x, int *y); void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int main() int a=4, c=6; printf(“a: %d, c: %d\n”,a,c); swap(&a, &c); return(0); a c 4 6 6 4
Δεικτες (pointers) Συνταξη Δηλωσης Δεικτη Σημασια Δεικτη τυπος *ονομα_μεταβλητης int *foo, *pointer, no_pointer; Σημασια Δεικτη μεταβλητη που περιεχει διευθυνση μιας αλλης μεταβλητης
Δεικτες Τελεστης Διευθυνσης & Τελεστης Εμμεσης Αναφορας * Συνταξη: &ονομα_μεταβλητης (συναρτηση) Σημασια: δινει την διευθυνση της μεταβλητης Τελεστης Εμμεσης Αναφορας * Συνταξη: *διευθυνση Σημασια: δινει την τιμη στην διευθυνση
Τελεστης * Τελεστης γινομενου Δηλωση Δεικτη a*b; Δηλωση Δεικτη int *p; Τελεστης Εμμεσης Αναφορας * x = *p + 1;
Παραδειγμα με Δεικτες int *p, y, *z; y p *p z *z y = 6; p = &y; z = p;
Παραδειγμα δεικτες Γραψετε την συναρτηση sort2 που ταξινομει δυο αριθμους a και b ωστε μετα την εκτελεση a<=b Χρειαζονται δεικτες
Παραδειγμα δεικτες void sort2(int *a, int *b) { int temp; if (*a>*b) temp=*a; *a=*b; *b=temp; }
Παραδειγμα δεικτες void sort2(int *a, int *b) { if (*a>*b) swap(a,b); }
Παραδειγμα δεικτες Γραψετε την συναρτηση sort3 που ταξινομει τρεις ακεραιους αριθμους a, b και c ωστε μετα την εκτελεση a<=b<=c Χρησιμοποιηστε την sort2
Παραδειγμα δεικτες void sort3(int *a, int *b, int *c) { sort2(a,b); /* a<= b*/ sort2(a,c); /* a<=c and a<=b sort2(b,c); /* b<= c */ }
Χρηση δεικτων Χρησιμοποιατε δεικτες μονο οταν χρειαζονται - εμμεση αναφορα ειναι αργη σχεδον σε ολους τους υπολογιστες Οταν μια συναρτηση επιστρεφει μια τιμη χρησιμοποιατε return αντι δεικτη Πλευρικα φαινομενα μεσω δεικτων πιο δυσκολα να κατανοηθουν/ανιχνευτουν Πολυ κοινη πηγη λαθων
Εμβέλεια Μεταβλητής (scope) Το τμημα του προγραμματος που μπορει μια μεταβλητη να χρησιμοποιηθει local (τοπικες): δηλωνονται στην αρχη ενος programming block {..} οπουδηποτε μετα τον ορισμο μεσα στο block global (καθολικες) δηλωνονται εξω απο συναρτησεις οπουδηποτε μετα τον ορισμο Συγκρουσεις:τοπικες ονομασιες εχουν προτεραιοτητα
Παραμετροι (parameters) #include <stdio.h> int sum=0; int compute_sum(int x, int y); void compute_sum(int a, int b) { sum = a + b; } int main() int a = 4; compute_sum(a, 6); printf(“The sum of %d and %d is %d\n”,a, 6, sum); return(0); Καθολικη (global) Παραμετροι (parameters) Τοπικη (local) Ορισματα (arguments)
Καθολικες Μεταβλητες Γενικα πρεπει να αποφευγονται: δυσκολο να κατανοησεις πλευρικα φαινομενα γιατι διεπαφη γινεται χωρις παραμετρους Χρησιμη για μεταβλητες που χρησιμοποιουντε απο πολλες συναρτησεις
9 5 4 9 sum a b sum #include <stdio.h> int sum=0; int compute_sum(int x, int y); int compute_sum(int a, int b) { int sum; sum = a + b; return sum; } int main() sum = compute_sum(5, 4); printf(“The sum of %d and %d is %d\n”,4, 5, sum); return(0); sum 9 a 5 b 4 sum 9
9 5 4 sum a b #include <stdio.h> int sum=0; int compute_sum(int x, int y); void compute_sum(int a, int b) { sum = a + b; } int main() compute_sum(5, 4); printf(“The sum of %d and %d is %d\n”,4, 5, sum); return(0); sum 9 a 5 b 4
Τοπικες Μεταβλητες Αυτοματες (automatic) οι τιμες δεν διατηρουνται μεταξυ εκτελεσεων του block που δηλωνεται η μεταβλητη. Δεσμευση/ αποδεσμευση μνημης καθε κληση/ επιστροφη Στατικες (static) οι τιμες τους υφιστανται μετα την πρωτη εκτελεση του block που ανηκουν. Μια φορα δεσμευση μνημης (αναδρομη!)
Παραδειγμα automatic και static void count_events(int events) { int total = 0; total += events; printf(“Events up to now: %d\n”,total); } int main() count_events(5); count_events(10); return 0;
Παραδειγμα automatic και static void count_events(int events) { static int total = 0; total += events; printf(“Events up to now: %d\n”,total); } int main() count_events(5); count_events(10); return 0;
Εμβέλεια Συναρτησεων C Το τμημα του προγραμματος που μπορει μια συναρτηση να χρησιμοποιηθει Oλες οι συναρτησεις σε ενα αρχειο ειναι καθολικες (δεν υπαρχουν τοπικες συναρτησεις) Η C δεν παρεχει τοπικες συναρτησεις (αλλες γλωσσες μπορουν πχ pascal)
Αναδρομή (recursion) Συναρτηση ειναι αναδρομικη εαν ο ορισμος της περιεχει κληση στον ευατο της Αναδρομικη λυση ενος προβληματος ειναι συχνα ο “φυσικος” τροπος επιλυσης του Διαμορφωση προβληματος για αναδρομικη λυση Καθε αναδρομικη συναρτηση μπορει να υλοποιηθει με επαναληψη
Αναδρομή (recursion) Αναδρομικη και Τερματικη περιπτωση Πρεπει να υπαρχει τουλαχιστο μια βασικη περιπτωση (base-case) που τερματιζει αναδρομη. Αλλιως απειρος αναδρομη ή δεσμευση ολοκληρη μνημης. Η αναδρομική κλήση πρέπει να είναι ένα βήμα πιο κοντά σε τερματική περίπτωση, από την κλήση που οδήγησε σε αυτή.
Αναδρομή (recursion) Υπολογισμος n! n! = n n-1 n-2 … 1, 1!=1 0!=1 fact(n) = n fact(n-1) και fact(1)=1, fact(0)=1
Αναδρομή (recursion) float factorial(int n) { if (n<2) return 1; return n*factorial(n-1); } float factorial(int n) { int i ; int fact = 1; for(i=n;i>2;--i) fact = fact *i; return fact; }
Προβληματα Αναδρομής Αχρειαστος υπολογισμος Δεσμευση μνημης (για αυτοματες μεταβλητες)
Ακολουθια Fibonacci 0, 1, 1, 2, 3, 5, 8, 13, . . . . . Fib(n) = Fib(n – 2) + Fib(n – 1) και Fib(0) = 0, Fib(1) = 1 πχ Fib(2) = Fib(0)+ Fib(1) = 0 + 1 = 1 Fib(3) = Fib(1)+ Fib(2)= 1 + 1 = 2 Fib(4) = Fib(2)+ Fib(3)= 1 + 2 = 3 . . . . . . . .
Αναδρομικο Fibonacci int Fib (int x){ if (x == 0) return 0; else if (x == 1) return 1; else return Fib(x – 2) + Fib(x – 1); }
Ο ορισμός δεν είναι αποδοτικός Fib(5) Fib(3) Fib(4) Fib(2) Fib(1) Fib(2) Fib(3) 1 Fib(0) Fib(1) Fib(0) Fib(1) Fib(1) Fib(2) 1 1 1 Fib(0) Fib(1) 1 Ο ορισμός δεν είναι αποδοτικός
Fibonacci με επαναληψη int Fib (int x){ int f, a=0, b=1,i; if (x < 2) return x; for(i=2;i<=x;++i){ f=a+b; a = b; b = f; } return f; εννοια moving window
Αναδρομη και static Συναρτηση read_and_sum που διαβαζει μια σειρα θετικων ακεραιων απροσδιοριστου μεγευθους (τερματιζεται με 0) και υπολογιζει και επιστρεφει το αθροισμα τους.
Αναδρομη και static int read_and_sum() { int number; scanf(“%d”,&number); if (number == 0) return 0; return number + read_and_sum(); }
Αναδρομη και static(problematic) int read_and_sum() { static int number; scanf(“%d”,&number); if (number == 0) return 0; return number + read_and_sum(); }
Αναδρομη Γραψετε την συναρτηση reverse που διαβαζει μια απροσδιοριστου μεγεθους σειρας και την τυπωνει αντιστροφα. void reverse() { int number; scanf(“%d”,&number); if (number == 0) return; printf(“%d\n”,number); }