Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε

HY100 : ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΕΠΙΣΤΗΜΗ ΥΠΟΛΟΓΙΣΤΩΝ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ, ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ, ΤΜΗΜΑ ΕΠΙΣΤΗΜΗΣ ΥΠΟΛΟΓΙΣΤΩΝ ΔΙΔΑΣΚΟΝΤΕΣ Αντώνιος Σαββίδης, Χρήστος.

Παρόμοιες παρουσιάσεις


Παρουσίαση με θέμα: "HY100 : ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΕΠΙΣΤΗΜΗ ΥΠΟΛΟΓΙΣΤΩΝ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ, ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ, ΤΜΗΜΑ ΕΠΙΣΤΗΜΗΣ ΥΠΟΛΟΓΙΣΤΩΝ ΔΙΔΑΣΚΟΝΤΕΣ Αντώνιος Σαββίδης, Χρήστος."— Μεταγράφημα παρουσίασης:

1 HY100 : ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΕΠΙΣΤΗΜΗ ΥΠΟΛΟΓΙΣΤΩΝ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ, ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ, ΤΜΗΜΑ ΕΠΙΣΤΗΜΗΣ ΥΠΟΛΟΓΙΣΤΩΝ ΔΙΔΑΣΚΟΝΤΕΣ Αντώνιος Σαββίδης, Χρήστος Νικολάου

2 ΕΝΟΤΗΤΑ Ι ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ Διάλεξη 7η

3 Περιεχόμενα Υποπρογράμματα Επιπλέον παραδείγματα

4 Υποπρογράμματα (1/21) Η πρακτική ανάγκη –Όταν έχουμε κατασκευάσει κάποια προγράμματα που λύνουν κάποια συγκεκριμένα ανεξάρτητα προβλήματα π.χ. εύρεση μέσου όρου, υπολογισμός απόλυτης τιμής, λύση τριωνύμου, κλπ., –θα θέλαμε να μπορούμε να τα χρησιμοποιούμε σε πιο πολύπλοκα προγράμματα, χωρίς όμως κάθε φορά να ξαναγράφουμε τον κώδικά τους –αλλά να μπορούμε να τα χρησιμοποιούμε ως προϋπάρχοντα υποπρογράμματα, με κάποιο απλό εκφραστικά τρόπο όπως, π.χ., τις βασικές συναρτήσεις του υπηρέτη sqr, sqrt, INPUT, POISITIONOF, cos, sin, κλπ.

5 Υποπρογράμματα (2/21) Οι πρώτες διαφοροποιήσεις –Εάν, με κάποιο τρόπο καταφέρουμε να έχουμε ένα υποπρόγραμμα έστω αυτό του υπολογισμού της απόλυτης τιμής –θα θέλαμε να το χρησιμοποιούμε στο πρόγραμμά μας σαν να ήταν μία εγγενής μαθηματική συνάρτηση, π.χ. ονομαζόμενη abs abs(x), abs(cos(x) + sin(y)), κλπ. –Τότε, στο υποπρόγραμμα της απόλυτης τιμής, δεν θα θέλαμε η μεταβλητή x να διαβάζεται από την είσοδο αλλά να μπορεί το εκάστοτε πρόγραμμα που χρησιμοποιεί την απόλυτη τιμή να δίνει την τιμή του x ως παράμετρο κλήσης στη συνάρτηση παρόμοια με τις εγγενείς μαθηματικές συναρτήσεις και επίσης, να μπορεί να παραλαμβάνει το αποτέλεσμα, όχι από την έξοδο, αλλά με κάποιο άλλο τρόπο ως επιστρεφόμενο αποτέλεσμα κλήσης –π.χ. να μπορούμε να γράφουμε y = sqrt(x);

6 Υποπρογράμματα (3/21) Τα υποπρογράμματα είναι δύο τύπων: –Αυτά που επιστρέφουν κάποιο αποτέλεσμα μετά τη διεργασία που επιτελούν, όπως η sqrt και sqr Αυτά ονομάζονται συναρτήσεις – functions –Αυτά που δεν επιστρέφουν κάποιο αποτέλεσμα, απλώς επιτελούν κάποια συγκεκριμένη χρήσιμη διεργασία, όπως η INPUT και OUTPUT Αυτά ονομάζονται διαδικασίες - procedures

