460 likes | 610 Views
Συναρτήσεις. Κληση/Επιστροφη Παραμετροι Περασμα/Επιστροφη δια αναφορας Δεικτες (τελεστες * και &) Εμβελεια Μεταβλητων (συναρτησεων) τοπικες/καθολικες/στατικες/αυτοματες Αναδρομη. τ υπ ικοι παραμετροι. ορισματα/ πραγματικοι παραμετροι. #include <stdio.h>
E N D
Συναρτήσεις • Κληση/Επιστροφη • Παραμετροι • Περασμα/Επιστροφη δια αναφορας • Δεικτες (τελεστες * και &) • Εμβελεια Μεταβλητων (συναρτησεων) • τοπικες/καθολικες/στατικες/αυτοματες • Αναδρομη
τυπικοι παραμετροι ορισματα/ πραγματικοι παραμετροι #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 και αντιγραφη της τιμης στο σημειο κλησης (εαν επιστρεφεται τιμη) • Συνεχιση εκτελεσης με την εντολη που ακολουθει την κληση
sum a 9 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); } 0 5 4 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); } 9
Παραμέτροι • Επιτρεπουν την επικοινωνια μεταξυ συναρτησεων • περασμα δια τιμης (τιμή) • Διοχετευση πληροφοριων προς στην συναρτηση • Μεταβλητη στην συναρτηση κλησης δεν επηρεαζεται - αντιγραφεται η τιμη της • περασμα/επιστροφη δια αναφορας (διεύθυνση) • Διοχετευση πληροφοριων απο την συναρτηση (και εισοδο) • Μεταβλητη στην συναρτηση κλησης μπορει να της ανατεθουν τιμες στην καλουμενη συναρτηση (scanf με τελεστη διευθυνσης) • Επιστροφη πολλων τιμων μεσο διευθυνσεων
4 4 6 6 a 6 c 4 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); printf(“a: %d, b: %d\n”,a,c); return(0); } 4
4 6 a 6 c 4 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); printf(“a: %d, c: %d\n”,a,c); return(0); } 4
4 6 a 6 c 4 #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); printf(“a: %d, c: %d\n”,a,c); return(0); }
Δεικτες (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; *p = *p + 1; y = *z + 1;
Παραδειγμα δεικτες • Γραψετε την συναρτηση 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 (καθολικες) • δηλωνονται εξω απο συναρτησεις • οπουδηποτε μετα τον ορισμο • Συγκρουσεις:τοπικες ονομασιες εχουν προτεραιοτητα
#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)
Καθολικες Μεταβλητες • Γενικα πρεπει να αποφευγονται: δυσκολο να κατανοησεις πλευρικα φαινομενα γιατι διεπαφη γινεται χωρις παραμετρους • Χρησιμη για μεταβλητες που χρησιμοποιουντε απο πολλες συναρτησεις
sum a 9 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); } 0 5 4 9
9 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); } 0 5 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 • n! = n n-1! • fact(n) = n fact(n-1) και fact(1)=1, fact(0)=1
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; } Αναδρομή (recursion)
Προβληματα Αναδρομής • Αχρειαστος υπολογισμος • Δεσμευση μνημης (για αυτοματες μεταβλητες)
Ακολουθια 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 0 1 0 Fib(0) Fib(1) 0 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); }