Υπολογιστές Ι Ε. Νισταζάκης Αναπλ. Καθηγητής
Πραγματικές και Φανταστικές Ρίζες Δευτεροβάθμιας Εξίσωσης 2 Έστω η δευτεροβάθμια εξίσωση: ax + bx+ c = 0 Ηδιακρίνουσαείναι: Δ = b 2 4ac Όταν η Δ>0, προκύπτουν πραγματικές ρίζες: b ± Δ x1,2 = 2a Όταν Δ<0, προκύπτουν μιγαδικές ρίζες: x 1,2 = b Δ ± Τι γίνεται όμως με τη ρίζα αφού 2a 2a το υπόριζο είναι αρνητικό;
Πραγματικές και Φανταστικές Ρίζες Δευτεροβάθμιας Εξίσωσης 2 Έστω η δευτεροβάθμια εξίσωση: ax + bx+ c = 0 Στην περίπτωση αυτή θα πρέπει να χρησιμοποιηθεί η φανταστική μονάδα, i, για την οποία ισχύει: 2 i = 1 Έτσι, οι ρίζες της εξίσωσης γράφονται ως: 2 b Δ b i Δ b Δ x1,2 = ± = ± = ± i = x _ re ± ix _ im 2a 2a 2a 2a 2a 2a Οπότε, τελικά θα γραφτεί ως: printf( x1 = %lf + i%lf\n, x_re, x_im);
Πραγματικές και Φανταστικές Ρίζες Δευτεροβάθμιας Εξίσωσης 2 Έστω η δευτεροβάθμια εξίσωση: ax + bx+ c = 0 #include <stdio.h> #include <math.h> int main() { double a, b, c, p1, p2, p12; double p1re, p1im, p2re, p2im, dia; printf( Dwste tis times twn: a b c\n ); scanf( %lf %lf %lf, &a, &b, &c); dia = b*b 4*a*c; if(dia<0) { p_re = ( b)/(2*a); p_im= im=(sqrt(fabs(dia)))/(2*a); printf( p1 = %lf + i%lf\n, p_re, p_im); printf( p2 = %lf i%lf \n, p_re, p_im); } return 0; } if(dia>=0) { p1 = ( b + sqrt(dia))/(2*a); p2 = ( b sqrt(dia))/(2*a); ) printf( p1 = %lf kai p2 = %lf\n,p1,p2); }
Πράξεις Πινάκων (1) Πρόσθεση (Αφαίρεση) ί Πινάκων: Α[m,p] +( ) Β[m,p] = C[m,p] Πολλαπλασιασμός Πινάκων: Α[m,n] B[n,p] = C[m,p]
Πράξεις Πινάκων (2) Πρόσθεση Πινάκων: Α[m,p] + Β[m,p] = C[m,p] for (i=0; i<m; ++i) for (j=0; j<p;++j) { c[i][j] = a[i][j]+b[i][j]; printf( \n C[%d][%d] = %lf, i+1, j+1, c[i][j]); p ( \ [ ][ ],, j, [ ][j]); }
Πράξεις Πινάκων (3) Πολλαπλασιασμός Πινάκων: Α[m,n] B[n,p] = C[m,p] for (i=0; i<m; ++i) for (j=0; j<p;++j) { c[i][j] = 0.0; for (k=0; k<n; ++k) c[i][j] =c[i][j] +a[i][k]*b[k][j]; [][] [][j]; printf( \n C[%d][%d] = %lf, i+1, j+1, c[i][j]); }
Πράξεις Πινάκων (4) Πολλαπλασιασμός Πινάκων: Α[m,n] B[n,p] = C[m,p] printf( \n ); for (i=0; i<m; ++i) { for (j=0; j<p;++j) { c[i][j] = 0.0; for (k=0; k<n; ++k) c[i][j] = c[i][j] + a[i][k]*b[k][j]; printf( C[%d][%d] = %lf\t, i+1, j+1, c[i][j]); } printf( \n ); }
Εντολή while (1) Τι κάνει η εντολή while; (α) επαναλαμβάνει ένα κομμάτι του προγράμματος για όσο διάστημα ισχύει μια συγκεκριμένη συνθήκη. (β) Πρέπει να είναι γνωστή η συνθήκη από πριν για να ξεκινήσουν οι επαναλήψεις. Πως χρησιμοποιείται στο πρόγραμμα; Ορισμός αρχικής τιμής της συνθήκης while (συνθήκη) {τμήμα του προγράμματος που θα επαναληφθεί και μεταβολή των παραμέτρων της συνθήκης}
Εντολή while (2) Τμήμα προγράμματος (παραγοντικό του n): while (counter <= n) { par = par*counter; counter = counter + 1; } Το Πρόγραμμα αυτό τρέχει; Δίνει αποτελέσματα;
Εντολή while (2) Τμήμα προγράμματος (παραγοντικό του n): counter = 2; par = 1; while (counter <= n) { par = par*counter; counter = counter + 1; } Γιατί το counter ξεκινάει από την τιμή 2;
Εντολή while (3) Να γραφτεί πρόγραμμα που να υπολογίζει το άθροισμα : A 1 1 = 1+ +... n 2 = n= 1 #include <stdio.h> int main(void) { double athroisma = 0.0, oros = 1, epsilon = 0.001; int plithos = 1; while (oros>=epsilon) { athroisma = athroisma + oros; plithos = plithos +1; oros = 1.0 / plithos; } printf( Πλήθος όρων = %d Άθροισμα σειράς =%6 3f, plithos-1, athroisma); printf( Πλήθος όρων %d. Άθροισμα σειράς %6.3f, plithos 1, athroisma); return 0; }
Εντολή do while (1) Τι κάνει η εντολή do while; (α) επαναλαμβάνει ένα κομμάτι του προγράμματος για όσο διάστημα ισχύει μια συγκεκριμένη συνθήκη. (β) ΔΕ Χρειάζεται να είναι γνωστή η συνθήκη από πριν για να ξεκινήσουν οι επαναλήψεις. Πρώτα ξεκινάει με την πρώτη επανάληψη και μετά ελέγχει αν θα συνεχίσει. Πως χρησιμοποιείται στο πρόγραμμα; do {τμήμα του προγράμματος που θα επαναληφθεί και ορισμός/μεταβολή των παραμέτρων της συνθήκης} while hl (συνθήκη)
Εντολή do while (2) Να γραφτεί πρόγραμμα που να υπολογίζει το άθροισμα : A 1 1 = 1+ +... n 2 = n= 1 #include <stdio.h> int main(void) { double athroisma = 0.0, oros, epsilon = 0.001; int plithos = 1; do { athroisma = athroisma + oros; plithos = plithos +1; oros = 1.0 / plithos; } while (oros>=epsilon) printf( Πλήθος όρων = %d Άθροισμα σειράς =%6 3f, plithos-1, athroisma); printf( Πλήθος όρων %d. Άθροισμα σειράς %6.3f, plithos 1, athroisma); return 0; }
Εντολή do while (2) Να γραφτεί πρόγραμμα που να υπολογίζει το άθροισμα : A 1 1 = 1+ +... n 2 = n= 1 #include <stdio.h> int main(void) { double athroisma = 0.0, oros, epsilon = 0.001; int plithos = 1; do { athroisma = athroisma + oros; plithos = plithos +1; oros = 1.0 / plithos; } while (oros>=epsilon) Γιατί δεν «τρέχει» αυτό το πρόγραμμα; ; printf( Πλήθος όρων = %d. Άθροισμα σειράς =%6.3f 3f, plithos-1, athroisma); return 0; }
Αρχεία (1) Τι σημαίνει δημιουργώ ένα αρχείο; (α) Ανοίγω σε μία περιοχή του δίσκου ένα αρχείο και του δίνω όνομα, π.χ. results.dat (β) Αποθηκεύωσεαυτόδεδομέναταοποίαμπορώναταμεταφέρω(μέσω e mail, USBstick, DVD, etc). (γ) Η αποθήκευση των στοιχείων γίνεται με συγκεκριμένο τρόπο που πρέπει να είναι ακριβώς ο ίδιος όταν θα χρειαστεί να τα «διαβάσω» απο το αρχείο για να τα χρησιμοποιήσω. Τι σημαίνει «διαβάζω» ένα αρχείο; (α) ανασύρω απο τον δίσκο τα στοιχεία που έχουν αποθηκευτεί και τα φέρνω στη μνήμη του υπολογιστή μου για επεξεργασία. (β) πρέπει να δημιουργήσω ένα πρόγραμμα τοοποίοναέχει τη δυνατότητα να διαβάζει δεδομένα, που έχουν αποθηκευτεί με συγκεκριμένο τρόπο σε κάποιο αρχείο, στο δίσκο του συστήματος μας.
Αρχεία (2) Δημιουργία Αρχείου #include <stdio.h> #include <stdlib.h> int main() { FILE* fp; double x, fx; fp=fopen( test1.dat, w ); for(x=-100; x<100; x=x+0.1) { fx = 3*pow(x,4)+2*pow(x,3)-5*x+1; fprintf(fp, %lf, %lf\n, x, fx);} fclose(fp); return 0;} Προσοχή στη συγκεκριμένη βιβλιοθήκη Ορισμός του fp, ως τι; Ανοίγουμε το αρχείο, δίνοντας το συγκεκριμένο ονομα και δηλώνουμε ότι είναι για εγγραφή στοιχείων (w) Μπορούμε ναχρησιμοποιήσουμε μ τοχ<=100; Αποθήκευση στο αρχείο, με συγκεκριμένο τρόπο, σε συγκεκριμένη θέση, και συγκεκριμένους τύπους δεδομένων. Κλείνουμε το αρχείο ώστε να μην χρειάζεται να του γράψουμε άλλα στοιχεία.
Διάβασμα Αρχείου int main() { FILE* fp; Αρχεία (3) fp=fopen("test1.dat", "r"); plithos=0.; athroisma_x=0.; // Αρχικοποίηση τιμών athroisma_x2=0.; while(!feof(fp)){ fscanf(fp, "%lf, %lf", &timi_x, &timi_f); plithos +=1; athroisma_x += timi_f; athroisma_x2 += pow(timi_f,2);} mesos = athroisma_x/plithos; diaspora = athroisma_x2/plithos+pow(mesos,2.); fclose(fp); ( p); return 0; } // ΠΑΝΤΑ με τον ίδιο τρόπο που έγινε το SAVE
Διάβασμα Αρχείου #include <stdio.h> #include <stdlib.h> Αρχεία (4) int main() { FILE* fp; double timi_f, athroisma_x, athroisma_x2, mesos, diaspora, timi_x, plithos; fp=fopen("test1.dat", "r"); plithos=0.; athroisma_x=0.; Για να μπορούμε να συνεχίσουμε την άθροιση έχοντας ένα σημείο αναφοράς εκκινησης athroisma_x2=0.; while(!feof(fp)){ fscanf(fp, "%lf, %lf", &timi _ x, &timi _ f); ΠΑΝΤΑ με τον ίδιο τρόπο που έγινε το SAVE plithos +=1; athroisma_x += timi_f; athroisma_x2 += pow(timi_f,2);} mesos = athroisma_x/plithos; diaspora = athroisma_x2/plithos+pow(mesos,2.); 2 printf("\nn = \t %lf\n", plithos); Μπορώ να γράψω: fprintf("\nn = \t %lf\n", plithos);??? printf("mesos = \t %lf\n", mesos); Τι αλλαγές πρέπει να κάνω; printf("diaspora = \t%lf \n", diaspora); fclose(fp); return 0; }
Μέθοδοι Ολοκλήρωσης Συναρτήσεων Συνάρτηση a b Διαμέριση σε Ν μικρά Τραπέζια ή Παραλληλόγραμμα. Αρα το βήμα στον άξονα x θα είναι: dx=(b a)/n
Μέθοδοι Ολοκλήρωσης Συναρτήσεων Μέθοδος Τραπεζίου (1) Μέθοδος Τραπεζίου (1) Κάθε στοιχειώδες Τραπέζιο θα έχει εμβαδό: dx dx a f a f dx x f x f B b de 2 ) ( ) ( 2 ) ( ) ( 2 2 1 1 + + = + = + = υ χ ς ρ ζ χ μβ 2 2 2 dx dx a f dx a f dx x f x f B b de 2 ) 2 ( ) ( 2 ) ( ) ( 2 3 2 2 + + + = + = + = υ.. + b f dx b f x f x f B b N N ) ( ) ( ) ( ) ( 1 + + +. dx b f dx b f dx x f x f B b de N N N 2 ) ( ) ( 2 ) ( ) ( 2 1 1 + = + = + = + + υ
Μέθοδοι Ολοκλήρωσης Συναρτήσεων Μέθοδος Τραπεζίου (2) Το συνολικό ολοκλήρωμα, θα ισουται με το άθροισμα τωνστοιχειωδών εμβαδών τραπεζίων και θα υπολογίζεται ως: E = N de1 + de2 +... + de + 1 = dx 2 ( f x ) + f ( x ) +... + f ( x )) ( f ( x ) f ( x )) = dx ( 1 2 N + 1 1 + N + 1
Μέθοδοι Ολοκλήρωσης Συναρτήσεων Μέθοδος Τραπεζίου (3) Συνάρτηση: f(x) = cos(x) () sum = 0.0; 00; for (i=0; i<n+1; ++i) sum = sum + cos(a+dx*i)*dx; sum = 0.5*dx*(cos(a)+cos(b)); ( ( ))
Τι είναι υποπρόγραμμα; Τι είναι υποπρόγραμμα,, βοηθητική η συνάρτηση, ρη η, function; Μία συνάρτηση ή υποπρόγραμμα είναι μία ανεξάρτητη και αυτόνομη ενότητα κώδικα, που γράφεται για να εκτελεί μία ορισμένη εργασία και προαιρετικά επιστρέφει μία τιμή στο πρόγραμμα που την κάλεσε. Γιατί χρησιμοποιούμε τα βοηθητικά προγράμματα; (1) Επανάληψη παρόμοιας διαδικασίας (π.χ. Το πρόγραμμα πολλαπλασιασμού και άθροισης ηςή αφαίρεσης πινάκων). ) (2) Μια διαδικασία που μπορεί αυτούσια να χρησιμοποιηθεί και σε άλλα προγράμματα. (3) Εύκολος έλεγχος του συνολικού προγράμματος. (4) Σωστότερη δομή του προγράμματος.
Ορισμός της Function στο Πρόγραμμα Ορισμός της function στο πρόγραμμα, ονομάζεται η δήλωση των σημαντικών της στοιχείων, δηλαδή του ονόματός της, των παραμέτρων της (ορισμάτων της) και του τύπου της πιθανής επιστρεφόμενης τιμής της συνάρτησης Η γενική περίπτωση δήλωσης μίας συνάρτησης έχει την παρακάτω μορφή: Το όνομα_συνάρτησης πρέπει να είναι μοναδικό μέσα στο πρόγραμμα, δηλαδή να μην υπάρχει άλλη μεταβλητή ή συνάρτηση με το ίδιο όνομα Η δήλωση της συνάρτησης πρέπει να τελειώνει πάντοτε με το ελληνικό ερωτηματικό ;
Πού δηλώνουμε τη Συνάρτηση; Η δήλωση μίας συνάρτησης πρέπει να συμπεριληφθεί στην αρχή του προγράμματος (μετά τα #include ). Π.χ. οι δηλώσεις των συναρτήσεων printf(), scanf(), βρίσκονται στη βιβλιοθήκη stdio.h η οποία συμπεριλαμβάνεται στο πρόγραμμα μέσω της εντολής: #include <stdio.h>. Αντίστοιχα οι δηλώσεις των συναρτήσεων pow(), sin(), cos(), βρίσκονται στη βιβλιοθήκη math.h η οποία συμπεριλαμβάνεται στο πρόγραμμα μέσω της εντολής: #include <math.h>. Η δήλωση της συνάρτησης γίνεται πριν από τη συνάρτηση int main().
Τι επιστρέφει η συνάρτηση; Ο τύπος_επιστροφής μίας συνάρτησης καθορίζει τον τύπο δεδομένων που επιστρέφει η συνάρτηση στο πρόγραμμα, στοσημείοπουτηνκάλεσε. Ο τύπος_επιστροφής μπορεί να είναι οποιοσδήποτε τύπος δεδομένων της C, όπως int, double, δείκτης, κλπ. Ο τύπος επιστροφής void χρησιμοποιείται όταν η συνάρτηση δεν επιστρέφει κάποια τιμή.
Ορίσματα συνάρτησης Η συνάρτηση μπορεί να δεχτεί μία λίστα ορισμάτων, που χωρίζονται μεταξύ τους με κόμμα (,). Οτύποςκάθεπαραμέτρου(τύπος_παραμ_1, τύπος_παραμ_2,...) μπορεί να είναι μία οποιαδήποτε έγκυρη έκφραση της C, όπως π.χ. μία σταθερά, μία μεταβλητή, μία μαθηματική ή λογική έκφραση κλπ. Το όνομα κάθε παραμέτρου (όνομα_1, όνομα_2,...) μπορεί να είναι οποιοδήποτε έγκυρο όνομα επιλέξει ο προγραμματιστής (μόνο λατινικοι χαρακτήρες, ποτέ Ελληνικά γράμματα) Εάν η συνάρτηση δεν δέχεται παραμέτρους, τότε η λίστα παραμέτρων δηλώνεται η ρ η η χ ρ μ ρ ς, η ρ μ ρ η ως (void) ή με κενή παρένθεση (). Προτιμάται η περίπτωση του (void).
Παραδείγματα (δήλωσης) συνάρτησεων Πως αλλιώς θα μπορούσε να δηλωθεί (ως προς το όρισμα); Πως θα γραφόταν αν δεν επέστρεφε τιποτα; Αν είχε για ορίσματα δύο long float;
Σημαντικές Παρατηρήσεις Η κύρια συνάρτηση main() ενός προγράμματος στη C είναι μία συνάρτηση, επίσης. Η main() καλείται από το λειτουργικό σύστημα όταν αρχίζει η εκτέλεση του προγράμματος και τερματίζεται όταν τελειώνει η εκτέλεση του προγράμματος Η δήλωση int main() ή int main(void), σημαίνει ότι η συνάρτηση ότι δεν δέχεται παραμέτρους και επιστρέφει μία ακέραια τιμή (int). Σημαντικό σχόλιο: Το όνομα μίας συνάρτησης πρέπει να επιλέγεται με τέτοιο τρόπο, ώστε να περιγράφει όσο το δυνατόν καλύτερα τον σκοπό της Δηλαδή, αν θέλετε να δηλώσετε μία συνάρτηση που να υπολογίζει το άθροισμα κάποιων αριθμών, τότε ένα επιτυχημένο περιγραφικό όνομα θα μπορούσε να είναι το sum ή το athroisma και όχι ένα όνομα όπως function, func, test, dokimi, programma1, κλπ.
Υποπρόγραμμα συνάρτησης Το υποπρόγραμμα της συνάρτησης έπεται της επικεφαλίδας της και περιέχει τις εντολές της συνάρτησης ανάμεσα σε άγκιστρα {}, όπως συμβαίνει και στη συνάρτηση main(). Η επικεφαλίδα της συνάρτησης πρέπει να είναι ίδια με τη δήλωση της συνάρτησης, με τη διαφορά ότι δεν μπαίνει το ελληνικό ερωτηματικό στο τέλος της. Το υποπρόγραμμα της συνάρτησης εκτελείται μόνο όταν αυτή κληθεί από κάποιο σημείο του κυρίως προγράμματός μας. Όταν καλείται μία συνάρτηση, ρη η, η εκτέλεση του προγράμματος της αρχίζει με την πρώτη εντολή της και τερματίζεται είτε όταν βρεθεί μία εντολή return είτε όταν η εκτέλεση φτάσει στο άγκιστρο κλεισίματος. Το πρόγραμμα μίας συνάρτησης εισάγεται μετά το τέλος της συνάρτησης main().
Πως λειτουργεί η εντολή return σε μια συνάρτηση (1) Ηεντολήreturn χρησιμοποιείται για τον άμεσο τερματισμό μίας συνάρτησης. Όταν το πρόγραμμα της συνάρτησης φτάσει σε μία εντολή return, τότε η συνάρτηση τερματίζεται αυτομάτως ανεξάρτητα απο το αν επιστρέφει ή όχι κάτι στο κυρίως πρόγραμμα. Τι κάνει η εντολή while στο παρακάτω πρόγραμμα; Με ποιές τιμές τερματίζει το παρακάτω πρόγραμμα και γιατί; Τι εξοδο δίνει το πρόγραμμα αυτό στην οθόνη;
Πως λειτουργεί η εντολή return σε μια συνάρτηση (2) Αν η συνάρτηση δεν έχει οριστεί να επιστρέφει κάποια τιμή (δηλ. αν ο επιστρεφόμενος τύπος της είναι void ή κενό), ) τότε για να τερματίσουμε άμεσα σε κάποιο σημείο τη συνάρτηση γράφουμε απλά return; Αν, όμως, ησυνάρτηση έχει οριστεί να επιστρέφει κάποια τιμή, τότε η εντολή return πρέπει να ακολουθείται από κάποια τιμή (Τι συμβαίνει στην main();). Αυτή η τιμή επιστρέφεται στο πρόγραμμα που την κάλεσε. Ο τύπος της τιμής που επιστρέφεται πρέπει να είναι ίδιος (δηλαδή int, double, char, κλπ) με τον τύπο που ορίστηκε να επιστρέφει η συνάρτηση στη δήλωσή της, δηλαδή στο πρωτότυπό της.
Παραδείγματα συναρτήσεων (1) Τι ορίσματα έχει η συνάρτηση αυτή και τι επιστρέφει όταν την καλέσει το κυρίως πρόγραμμα; Πού τερματίζεται αυτή ησυνάρτηση, αφού ύδεν περιέχει την εντολή return; Γιατί για την παράμετρο i ορίζουμε τοντύποτης; γ η ρ μ ρ ρζ μ ης; Γιατί δεν χρειάζεται να οριστεί ο τύπος των a, b;
Παραδείγματα συναρτήσεων (2) Τι κάνει η συνάρτηση αυτή; Τι δέχεται ως όρισμα και τι επιστρέφει στο πρόγραμμα; Πού τερματίζεται η συνάρτηση αυτή;
Παραδείγματα συναρτήσεων (3) Ποιά είναι τα ορίσματα της συνάρτησης αυτής και τι επιστρέφει στο πρόγραμμα όταν τρέξει; Τι δίνει η συνάρτηση αυτή όταν τρέχει; Τι επιστρέφει στο κυρίως πρόγραμμα; Επιστρέφονται ακέραιες τιμές ΠΡΟΣΟΧΗ: δεν επιτρέπεται η επιστροφή άλλου τύπου (π.χ. δεκαδικού) Πότε σταματάει η εξέλιξη αυτού του υποπρογράμματος; μ η ξ ξη ρ γρ μμ ς; Όταν μία συνάρτηση επιστρέφει κάποια τιμή, θα πρέπει όλα τα δυνατά «μονοπάτια» της, να επιστρέφουν κάποια τιμή. Τι γίνεται όταν δεν επιστρεφουν τιμή όλες οι δυνατές διαδρομές;
Κλήση συνάρτησης Όταν καλείται μία συνάρτηση, το πρόγραμμα συνεχίζει με την εκτέλεση του κώδικα της συνάρτησης. Όταν τερματίζεται η συνάρτηση, η εκτέλεση του προγράμματος επιστρέφει στο σημείο κλήσης της συνάρτησης και συνεχίζει με την εκτέλεση της επόμενης εντολής του κυρίως προγράμματος. Μία συνάρτηση μπορεί να κληθεί όσες φορές είναι απαραίτητο για τους σκοπούς του προγράμματος (π.χ. επανάληψη παρόμοιων διαδικασιών). Όταν γίνεται η κλήση μίας συνάρτησης, ομεταγλωττιστήςδεσμεύει μνήμη για να αποθηκεύσει τις μεταβλητές που δηλώνονται στη λίστα παραμέτρων της συνάρτησης, καθώς και αυτές που δηλώνονται μέσα στο σώμα της. Αυτή η μνήμη δεσμεύεται από ένα συγκεκριμένο τμήμα μνήμης που παρέχει το λειτουργικό σύστημα στο πρόγραμμα και ονομάζεται στοίβα (stack). Η αποδέσμευση της μνήμης αυτής γίνεται αυτόματα όταν τερματιστεί η εκτέλεση της συνάρτησης.
Κλήση συνάρτησης χωρίς παραμέτρους Ηκλήση μία συνάρτησης ρη ηςπου δεν δέχεται παραμέτρους ρ σημαίνει ότι δεν της μεταβιβάζεται κάποια πληροφορία καιάρακάνεικάτιαπολύτωςσυγκεκριμένο που το επαναλαμβάνει κάθε φορά που θα κληθεί από το πρόγραμμα ή από κάποια άλλη συνάρτηση. Η κλήση μίας τέτοιας συνάρτησης γίνεται γράφοντας (μέσα στο πρόγραμμα, στο σημείο που επιθυμούμε να την καλέσουμε) το όνομά της, ακολουθούμενη από κενές παρενθέσεις.
Παράδειγμα συνάρτησης χωρίς παραμέτρους που δεν επιστρέφει τιμή Τι ορίσματα έχει και τι έξοδο δίνει η συνάρτηση αυτή; Θα δώσει διαφορετικό αποτέλεσμα κάθε φορά που θα τρέχει η συνάρτηση αυτή; Τι ακριβώς κάνει η συνάρτηση κάθε φορά που την καλούμε; Έξοδος: Call_1 In In Call_2 In In Τι αποτέλεσμα θα δώσει το πρόγραμμα όταν θα τρέξει;
Παράδειγμα συνάρτησης χωρίς παραμέτρους που επιστρέφει τιμή Τι ορίσματα έχει και τι έξοδο δίνει η συνάρτηση αυτή; Θα δώσει διαφορετικό αποτέλεσμα κάθε φορά που θα τρέχει η συνάρτηση αυτή; Τι ακριβώς κάνει η συνάρτηση κάθε φορά που την καλούμε; Τι αποτέλεσμα θα δώσει το πρόγραμμα όταν θα τρέξει; Έξοδος: Sum = 30
Κλήση συνάρτησης με παραμέτρους Η κλήση μίας συνάρτησης ρη ης που δέχεται παραμέτρους ρ σημαίνει ότι στη συνάρτηση μεταβιβάζεται πληροφορία μέσω των παραμέτρων της και άρα, ανάλογα με τις παραμέτρους αυτές δίνει (επιστρέφει στο πρόγραμμα) διαφορετικό αποτέλεσμα κάθε φορά. Η κλήση μίας τέτοιας συνάρτησης, αφού πρώτα δηλωθεί, γίνεται γράφοντας το όνομά της και μέσα σε παρενθέσεις μία λίστα παραμέτρων Το πλήθος και ο τύπος των παραμέτρων της, θα πρέπει να είναι σε απόλυτη συμφωνία με τη δήλωση της συνάρτησης. π.χ. αν μία συνάρτηση έχει δηλωθεί να έχει δύο ακέραιες παραμέτρους, τότε στην κλήση της συνάρτησης πρέπει να της διοχετεύονται υποχρεωτικά δύο ακέραιες τιμές, και όχι μία ή περισσότερες από δυο, ανεξάρτητα από το πόσες είναι μη μηδενικές. Ο μεταγλωττιστής ελέγχει αν το πλήθος και ο τύπος των παραμέτρων συμφωνούν με τη δήλωση της συνάρτησης Αν δεν υπάρχει συμφωνία είτε στο πλήθος είτε στον τύπο των παραμέτρων, ρχ μφ ή ς ρ μ ρ, τότε ενημερώνει τον προγραμματιστή με ένα λάθος μεταγλώττισης.
Παράδειγμα εκχώρησης θέσεων μνήμης
Δηλαδή... Όταν εκτελείται το προηγούμενο πρόγραμμα,, ο μεταγλωττιστής δεσμεύει 8 θέσεις μνήμης (π.χ. 100 107) για την αποθήκευση των τιμών (10 και 20) των ακέραιων μεταβλητών a και b αντίστοιχα Όταν καλείται η συνάρτηση function() ο μεταγλωττιστής δεσμεύει άλλες 8 θέσεις μνήμης (π.χ. 2000 2007) για την αποθήκευση των τιμών των ακέραιων μεταβλητών x και y Στη συνέχεια, αντιγράφει τις τιμές των παραμέτρων a και b (δηλ. 10 και 20) στις αντίστοιχες θέσεις μνήμης των μεταβλητών x και y Όπως φαίνεται λοιπόν οι διευθύνσεις μνήμης των μεταβλητών x και y είναι διαφορετικές από τις διευθύνσεις μνήμης των ακέραιων μεταβλητών a και b Ωστόσο, τα περιεχόμενα των διευθύνσεων μετά την αντιγραφή είναι τα ίδια. Η αποδέσμευση αυτής της μνήμης (π.χ. 2000 2007) γίνεται αυτόματα, όταν τερματιστεί η εκτέλεση της συνάρτησης function() Πάντα ακολουθείται αυτή η διαδικασία;
Μεταβίβαση παραμέτρων σε συνάρτηση Δύο είναι οι διαφορετικοί τρόποι μεταβίβασης παραμέτρων σε μία συνάρτηση Κλήση μέσω τιμής (call by value) Κλήση μέσω αναφοράς (call by reference)
Κλήση συνάρτησης μέσω τιμής (call by value) Όταν γίνεται κλήση συνάρτησης μέσω τιμής, τότε στη συνάρτηση διοχετεύονται οι τιμές των παραμέτρων του προγράμματος που την καλεί. Οποιαδήποτε αλλαγή γίνει στις τιμές των παραμέτρων μέσα στο σώμα της συνάρτησης δεν επηρεάζει τις τιμές των αντίστοιχων παραμέτρων που διοχετεύθηκαν στη συνάρτηση απο το κυρίως πρόγραμμα, γιατί οι τυχόν αλλαγές γίνονται σε διαφορετικές διευθύνσεις μνήμης (όπως είδαμε σε προηγούμενη διαφάνεια).
Κλήση Συνάρτησης μέσω αναφοράς (call by reference) Όταν θέλουμε μία συνάρτηση να μπορεί να αλλάξει τις τιμές των παραμέτρων, τότε πρέπει να γίνει κλήση της συνάρτησης μέσω αναφοράς. Σε αυτή την περίπτωση, στη συνάρτηση διοχετεύονται οι διευθύνσεις μνήμης των παραμέτρων του προγράμματος που την καλεί και όχι οι τιμές τους (γεγονός που πραγματοποιείται κατά την κλήση μέσω τιμής). Επομένως, αφού η συνάρτηση έχει πρόσβαση στις διευθύνσεις των παραμέτρων του προγράμματος που την κάλεσε, τότε μπορεί να μεταβάλλει τις τιμές αυτών.
Διαχείρηση μνήμης για κλήση συνάρτησης μέσω τιμής Έξοδος: Val = 10
Διαχείρηση μνήμης για κλήση συνάρτησης μέσω αναφοράς Έξοδος: Val = 20 Kαταχωρείί το i=10 το οποίο αποθηκεύεται στις διευθύνσεις 100 103. Οριζει την ptr ως τη διεύθυνση που έχει αποθηκευτεί το i. Στέλνει στην function(ptr) τη διεύθυνση που έχει καταχωρηθεί το περιεχόμενο του i. Aλλάζει απευθείας, το περιεχόμενο, στην function.
Παράδειγμα διαχείρησης μνήμης για κλήση συνάρτησης μέσω τιμής και μέσω αναφοράς Έξοδος: 300 200 ιεύθυνση Περιεχόμενο Μνήμης Μνήμης 152 153 154 155 156 157 158 0 0 0 100 0 0 0 159 200.. 2000 0 2001 0 2002 0 2003 2004 0 2005 0 2006 0 2007.. RAM 152 200
Παραδείγματα (1) Οι κλήσεις των συναρτήσεων scanf() και printf() με ποιον από τους δύο τρόπους κλήσης μίας συνάρτησης γίνονται στο παρακάτω παράδειγμα; Απάντηση: άτηση scanf(): κλήση μέσω αναφοράς (αφού διαβιβάζεται η διεύθυνση μίας μεταβλητής) printf(): κλήση μέσω τιμής (αφού p () ή η μ μής ( φ διαβιβάζεται η τιμή μίας μεταβλητής)
Παραδείγματα (2) Δημιουργήστε μία συνάρτηση που να δέχεται σαν παράμετρο έναν πραγματικό αριθμό και να επιστρέφει το εμβαδό του αντίστοιχου κύκλου. Στη συνέχεια γράψτε ένα πρόγραμμα το οποίο να διαβάζει το μήκος της ακτίνας και να εμφανίζει το εμβαδό του κύκλου με χρήση της προηγούμενης συνάρτησης
Παραδείγματα (3) Δημιουργήστε μία συνάρτηση που να δέχεται σαν παράμετρο έναν ακέραιο αριθμό και έναν χαρακτήρα και να εμφανίζει τον χαρακτήρα τόσες φορές όσες και η τιμή του ακεραίου Στη συνέχεια γράψτε ένα πρόγραμμα το οποίο να διαβάζει έναν ακέραιο αριθμό και έναν χαρακτήρα και να εμφανίζει τον χαρακτήρα τόσες φορές όσο και ο ακέραιος (με χρήση της συνάρτησης)
Παραδείγματα (4) Ποια είναι η έξοδος του παρακάτω προγράμματος; Έξοδος: 13
Παραδείγματα (5) Δημιουργήστε μία συνάρτηση που να δέχεται σαν παράμετρο έναν ακέραιο αριθμό (n) και να επιστρέφει την τιμή της παράστασης: 1 3 + 2 3 + 3 3 +... + n 3 Στη συνέχεια γράψτε ένα πρόγραμμα το οποίο να διαβάζει έναν θετικό ακέραιο αριθμό μέχρι 1000 και να εμφανίζει την τιμή της παραπάνω παράστασης με χρήση της συνάρτησης
Εμβέλεια Μεταβλητών Κάθε μεταβλητή που δηλώνεται σε ένα πρόγραμμα (π.χ. χ απλή μεταβλητή, πίνακας, δείκτης, δομή,...) αποκτά μία εμβέλεια μέσα σε αυτό Οό όρος εμβέλεια αναφέρεται στο κατά πόσο τα διαφορετικά τμήματα του προγράμματος έχουν πρόσβαση σε αυτή τη μεταβλητή Τα διαφορετικά είδη μεταβλητών βάσει της εμβέλειάς των είναι: Οι καθολικές μεταβλητές (global variables) Οι τοπικές μεταβλητές ς( (local variables)
Καθολικές Μεταβλητές (global) Μία μεταβλητή που δηλώνεται έξω από οποιαδήποτε συνάρτηση ονομάζεται καθολική (global) μεταβλητή Η εμβέλεια μίας καθολικής μεταβλητής εκτείνεται σε όλο το πρόγραμμα Αυτό σημαίνει ότι όλες οι συναρτήσεις του προγράμματος έχουν πρόσβαση σε αυτή τη μεταβλητή, άρα μπορούν να τροποποιήσουν την τιμή της
Σχόλια... Να δηλώνετε μία μεταβλητή σαν καθολική, μόνο όταν οι περισσότερες συναρτήσεις του προγράμματός σας πρέπει να τη χρησιμοποιούν. Το όνομα μίας καθολικής μεταβλητής πρέπει να επιλέγεται, έτσι ώστε ναπεριγράφειόσοτοδυνατόν καλύτερα τον σκοπό της. Να δίνετε αρχική τιμή (να κάνετε δηλ. ρητή Να δίνετε αρχική τιμή (να κάνετε δηλ. ρητή αρχικοποίηση) σε μία καθολική μεταβλητή, αμέσως όταν τη δηλώνετε
Παράδειγμα 1 Ποια είναι η έξοδος του παρακάτω προγράμματος??? Έξοδος: Value = 1 Value = 10 Value = 20
Παράδειγμα 2 Ποια είναι η έξοδος του παρακάτω προγράμματος??? Έξοδος: Ι test = 200 ξ ς _ I_main = 10
Παράδειγμα 3 Ποια είναι η έξοδος του παρακάτω προγράμματος??? Έξοδος: Values: 100 100
Αναδρομική Συνάρτηση 1 Αν ο χρήστης πληκτρολογήσει 3: Έξοδος: val = 1 val = 2 val = 3 Διότι, όταν μία συνάρτηση καλεί τον εαυτό της, οι επόμενες εντολές του σώματός της καθώς και οι τιμές των εμπλεκόμενων μεταβλητών (οι οποίες αποθηκεύονται) ) παραμένουν στη μνήμη. Όταν η συνάρτηση σταματήσει να καλεί τον εαυτό της, οι αποθηκευμένες εντολές εκτελούνται με αντίστροφη σειρά (δηλ. από την τελευταία προς την πρώτη)
Αναδρομική Συνάρτηση 2 Γράψτε ένα πρόγραμμα το οποίο να διαβάζει έναν ακέραιο αριθμό (n) και να εμφανίζει το παραγοντικό του (n!) με χρήση αντίστοιχης αναδρομικής συνάρτησης
Παράδειγμα 1 #include <stdio.h> if(dia==0) #include <math.h> { int main() p12 = ( b)/(2*a); { printf( p1 = p2 = %lf\n,p12); double a, b, c, p1, p2, p12; } double p1re, p1im, p2re, p2im, dia; if(dia<0) { printf( Dwste tis times twn: a b c\n ); p1re = ( b)/(2*a); scanf( %lf %lf %lf, &a, &b, &c); p2re = ( b)/(2*a); dia = b*b 4*a*c; p1im = (sqrt( dia))/(2*a); p2im = (sqrt( dia))/(2*a); ) if(dia>0) printf( p1 = %lf + i%lf\n, p1re, p1im); { printf( p2 = %lf + i%lf \n, p2re, p2im); p1 = ( b + sqrt(dia))/(2*a); a); } p2 = ( b sqrt(dia))/(2*a); printf( p1 = %lf kai p2 = %lf\n,p1,p2); return 0; } }
Παράδειγμα 2 #include <stdio.h> double fun(double x1) double fun(double); { int main() double f1, f2, f3, f4; { f1 = x1*x1*x1; double a1; f2 = x1*x1; printf( Dvse enan arithmo ); f3 = x1 + 4; scanf( %lf,&a1); f4 = f1 + f2 + f3; printf( f(%lf) = %lf, a1, return f4; fun(a1)); } return 0; }
#include <stdio.h> int paragontiko(int); int main() { int n, k, ar, par1, par2, res; printf( Dvse ton arithmo twn stoixeiwn (n) ); scanf( %d,&n); printf( Dvse ton arithmo twn thesewn (k) ); Παράδειγμα 3 scanf( %d,&k); ar = paragontiko(n); par1= paragontiko(k); par2 = paragontiko(n k); res = ar/(par1*par2); par2); printf( (%d ana %d) = %d, n, k, res); return 0; }
#include <stdio.h> int paragontiko(int); int main() { int n, k, ar, par1, par2, res; printf( Dvse ton arithmo twn stoixeiwn (n) ); scanf( %d,&n); printf( Dvse ton arithmo twn thesewn (k) ); Παράδειγμα 3 scanf( %d,&k); ar = paragontiko(n); par1= paragontiko(k); par2 = paragontiko(n k); res = ar/(par1*par2); par2); printf( (%d ana %d) = %d, n, k, res); return 0; } Η σχέση αυτή υπολογίζει το πλήθος n n n!! των δυνατών συνδυασμών που = μπορούν να τοποθετηθούν n k k!( n k)! αντικείμενα σε k συγκεκριμένες θέσεις
Παράδειγμα 4 #include <stdio.h> nk1 = 0; int paragontiko(int); int n_ana_k(int,int); int main() { int n, k, ar, par1, par2, res; printf( n=? ); scanf( %d,&n); printf( k=? ); scanf( %d,&k); printf( (%d ana %d) = %d, n, k, n_ana_k(n, k)); return 0; } int n_ana_k (int n1, int k1) { int nk1; if (k1>n1) else nk1 = paragontiko(n)/( paragontiko(k)* paragontiko(n k)); return nk1; } int paragontiko(int t x1) { int i,f1=1; if (x1>1) for (i=1; i<=x1; i++) f1 = f1*i; return f1; }