7 Υποπρογράμματα (4/21) Τρόπος περιγραφής στη γλώσσα flip PΡOCEDURE Name ARGUMENTS ( T 1 a 1,..., T n a n ) BEGIN Εντολές END FUNCTION(Τύπος) Name ARGUMENTS ( T 1 a 1,..., T n a n ) BEGIN Εντολές END Επικεφαλίδα υποπρογράμματος

8 Υποπρογράμματα (5/21) Στην περίπτωση των υποπρογραμμάτων-συναρτήσεων υποστηρίζεται η εντολή RESULT (έκφραση) την οποία εκτελεί ο υπηρέτης ως εξής: –Υπολογίζει την τιμή της έκφρασης, η οποία θα πρέπει να είναι του ίδιου τύπου με τον επιστρεφόμενο τύπο της συνάρτησης –Διακόπτει την εκτέλεση του υποπρογράμματος ενώ θεωρεί ως αποτέλεσμα της καλούμενης συνάρτησης την υπολογιζόμενη τιμή της έκφρασης Στην περίπτωση υποπρογραμμάτων-διαδικασιών υποστηρίζεται η εντολή FINISH την οποία εκτελεί ο υπηρέτης ως εξής: –Διακόπτει την απευθείας εκτέλεση του υποπρογράμματος Και στις δύο περιπτώσεις ο υπηρέτης επιστρέφει τον έλεγχο εκτέλεσης ακριβώς στο σημείο κλήσης

9 Υποπρογράμματα (6/21) Ορισμένοι βασικοί κανόνες (1/2) –Τα υποπρογράμματα ορίζονται πάντα σε χώρο καθολικής εμβέλειας, δηλ. εκεί που ορίζονται και οι καθολικές μεταβλητές (πριν το PROGRAM_BEGIN) –Δεν επιτρέπεται ορισμός υποπρογραμμάτων μέσα σε ένα υποπρόγραμμα –Δεν επιτρέπονται δύο υποπρογράμματα με το ίδιο όνομα –Οι μεταβλητές που ορίζονται στο χώρο (block) ενός υποπρογράμματος δεν είναι «ορατές» εκτός αυτού του χώρου –Σε ένα υποπρόγραμμα μπορούν να χρησιμοποιούνται καθολικές μεταβλητές, αρκεί αυτές να δηλώνονται πριν τον ορισμό του υποπρογράμματος

10 Υποπρογράμματα (7/21) Ορισμένοι βασικοί κανόνες (2/2) –Τα ονόματα μεταβλητών, τύπων της FLIP, λέξεων κλειδιών, τύπων που ορίζετε εσείς και ονομάτων υποπρογραμμάτων δεν μπορούν να είναι τα ίδια (πρέπει να «ξεχωρίζουν» με κάποιο τρόπο) –Σε ένα υποπρόγραμμα μπορούν να χρησιμοποιούνται άλλα υποπρογράμματα (τουλάχιστον αυτά που ορίζονται πιο πριν, αλλά θα δούμε και άλλες περιπτώσεις) –Σε ένα υποπρόγραμμα μπορείτε να χρησιμοποιήσετε τύπους RECORD που έχουν οριστεί πιο πριν –Η ύπαρξη μίας FINISH δεν είναι υποχρεωτική, καθώς μία procedure τελειώνει όταν τελειώνει το block της (default exit) –Αλλά η ύπαρξη μίας RESULT είναι αναγκαία πάντα για να επιστρέφεται κάποιο αποτέλεσμα

11 Υποπρογράμματα (8/21) Παραδείγματα (1/3) FUNCTION(REAL) abs ARGUMENTS (REAL x) BEGIN IF x < 0 THEN RESULT(-x); ELSE RESULT(x); END PROGRAM_BEGIN REAL x; INPUT(x); OUTPUT(abs(x)); PROGRAM_END Υποπρόγραμμα-συνάρτηση τύπου REAL, με μία παράμετρο τύπου REAL και όνομα abs. Τι γίνεται εάν δεν βάλουμε αυτό το ELSE; Πως συμπεριφέρεται τώρα το υποπρόγραμμα

12 Υποπρογράμματα (9/21) Παραδείγματα (2/3) PROCEDURE print ARGUMENTS (ADDRESSEX(INTEGER) p, INTEGER n) BEGIN WHILE n > 0 DO BEGIN OUTPUT(CONTENTOFEX(p)); p = p + 1; n = n - 1; END PROGRAM_BEGIN ARRAY(INTEGER, 5) p; ADDRESSEX(INTEGER) d = p; INPUT(p); print(d, 5); PROGRAM_END Χρησιμοποιούμε τις μεταβλητές διευθύνσεων τετραδίου για συγκεκριμένους τύπους ADDRESSEX Εναλλακτικά, χωρίς μεταβλητή ADDRESSEX

13 Υποπρογράμματα (10/21) Παραδείγματα (3/3) FUNCTION(REAL) sum ARGUMENTS (ADDRESSEX(REAL) p, INTEGER n) BEGIN REAL s; FOR s = 0; n > 0; p = p+1, n = n-1 DO s = s + CONTENTOFEX(p); RESULT(s); END PROGRAM_BEGIN ARRAY(REAL, 5) p; INPUT(p); OUTPUT(sum(p, 5)); PROGRAM_END Μπορώ να εκχωρήσω σε μία μεταβλητή ADDRESSEX(T) μεταβλητή ARRAY(T,N). Τότε η μεταβλητή λαμβάνει την αρχική διεύθυνση του πίνακα.

14 Υποπρογράμματα (11/21) Πως διαχειρίζεται τα υποπρογράμματα ο υπηρέτης (1/4) –Διαβάζει την επικεφαλίδα του προγράμματος, «κοιτώντας» προσεκτικά όλες τις παραμέτρους Καταγράφει πόσες συνολικά συνεχόμενες σειρές τετραδίου απαιτούνται για την αποθήκευσή κάθε ξεχωριστής παραμέτρου –ώστε όταν κληθεί το υποπρόγραμμα με συγκεκριμένες τιμές στις παραμέτρους να βρίσκει συνεχόμενες ελεύθερες σειρές τετραδίου για κάθε μία από αυτές Επιπλέον, δημιουργεί έναν πίνακα του υποπρογράμματος με κάθε τέτοια παράμετρο, σημειώνοντας συμβολική αρχική θέση τετραδίου η οποία θα δίνεται στο υποπρόγραμμα κατά την κλήση του Υποπρόγραμμα sum(p,n) n, INTEGER, 1Θέση n? p, ADDRESSEX(REAL), 1 Θέση p? Προσοχή, ο υπηρέτης ψάχνει θέση για κάθε παράμετρο από την τελευταία προς την πρώτη!!!

15 Υποπρογράμματα (12/21) Πως διαχειρίζεται τα υποπρογράμματα ο υπηρέτης (2/4) –To “σώμα» ενός υποπρογράμματος είναι ουσιαστικά ένα block από εντολές και το αντιμετωπίζει ακριβώς όπως γνωρίζουμε. Απλώς κάθε αναφορά στο block σε παράμετρο του υποπρογράμματος ο υπηρέτης την αντικαθιστά χρησιμοποιώντας την συμβολική θέση της παραμέτρου, π.χ. Θέση n? –Η οποία όπως θα δούμε συγκεκριμενοποιείται σε κάθε κλήση που υποπρογράμματος, όταν δίνεται από τον υπηρέτη χώρος τετραδίου για τις παραμέτρους κλήσης FUNCTION(REAL) sum ARGUMENTS (ADDRESSEX(REAL) p, INTEGER n) BEGIN REAL s; FOR s = 0; n > 0; p = p+1, n = n-1 DO s = s + CONTENTOFEX(p); RESULT(s); END sum, Θέση p? sum, Θέση n? block 1,start1+0

16 Υποπρογράμματα (13/21) Πως διαχειρίζεται τα υποπρογράμματα ο υπηρέτης (3/4) –Τις παραμέτρους / ορίσματα του υποπρογράμματος στον ορισμό του υποπρογράμματος τις ονομάζουμε τυπικές παραμέτρους – formal arguments –Τις εκφράσεις που δίνονται ως ορίσματα / παράμετροι κατά την κλήση ενός υποπρογράμματος τις ονομάζουμε πραγματικά ορίσματα - actual arguments Ο υπηρέτης βρίσκει πρώτα ελεύθερο χώρο στο τετράδιο για την αποθήκευση της κάθε παραμέτρου, διατρέχοντας τη λίστα των πραγματικών παραμέτρων από δεξιά προς τα αριστερά –Υπολογίζοντας όμως πάντοτε πρώτα την τιμή κάθε «έκφρασης» που δίδεται ως όρισμα –Οι σειρές τετραδίου λαμβάνονται από τον ειδικό χώρο «προσωρινών» μεταβλητών (από την 150 σελίδα και πέρα). Για τα παραδείγματα και μόνο, χάριν απλότητας, θα θεωρήσουμε απλώς τις πρώτες ελεύθερες θέσεις του τετραδίου.

17 Υποπρογράμματα (14/21) Πως διαχειρίζεται τα υποπρογράμματα ο υπηρέτης (4/4) –Έπειτα «καλείται» το υποπρόγραμμα, δηλ. αρχίζει η εκτέλεσή του –Μόλις τελειώσει η εκτέλεση του υποπρογράμματος, το επιστρεφόμενο αποτέλεσμα αποθηκεύεται στην πρώτη ελεύθερη θέση του τετραδίου την οποία και «κρατάει»: –(1) είτε έως τη στιγμή που αυτό θα χρησιμοποιηθεί στην εντολή όπου γίνεται η κλήση του υποπρογράμματος, –(2) ή έως τη στιγμή που θα περατωθεί όλη η εντολή που περιλαμβάνει την κλήση του υποπρογράμματος μόνο μετά από την απελευθέρωση της μνήμης τετραδίου για το αποτέλεσμα απελευθερώνονται και οι σειρές που «κρατήθηκαν» για τις παραμέτρους και περιείχαν τις τιμές τους

18 Υποπρογράμματα (15/21) Παράδειγμα (1/4) FUNCTION(REAL) max ARGUMENTS (REAL x, REAL y) BEGIN IF x >= y THEN RESULT(x); ELSE RESULT(y); END PROGRAM_BEGIN REAL x,y; INPUT(x); INPUT(y); OUTPUT(max(x, y)); PROGRAM_END Υποπρόγραμμα max y, REALΘέση y?  (0,2) x, REALΘέση x?  (0,3) (0,0), x (0,1), y (0,2) max, y (0,3) max, x (0,4) max(x,y) programblock “max”function (0,0), x (0,1), y Ακριβώς μετά την εκτέλεση της εντολής OUTPUT

19 Υποπρογράμματα (16/21) Παράδειγμα (2/4) FUNCTION(REAL) max ARGUMENTS (REAL x, REAL y) BEGIN OUTPUT(POSITIONOF(x)); OUTPUT(POSITIONOF(y)); IF x >= y THEN RESULT(x); ELSE RESULT(y); END θέση y θέση x Βάζοντας στο πρόγραμμα εντολές για την εκτύπωση των διευθύνσεων των παραμέτρων επιβεβαιώνουμε τον κανόνα αποθήκευσης των πραγματικών παραμέτρων.

20 Υποπρογράμματα (17/21) Παράδειγμα (3/4) REAL x,y,z; INPUT(x); INPUT(y); INPUT(z); OUTPUT(max(x, max(y, z))); (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5) result (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5), max, y (0,0) x (0,1) y (0,2) z (0,3) (0,4) (0,5), max, y 1 2 33 (0,0) x (0,1) y (0,2) z (0,3), max, x (0,4) (0,5), max, y 4 (0,0) x (0,1) y (0,2) z (0,3), max, x (0,4) result (0,5), max, y 5 y z max max x 1η κλήση υποπρογράμματος 2η κλήση υποπρογράμματος OUTPUT 1 2 3 4 5 6 (0,0) x (0,1) y (0,2) z 6 Περίπτωση 1: απελευθέρωση με τη χρησιμοποίηση του αποτελέσματος (Visual Studio)

21 Υποπρογράμματα (18/21) Παράδειγμα (4/4) REAL x,y,z; INPUT(x); INPUT(y); INPUT(z); OUTPUT(max(x, max(y, z))); (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5) result (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5), max, y (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5), max, y (0,6), max, x 1 2 4 3 (0,0) x (0,1) y (0,2) z (0,3), max, y (0,4), max, x (0,5), max, y (0,6), max, x (0,7) result 5 (0,0) x (0,1) y (0,2) z y z max max x 1η κλήση υποπρογράμματος 2η κλήση υποπρογράμματος OUTPUT 1 2 3 4 5 6 6 Περίπτωση 2: απελευθέρωση με τo πέρας της συνολικής εντολής (gcc)

22 Υποπρογράμματα (19/21) max(x, max(y, z)); max(max(x,y), max(y, z)); max(max(y,z), x); max(y,z) max(x, result ) max(y,z) max(x,y) max( result2, result1 ) max(y,z) max( result, x) Περίπτωση 1 (Visual Studio) Περίπτωση 2 (gcc)

23 Υποπρογράμματα (20/21) Ο γενικός κανόνας: –Έστω συνάρτηση ή διαδικασία F(Τ 1 x 1,…, T n x n ) όπου το x j είναι ένα τυπικό όρισμα τύπου Τ j –Έστω κάποια κλήση F(e 1,…,e n ) της F με e j έκφραση του προγράμματος που αντιπροσωπεύει πραγματικό όρισμα για το x j –Η τιμή της e j πρέπει να είναι τύπου Τ j, αλλιώς η κλήση δεν είναι ορθή και έχουμε συντακτικό λάθος –Εάν πρόκειται για συνάρτηση, τότε η κλήση της συνάρτησης αντιπροσωπεύει τιμή του τύπου επιστρεφόμενου τύπου της συνάρτησης –Επομένως πρέπει η εμφάνιση της κλήσης μέσα σε έκφραση να είναι νόμιμη θεωρώντας τον συγκεκριμένο τύπο της συνάρτησης

24 Υποπρογράμματα (21/21) Ο υπηρέτης κάνει για την κλήση τα εξής: –  i: n…1, υπολογίζει την τιμή της έκφρασης e i, και έπειτα βρίσκει τόσο χώρο στο τετράδιο όσο χρειάζεται η αποθήκευση της τιμής της e i Στην συνέχεια, αντιστοιχίζει την τυπική μεταβλητή x i στην σειρά τετραδίου που δόθηκε για την αποθήκευση της τιμής της e i –Γίνεται η κλήση, με εκτέλεση του βασικού της block της συνάρτησης η διαδικασίας –Εάν πρόκειται για συνάρτηση, η τιμή του αποτελέσματος αποθηκεύεται στο πρώτο διαθέσιμο τμήμα του τετραδίου (όσο χρειάζεται ανάλογα με τον τύπο του) –Ακολουθώντας τους κανόνες εκτέλεσης των blocks, η μνήμη για τις τοπικές μεταβλητές του βασικού block προφανώς απελευθερώνεται ακριβώς με το πέρας της κλήσης –Αλλά μόνο όταν περατωθεί η εντολή στην οποία εμφανίζεται και η κλήση, θα έχει απελευθερωθεί όλος ο χώρος τετραδίου του αποτελέσματος και για τα πραγματικά ορίσματα

25 Περιεχόμενα Υποπρογράμματα Επιπλέον παραδείγματα

26 Επιπλέον παραδείγματα (1/3) Θέλουμε να υλοποιήσουμε μία διαδικασία που αλλάζει τα περιεχόμενα δύο μεταβλητών. Μας κάνει η παρακάτω συνάρτηση? ναι / όχι και γιατί? PROCEDURE swap1 ARGUMENTS (REAL x, REAL y) BEGIN REAL temp = x; x = y; y = temp; END PROGRAM_BEGIN REAL x,y; INPUT(x); INPUT(y); swap1(x, y); OUTPUT(x); OUTPUT(y); PROGRAM_END

27 Επιπλέον παραδείγματα (2/3) Οι εντολές εκχώρησης στη swap1 αλλάζουν το περιεχόμενο των σειρών που «έδωσε» ο υπηρέτης για τα πραγματικά ορίσματα –και σίγουρα όχι το περιεχόμενο των μεταβλητών x και y του προγράμματος Τότε όπως μπορώ να επηρεάσω το περιεχόμενο των μεταβλητών x, y? –Εάν χρησιμοποιήσω τη διεύθυνση του τετραδίου στην οποία αποθηκεύονται! –Έτσι θα κάνω μία swap2 η οποία αντί να δέχεται REAL σαν παραμέτρους, θα δέχεται ADDRESSEX(REAL) μέσω των οποίων θα αλλάζει το περιεχόμενο των μεταβλητών των οποίων οι διευθύνσεις δίνονται κατά τη κλήση.

28 Επιπλέον παραδείγματα (3/3) PROCEDURE swap2 ARGUMENTS (ADDRESSEX(REAL) x, ADDRESSEX(REAL) y) BEGIN REAL temp = CONTENTOFEX(x); CONTENTOFEX(x) = CONTENTOFEX(y); CONTENTOFEX(y)= temp; END PROGRAM_BEGIN REAL x, y; INPUT(x); INPUT(y); swap2(POSITIONOFEX(x), POSITIONOFEX(y)); OUTPUT(x); OUTPUT(y); PROGRAM_END (0,0) (0,1) (0,1) (0,0) (0,1) (0,1) (0,0) (0,0),x, 10 (0,1),y, 20 (0,0),x, 10 (0,1),y, 20 … (0, k), temp, 10 (0,0) (0,0),x, 20 (0,1),y, 20 … (0, k), temp, 10 (0,0),x, 20 (0,1),y, 10 … (0, k), temp, 10 1 2 3 123

29 Κατακλείδα Ένα υποπρόγραμμα ενδέχεται να χρησιμοποιεί καθολικές μεταβλητές τις οποίες ενδέχεται και να τις αλλάζει –Εάν τις αλλάζει, λέμε ότι το υποπρόγραμμα έχει «πλάγια αποτελέσματα» - side effects Ένα υποπρόγραμμα μπορεί να προκαλεί side effects και χωρίς να χρησιμοποιεί καθολικές μεταβλητές! –Αρκεί να έχει παραμέτρους τύπου διεύθυνσης, μέσω των οποίων μπορεί και αλλάζει το περιεχόμενο άλλων μεταβλητών του προγράμματος! –Ή απλώς να καλεί ένα άλλο υποπρόγραμμα που προκαλεί side effects Κανόνας: εάν μπορούμε να υλοποιήσουμε ένα υποπρόγραμμα με τρόπο που δεν προκαλεί side effects, τότε πάντοτε προτιμάμε αυτή την υλοποίηση


Κατέβασμα ppt "HY100 : ΕΙΣΑΓΩΓΗ ΣΤΗΝ ΕΠΙΣΤΗΜΗ ΥΠΟΛΟΓΙΣΤΩΝ ΠΑΝΕΠΙΣΤΗΜΙΟ ΚΡΗΤΗΣ, ΣΧΟΛΗ ΘΕΤΙΚΩΝ ΕΠΙΣΤΗΜΩΝ, ΤΜΗΜΑ ΕΠΙΣΤΗΜΗΣ ΥΠΟΛΟΓΙΣΤΩΝ ΔΙΔΑΣΚΟΝΤΕΣ Αντώνιος Σαββίδης, Χρήστος."

Παρόμοιες παρουσιάσεις


Διαφημίσεις Google