ΤΟ ΑΣΧΗΜΟΠΑΠΟ ΠΟΥ ΕΓΙΝΕ ΚΥΚΝΟΣ



Σχετικά έγγραφα
ΡΑΣΤΗΡΙΟΤΗΤΕΣ ΓΙΑ ΤΟ ΑΣΟΣ: Ο ΗΓΟΣ ΓΙΑ ΤΟΝ ΕΚΠΑΙ ΕΥΤΙΚΟ

3. Έντυποι γενικοί όροι συναλλαγών εκτυπώνονται ευανάγνωστα σε εµφανές µέρος του εγγράφου της σύµβασης.

Επίσηµη Εφηµερίδα αριθ. L 261 της 06/08/2004 σ

Ευαγγελινή Αθανασοπούλου Κωνσταντία Λαδοπούλου Στέλλα Χαριτάκη

Ο ΝΟΜΟΣ 1963/91 ΓΙΑ ΤΗΝ Ι ΡΥΣΗ ΚΑΙ ΛΕΙΤΟΥΡΓΙΑ ΤΩΝ ΦΑΡΜΑΚΕΙΩΝ (ΝΟΜΟΣ 1963/91 ΦΕΚ. ΤΡΟΠΟΠΟΙΗΣΗ ΚΑΙ ΣΥΜΠΛΗΡΩΣΗ ΤΗΣ ΦΑΡΜΑΚΕΥΤΙΚΗΣ ΝΟΜΟΘΕΣΙΑΣ ΚΑΙ ΑΛΛΕΣ

1ο ΕΠΑΛ ΑΜΑΛΙΑ ΑΣ ΠΥΡΚΑΓΙΕΣ ΗΛΕΙΑΣ ΠΑΡΟΥΣΙΑ ΚΑΙ ΡΑΣΗ ΤΟΥ ΠΥΡΟΣΒΕΣΤΙΚΟΥ ΣΩΜΑΤΟΣ ΣΤΗΝ ΗΛΕΙΑ ΣΧΟΛ.ΕΤΟΣ Ο ΤΕΤΡΑΜΗΝΟ


ΣΥΝΑΣΠΙΣΜΟΣ ΡΙΖΟΣΠΑΣΤΙΚΗΣ ΑΡΙΣΤΕΡΑΣ ΟΜΙΛΙΑ ΤΟΥ ΠΡΟΕ ΡΟΥ ΤΟΥ ΣΥΡΙΖΑ, ΑΛΕΞΗ ΤΣΙΠΡΑ ΣΤΗΝ ΕΤΗΣΙΑ ΓΕΝΙΚΗ ΣΥΝΕΛΕΥΣΗ ΤΩΝ ΜΕΛΩΝ ΤΟΥ ΣΕΒ

ΑΠΟΛΟΓΙΣΜΟΣ ΕΤΟΥΣ 2013

Ο περί Προστασίας των Μισθών Νόµος του 2007 εκδίδεται µε ηµοσίευση στην Επίσηµη Εφηµερίδα της

8. ΑΝΑΠΝΕΥΣΤΙΚΑ ΠΡΟΒΛΗΜΑΤΑ ΤΟΥ ΠΡΟΩΡΟΥ ΚΑΙ ΤΟΥ ΤΕΛΕΙΟΜΗΝΟΥ ΝΕΟΓΝΟΥ

ΣΥΝΗΓΟΡΟΣ ΤΟΥ ΠΟΛΙΤΗ ΑΝΕΞΑΡΤΗΤΗ ΑΡΧΗ Κύκλος Κοινωνικής Προστασίας. ΠΟΡΙΣΜΑ (Ν. 3094/2003 Συνήγορος του Πολίτη και άλλες διατάξεις, Άρθρο 4 6)

Οµάδα κατασκευών. του Συνδέσµου Νέων της Ι.Μ..

ΥΠΟΥΡΓΟΣ: Καληµέρα σε όλους, καλή χρονιά, να είµαστε καλά, µε υγεία πάνω απ όλα, προσωπική για τον καθένα µας, συλλογική για τη χώρα µας και να

Ανάπτυξη πρώιμης αναγνωστικής ικανότητας Δρ. Ζαφειριάδης Κυριάκος Η ανάπτυξη του γραμματισμού ξεκινά ήδη από την προσχολική ηλικία, την περίοδο του

ΤΟ ΕΥ ΑΓΩΝΙΖΕΣΘΑΙ ΣΤΟ ΑΓΩΝΙΣΤΙΚΟ ΜΠΡΙΤΖ. Το ευ αγωνίζεσθαι ιαδικασία Αλέρτ Συµβάσεις και Συστήµατα

Newsletter 12/2011 ΠΕΡΙΕΧΟΜΕΝΑ Αστικό 3-136

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΔΗΜΟΣ ΗΡΩΙΚΗΣ ΠΟΛΗΣ ΝΑΟΥΣΑΣ ΠΡΟΜΗΘΕΙΑ ΤΡΟΦΙΜΩΝ ΓΙΑ ΤΙΣ ΑΝΑΓΚΕΣ ΤΩΝ ΣΥΣΣΙΤΙΩΝ ΤΟΥ

ΤΕΤΡΑΚΤΥΣ ΦΡΟΝΤΙΣΤΗΡΙΟ ΜΕΣΗΣ ΕΚΠΑΙ ΕΥΣΗΣ

ΠΙΝΑΚΑΣ ΠΕΡΙΕΧΟΜΕΝΩΝ ΣΥΝΕ ΡΙΑΣΗ ΠΑ. Τετάρτη 10 Μαρτίου 2010

ΑΝΩΤΑΤΟ ΤΕΧΝΟΛΟΓΙΚΟ ΕΚΠΑΙ ΕΥΤΙΚΟ Ι ΡΥΜΑ ΣΕΡΡΩΝ ΣΧΟΛΗ ΙΟΙΚΗΣΗΣ ΚΑΙ ΟΙΚΟΝΟΜΙΑΣ ΤΜΗΜΑ ΛΟΓΙΣΤΙΚΗΣ ΘΕΜΑ:

Η ΝΑΥΤΕΜΠΟΡΙΚΗ. Η επιστολή του Γ. Βαρουφάκη προς το Eurogroup. Τετάρτη, 25 Φεβρουαρίου 2015

Αλεξάνδρα Μελίστα/

ΝΕΟΕΛΛΗΝΙΚΗ ΛΟΓΟΤΕΧΝΙΑ ΚΑΤΕΥΘΥΝΣΗΣ Γ ΛΥΚΕΙΟΥ 19 ΜΑΪΟΥ 2010 ΚΕΙΜΕΝΟ. Γιώργου Ιωάννου. Στου Κεµάλ το Σπίτι

ΥΠΟΥΡΓΕΙΟN ΕΘΝΙΚΗΣ ΠΑΙ ΕΙΑΣ ΚΑΙ ΘΡΗΣΚΕΥΜΑΤΩΝ ΕΛΤΙΟ ΤΥΠΟΥ. Αθήνα 23 Σεπτεµβρίου 2004

για τη ριζική ανανέωση και αλλαγή της δηµοκρατικής παράταξης και του πολιτικού συστήµατος

ΜΗΝΙΑΙΑ ΕΝΗΜΕΡΩΤΙΚΗ ΕΚ ΟΣΗ ΤΟΥ ΙΕΡΟΥ ΝΑΟΥ ΑΓΙΟΥ ΠΑΝΤΕΛΕΗΜΟΝΟΣ ΡΑΠΕΤΣΩΝΑΣ. Έντυπο πνευµατικής εσωτερικής καταγραφής. Τεύχος 19ο Οκτώβριος 2008

Ευχαριστούµε πολύ, το προσωπικό του Ειδικού σχολείου Αιγάλεω, για την πολύτιµη βοήθεια που µας πρόσφεραν.

ΕNOTHTA 18 AΓΡΟΤΙΚΗ ΖΩΗ ΤΑΞΗ Β

ΕΝΩΣΗ ΕΛΛΗΝΩΝ ΕΡΕΥΝΗΤΩΝ

ΑΝΟΙΧΤΟΙ ΟΡΙΖΟΝΤΕΣ Τεύχος 1043 / Μαϊος Έλα Πνεύµα Άγιο. Στον καθένα δίνεται η φανέρωση του Πνεύµατος για κάποιο καλό.

ΚΟΙΝΗ ΥΠΟΥΡΓΙΚΗ ΑΠΟΦΑΣΗ ΟΙ ΥΠΟΥΡΓΟΙ ΚΑΙ

ΠΡΟΓΡΑΜΜΑΤΑ ΗΜΟΣΙΩΝ ΑΠΑΝΩΝ: ΚΟΙΝΩΝΙΚΗ ΑΣΦΑΛΙΣΗ ΟΙ ΑΠΑΝΕΣ ΚΟΙΝΩΝΙΚΗΣ ΑΣΦΑΛΙΣΗΣ ΣΤΗΝ ΕΛΛΑ Α

ΥΠΟΜΝΗΜΑ ΘΕΣΕΙΣ ΤΗΣ ΟΒΕΣ ΓΙΑ ΤΟ ΣΧΕΔΙΟ ΤΟΥ ΝΕΟΥ ΝΟΜΟΥ ΓΙΑ ΤΑ ΕΥΡΩΠΑΙΚΑ ΣΥΜΒΟΥΛΙΑ ΕΡΓΑΖΟΜΕΝΩΝ

ΕΠΑΝΑΠΡΟΚΗΡΥΞΗ. Αριθµ. Πρωτ.: οικ /3276

Ποσοστό στη.. του Μέτρου. Ποσό (σε ΕΥΡΩ)

ιδακτική της Χηµείας στο σχολείο - Προβλήµατα και λύσεις

Ο ρόλος του Σύγχρονου ιεπιστηµονικού Τεχνικού Πανεπιστηµίου. H Παιδεία ως θεµελιακής σηµασίας πρωτογενής αναπτυξιακή διαδικασία * 1991

ΕΙΣΗΓΗΤΙΚΗ ΕΚΘΕΣΗ ΣΤΟ ΠΡΟΣΧΕΔΙΟ ΝΟΜΟΥ «ΑΡΧΗ ΤΗΣ ΕΠΑΓΓΕΛΜΑΤΙΚΗΣ ΕΛΕΥΘΕΡΙΑΣ. ΚΑΤΑΡΓΗΣΗ ΑΔΙΚΑΙΟΛΟΓΗΤΩΝ ΠΕΡΙΟΡΙΣΜΩΝ ΣΤΗΝ ΠΡΟΣΒΑΣΗ ΚΑΙ ΑΣΚΗΣΗ ΕΠΑΓΓΕΛΜΑΤΩΝ»

1 Εισαγωγή στην Ανάλυση των Κατασκευών 1.1 Κατασκευές και δομοστατική

Οδηγίες χρήσης. Πλυντήριο πιάτων G 1173 SCVi. el - GR

ΠΕ5: Παρουσίαση Βασικών Παραµέτρων Α Επιλογής

Αλεξάνδρειο Ανώτατο Τεχνολογικό Εκπαιδευτικό Ίδρυµα Θεσσαλονίκης

ΜΙΣΘΟ ΟΣΙΑ ΞΕΝΟ ΟΧΕΙΑΚΩΝ ΕΠΙΧΕΙΡΗΣΕΩΝ

Ἀντιφωνητὴς. ΔΕΚΑΠΕΝΘΗΜΕΡΟ ΠΑΝΘΡΑΚΙΚΟ ΕΝΤΥΠΟ ΓΝΩΜΗΣ 25 ΙΟΥΝΙΟΥ 2008 ΕΤΟΣ 10ο / ΑΡ. Φ. 249 / ΤΙΜΗ 1

ΑΠΟΣΠΑΣΜΑ. Σελίδα 1 από 17 ΕΛΛΗΝΙΚΗ ΗΜΟΚΡΑΤΙΑ

ΠΕΡΙ ΓΕΝΩΝ ΚΑΙ ΔΙΑΣΤΗΜΑΤΩΝ ΤΗΣ ΒΥΖΑΝΤΙΝΗΣ ΜΟΥΣΙΚΗΣ

Περίληψη ειδικής έκθεσης «Το φαινόµενο της ρατσιστικής βίας στην Ελλάδα και η αντιµετώπισή του»

ΜΕΛΕΤΗ ΚΑΙ ΑΠΟΚΑΤΑΣΤΑΣΗ ΤΗΣ ΧΩΜΑΤΕΡΗΣ «ΑΣΤΙΜΙΤΣΙ» ΣΤΗΝ ΠΕΡΙΟΧΗ ΚΟΡΥΤΙΑΝΗΣ ΤΟΥ ΝΟΜΟY ΘΕΣΠΡΩΤΙΑΣ

ΙΑΚΗΡΥΞΗ: ΣΣΜ ΣΥΜΠΛΗΡΩΜΑ Νο 2 ΗΜΕΡΟΜΗΝΙΑ: ΑΝΤΙΚΕΙΜΕΝΟ: «ΠΡΟΜΗΘΕΙΑ ΛΑΜΤΗΡΩΝ»

«Ευζωία αγροτικών ζώων».

ΕΝΗΜΕΡΩΣΗ.Σ. Ε.Λ.Μ.Ε. ΠΡΟΤΥΠΩΝ

ΑΙΤΙΟΛΟΓΙΚΗ ΕΚΘΕΣΗ ΣΤΟ ΣΧΕ ΙΟ ΝΟΜΟΥ «για τη δίκαιη δίκη και την αντιµετώπιση φαινοµένων αρνησιδικίας» Α. ΓΕΝΙΚΟ ΜΕΡΟΣ

ΑΠΟΣΠΑΣΜΑ Από το Πρακτικό της µε αριθµό 29 ης / 09 εκεµβρίου 2011 Συνεδρίασης της Οικονοµικής Επιτροπής ήµου Καβάλας

Γενικοί Δείκτες για την Αξιολόγηση στη Συνεκπαίδευση 1

Newsletter 5/2011 ΠΕΡΙΕΧΟΜΕΝΑ Εργατικό 3-53

Επιστηµονική Επιµέλεια Κ.. Αϊβαλής Χ. Φ. Μπέλλας Α. A. Τορτοπίδης Στατιστική Ανάλυση Χ. Φ. Μπέλλας Γ. Παναγιωτίδης ISSN:

15PROC

της, την προστασία της.

Μεταπτυχιακό Πρόγραμμα Σπουδών: Κατεύθυνση Α: Αειφορική Διαχείριση Ορεινών Υδρολεκανών με Ευφυή Συστήματα και Γεωγραφικά Συστήματα Πληροφοριών

Προϋπολογισµός: Αρ. Μελέτης: Μ Ε Λ Ε Τ Η ΚΑΤΑΣΚΕΥΗ ΞΥΛΙΝΟΥ ΑΠΕ ΟΥ ΣΤΗΝ ΑΙΘΟΥΣΑ ΑΘΛΟΠΑΙ ΙΩΝ ΤΟΥ ΚΛΕΙΣΤΟΥ ΓΥΜΝΑΣΤΗΡΙΟΥ ΑΡΚΑΛΟΧΩΡΙΟΥ ΤΟΥ Ν.

Οµάδα εργασίας ΤΕΧΝΙΚΟ ΕΠΙΜΕΛΗΤΗΡΙΟ ΤΗΣ ΕΛΛΑ ΑΣ ΤΜΗΜΑ ΚΕΝΤΡΙΚΗΣ & ΥΤ. ΘΕΣΣΑΛΙΑΣ

ΚΑΝΟΝΙΣΜΟΣ (ΕΚ) αριθ. 1164/94 ΤΟΥ ΣΥΜΒΟΥΛΙΟΥ της 16ης Μαΐου 1994 για την ίδρυση του

74 η ΣΥΝΟΔΟΣ ΠΡΥΤΑΝΕΩΝ & ΠΡΟΕΔΡΩΝ Δ.Ε. ΤΩΝ ΕΛΛΗΝΙΚΩΝ ΠΑΝΕΠΙΣΤΗΜΙΩΝ Αριστοτέλειο Πανεπιστήμιο Θεσσαλονίκης Θεσσαλονίκη, Δεκεμβρίου 2013

Άσκηση και ανάπτυξη των αντιληπτικών ικανοτήτων, των βασικών κινητικών και σωµατικών. σχηµάτων.

ΠΡΟΧΕΙΡΟΣ ΙΑΓΩΝΙΣΜΟΣ. (Τύπος Γ) Για έργα προµηθειών που δηµοπρατούνται µε τη διαδικασία του πρόχειρου διαγωνισµού 1

ΕΒΔΟΜΑΔΙΑΙΟ ΔΗΜΟΣΙΟΓΡΑΦΙΚΟ ΟΡΓΑΝΟ ΤΩΝ ΣΥΜΦΕΡΟΝΤΩΝ ΤΩΝ ΚΟΡΙΝΘΙΩΝ

ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΙΓΑΙΟΥ ΜΥΤΙΛΗΝΗ: 03/04/2007 ΑΡΙΘ. ΠΡΩΤ.: 1835 ΙΑΚΗΡΥΞΗ

ΡΑΣΗ: Παράµετροι Αποτελεσµατικότητας των ιαφόρων Εργαλείων ιαχείρισης της Ενεργού Γήρανσης ΤΙΤΛΟΣ:

15PROC

Έχοντας υπόψη: 1. Τις διατάξεις όπως αυτές ισχύουν: 1.1 Του Ν. 2286/1995 (Φ.Ε.Κ. 19/Α/ ) «Προµήθειες του δηµοσίου τοµέα και ρυθµίσεις

ΘΕΜΑ ΗΜΕΡΗΣΙΑΣ ΙΑΤΑΞΗΣ: 18. ΕΓΚΡΙΣΗ ΑΝΑΝΕΩΣΗΣ ΠΑΡΑΓΩΓΙΚΩΝ Α ΕΙΩΝ ΑΡΜΟ ΙΟΤΗΤΑΣ ΗΜΟΥ Ε ΕΣΣΑΣ

ΑΡΙΘ. ΥΓ3/89292 (ΦΕΚ Β

ΘΕΜΑ: Παροχή οδηγιών για την εφαρµογή των διατάξεων (άρθρα 1 11) του ν.3259/2004 που αναφέρονται στη περαίωση εκκρεµών φορολογικών υποθέσεων.

ΕΡΓΟ: 3ο 2/θέσιο & 21ο 2/θέσιο Ολοήμερο Ν/Γ Αγρινίου, με τη μέθοδο της προκατασκευής

ΠΡΟΚΗΡΥΞΗ ΠΡΟΣΦΟΡΑΣ. Αρ. Προσφοράς: 2014/9 Τελ. Ημερομ. Υποβ. Προσφ: 3 Σεμπτεμβριου 2014

Θεωρώντας το νερό ως στοιχείο

4. Το Ν.2362/95 (ΦΕΚ 247/ ) «Περί ηµοσίου Λογιστικού ελέγχου των δαπανών του κράτους και

ισότητα στο πλαίσιο των ευρωπαϊκών συστηµάτων εκπαίδευσης και κατάρτισης», Βρυξέλλες, , COM (2006) 481 τελικό.

ΤΑ ΝΕΑ Τ Ν ΠΡΟ ΟΝΤ Ν ΕΤΑΙΡΙΚΗ ΚΟΙΝ ΝΙΚΗ ΕΥΘΥΝΗ ΠΟΛΙΤΙΣΤΙΚΑ ΜΕ ΜΙΑ ΜΑΤΙΑ ΠΟΛΙΤΙΣΤΙΚΑ ΦΙΕΡ ΜΑΤΑ ΕΤΑΙΡΙΕΣ ΟΜΙΛΟΥ ΣΤΟ ΕΠΙΚΕΝΤΡΟ. Μαζί ΣΤΟ ΕΠΙΚΕΝΤΡΟ

ΣΥΜΒΑΣΗ ΠΡΟΜΗΘΕΙΑΣ ΦΑΡΜΑΚΩΝ

(Ε. Π. Παπανούτσου, «Τα νιάτα και ο δάσκαλος», Η παιδεία Το µεγάλο µας πρόβληµα, εκδ. ωδώνη, Αθήνα 1976, σ. 250)

στοριογραφικη έρευνα περί πόλιν Ναούσικ ο ωδείο μας στην Κύπρο -Οι νέες ποικιλίες ροδακινιάς - νεκταρινιάς Ι»'4

ΕΛΛΗΝΙΚΗ ΔΗΜΟΚΡΑΤΙΑ ΝΟΜΟΣ ΕΒΡΟΥ ΔΗΜΟΣ ΣΟΥΦΛΙΟΥ ΤΕΧΝΙΚΗ ΥΠΗΡΕΣΙΑ ΑΡ.ΜΕΛ: 74/2013

3. ΠΕΡΙΓΡΑΦΙΚΟ ΤΙΜΟΛΟΓΙΟ ΜΕΛΕΤΗΣ

3. ΠΕΡΙΓΡΑΦΙΚΟ ΤΙΜΟΛΟΓΙΟ ΜΕΛΕΤΗΣ

«ΕΥΡΩΠΑΪΚΕΣ ΠΡΟΓΡΑΜΜΑΤΙΚΕΣ ΠΕΡΙΟΔΟΙ ΚΑΙ ΣΥΜΒΟΛΗ ΤΟΥΣ ΣΤΑ ΕΡΓΑ ΥΠΟΔΟΜΗΣ ΣΤΗΝ ΕΛΛΑΔΑ. ΤΙ

Αθήνα, 31 Αυγούστου2011

ΚΕΦΑΛΑΙΟ 113. Ο ΠΕΡΙ ΕΤΑΙΡΕΙΩΝ ΝΟΜΟΣ

ΠΟΛΥΤΕΧΝΕΙΟ 73. Η λάμψη της εξέγερσης είναι παντοτινή...

ΓΑΛΑΝΟΠΟΥΛΟΥ Β. ΕΣΠΟΙΝΑ Α.Μ.: ΕΦΑΡΜΟΓΕΣ ΗΜΟΣΙΟΥ ΙΚΑΙΟΥ. Ι ΑΣΚΩΝ ΚΑΘΗΓΗΤΗΣ: Ανδρέας Γ. ηµητρόπουλος. Αθήνα 2003

ΝΕΟΕΛΛΗΝΙΚΗ ΛΟΓΟΤΕΧΝΙΑ ΚΕΙΜΕΝΟ

ΙΣΤΟΡΙΚΟ ΛΕΞΙΚΟ ΕΠΙΣΤΗΜΟΝΙΚΩΝ ΟΡΩΝ

ΤΟ ΠΛΗΡΕΣ ΚΕΙΜΕΝΟ ΤΗΣ ΜΕΛΕΤΗΣ

Συντοµογραφίες ΑΕ=αρχαίος/α/ο ελληνικός/ή/ό ΓΓ=Γενετική γραµµατική ΝΕ=νές/α/ο ελληνικός/ή/ό ΠΙΕ=πρωτοϊνδοευρωπαϊκός/ή/ό

Α Α: 7 ΥΤΟΡ1Ο-Μ3Ε. ΕΛΛΗΝΙΚΗ ΗΜΟΚΡΑΤΙΑ ΥΠΟΥΡΓΕΙΟ ΥΓΕΙΑΣ ΕΛΚΕΑ ΙΟΙΚΗΣΗ 4 ης ΥΓΕΙΟΝΟΜΙΚΗΣ ΠΕΡΙΦΕΡΕΙΑΣ ΜΑΚΕ ΟΝΙΑΣ ΚΑΙ ΘΡΑΚΗΣ

ΕΙΣΑΓΩΓΗ ΘΕΜΑΤΩΝ ΓΙΑ ΤΗΝ ΠΡΟΩΘΗΣΗ ΤΗΣ ΙΣΟΤΗΤΑΣ ΤΩΝ ΦΥΛΩΝ ΣΤΗΝ ΕΚΠΑΙΔΕΥΤΙΚΗ ΔΙΑΔΙΚΑΣΙΑ ΒΟΗΘΗΤΙΚΟ ΕΚΠΑΙΔΕΥΤΙΚΟ ΥΛΙΚΟ ΓΙΑ ΤΑ ΣΧΟΛΙΚΑ ΕΓΧΕΙΡΙΔΙΑ ΜΑΘΗΜΑΤΩΝ

3. ΤΕΧΝΙΚΟ ΑΝΤΙΚΕΙΜΕΝΟ

«Σε μια ρώγα από σταφύλι» Εκπαιδευτικό Πρόγραμμα για το Αμπέλι, το Σταφύλι & το Κρασί

ΣΚΟΥΠΑ ΑΤΜΟΥ CLEANMAXX 0819 Ο ΗΓΙΕΣ ΧΡΗΣΗΣ

Transcript:

ΤΟ ΑΣΧΗΜΟΠΑΠΟ ΠΟΥ ΕΓΙΝΕ ΚΥΚΝΟΣ ή ΠΩΣ ΝΑ ΓΡΑΦΕΤΕ ΚΑΛΟ ΚΩΔΙΚΑ Βάνα Ντουφεξή Οι περισσότερες γλώσσες προγραµµατισµού επιτρέπουν στον προγραµµατιστή να διατάξει τον κώδικα όπως επιθυµεί και έχουν λίγους περιορισµούς για την ονοµασία συναρτήσεων και µεταβλητών. Οι ελάχιστες απαιτήσεις είναι το πρόγραµµα να µεταγλωττίζεται χωρίς λάθη και να λειτουργεί σωστά σύµφωνα µε τις δεδοµένες προδιαγραφές. Αυτό που πολλοί αρχάριοι προγραµµατιστές ξεχνούν είναι πως είναι εξίσου σηµαντικό το πρόγραµµα να µπορεί να συντηρηθεί (maintainable code), δηλαδή να είναι εύκολο να γίνουν διορθώσεις, βελτιώσεις, και προσθήκες νέων λειτουργιών. Υπάρχουν πολλά στοιχεία σε ένα πρόγραµµα τα οποία συντελούν στη συντηρησιµότητά του. Θα τα αναλύσουµε ένα-ένα µέσα από ένα παράδειγµα. Το παρακάτω πρόγραµµα C είναι τυπικό παράδειγµα κώδικα γραµµένου από αρχάριο προγραµµατιστή. Το πρόγραµµα είναι συντακτικά σωστό, αλλά είναι υπερβολικά δύσκολο να βρεθούν τυχόν λογικά λάθη ή να γίνουν αλλαγές. #include<stdio.h> int i; void func(int a[],int s){ int j,m; int t; for(j=0;j<s;j++) { m=j; for (i=j+1;i<s;i++) { if (a[i]<a[m]) m=i; t=a[m]; a[m]=a[j]; a[j]=t; int main(int argc,char *argv[]) { int a[10]={8,1,-2,9,0,4,3,8,5,10; func(a,10); for (i=0;i<10;i++) printf("%d ",a[i]); return 0; Μπορείτε να βρείτε τι κάνει το πρόγραµµα αυτό χωρίς να το τρέξετε?

ΔΙΑΤΑΞΗ Η διάταξη του προγράµµατος πρέπει να ακολουθεί τη λογική ροή του και να βελτιώνει την αναγνωσιµότητά του. Αυτό επιτυγχάνεται µε τη σωστή και κυρίως συνεπή χρήση κενών, κενών γραµµών, στοίχισης και οµαδοποίησης συσχετιζόµενων εντολών. Οι ίδιοι κανόνες ισχύουν για κάθε γραπτό κείµενο. Σκεφτείτεπωςθαήτανανδεχρησιµοποιούσαµεποτέκενάστ ιςπροτασειςήανδενξεχω ρίζαµετιςπαραγράφουςµεγραµµέςήανχωρίζαµετιςλ έξειςσελάθοςσυλλαβές. Στοίχιση (Indentation) Χρησιµοποιήστε στοίχιση για να δείξετε τη λογική δοµή του προγράµµατος. Κάθε εντολή πρέπει να βρίσκεται σε ξεχωριστή γραµµή. Εντολές που υπάγονται στο σώµα µιας σύνθετης εντολής πρέπει να γράφονται ένα tab πιο µέσα από την εντολή στην οποία υπάγονται. Το πιο αποτελεσµατικό µέγεθος για το tab είναι 4 κενά. Υπάρχουν δύο δηµοφιλείς τρόποι τοποθέτησης των αγκίστρων που εσωκλείουν µια οµάδα εντολών: Μέθοδος 1: Το αριστερό άγκιστρο βρίσκεται στην ίδια στήλη µε την αρχή της σύνθετης εντολής, στην ακριβώς επόµενη γραµµή. Το δεξί άγκιστρο βρίσκεται στην ίδια στήλη µε το αριστερό, σε ξεχωριστή γραµµή που δεν περιλαµβάνει τίποτα άλλο. Μέθοδος 2: Το αριστερό άγκιστρο βρίσκεται στην ίδια γραµµή µε τη σύνθετη εντολή. Το δεξί άγκιστρο βρίσκεται στην ίδια στήλη µε την αρχή της σύνθετης εντολής, σε ξεχωριστή γραµµή που δεν περιλαµβάνει τίποτα άλλο. Και οι δύο µέθοδοι είναι εξίσου αποδεκτές. Μπορείτε να χρησιµοποιήσετε όποια σας αρέσει αλλά είναι σηµαντικό να είστε συνεπείς στην επιλογή σας και να µην αλλάζετε µέθοδο στα µέσα του προγράµµατος. Συµβουλή: Είναι καλή ιδέα να χρησιµοποιείτε άγκιστρα για το σώµα σύνθετων εντολών ακόµη κι αν το σώµα αποτελείται από µία µόνο εντολή. Ο λόγος είναι ότι µειώνεται η πιθανότητα να γίνει κάποιο λάθος αν αργότερα προστεθούν επιπλέον εντολές στο σώµα. for (i=0; i<10; i++) { printf("%d ", i); if (size>5) printf("too big"); Μέθοδος 1 for (i=0; i<10; i++) { printf("%d ", i); if (size>5) printf("too big"); Μέθοδος 2 for (i=0; i<10; i++) { printf("%d ", i); if (size>5) printf("too big");

for (id = 0; id < 10; id++) { printf("%d", grade[id]); if (grade[id] >= 5) printf("pass"); printf("\n"); for (id = 0; id < 10; id++) { printf("%d", grade[id]); if (grade[id] >= 5) printf("pass"); printf("\n"); Ακολουθώντας τη συµβουλή: for (id = 0; id < 10; id++) { printf("%d", grade[id]); if (grade[id] >= 5) { printf("pass"); printf("\n"); switch(trafficlights[i]) { case RED: stop(cars); break; case AMBER: move_forward(cars, 1); stop(cars, 2); break; case GREEN: move_forward(cars); break; switch(trafficlights[i]) { case RED: stop(cars); break; case AMBER: move_forward(cars, 1); stop(cars, 2); break; case GREEN: move_forward(cars); break; Κενά Αφήνετε κενά ανάµεσα σε αναγνωριστικά (identifiers). Σε πολύπλοκες εκφράσεις, είναι συχνά καλό να αφήνετε κενό ανάµεσα σε ένα τελεστή (operator) και τελεσταίους (operands). Σε εντολές for αφήνετε πάντα κενό ανάµεσα στην αρχικοποίηση, έλεγχο τερµατισµού και ανανέωση µετρητή. tomorrow=today+1; tomorrow = today + 1; x=y+2*z-5; x = y + 2 * z - 5; numpeople=initpeople=0; numpeople = initpeope = 0; for(i=0;i<size/2;i++) for (i=0; i < size/2 ; i++) setstudentgrades(classlist,classid,numstudents); setstudentgrades( classlist, classid, numstudents); crossword[startrow+wordlength][startcol]=black; crossword[ startrow + wordlength ][ startcol ] = BLACK;

Κενές γραµµές Αφήνετε πάντα τουλάχιστον µια κενή γραµµή ανάµεσα σε υλοποιήσεις διαφορετικών συναρτήσεων. Μπορείτε να αφήνετε µια κενή γραµµή ανάµεσα σε διαφορετικά "τµήµατα" εντός της ίδιας συνάρτησης, ακριβώς όπως θα αφήνατε κενό ανάµεσα σε παραγράφους. Για παράδειγµα, ανάµεσα στο τµήµα δήλωσης µεταβλητών και στο τµήµα εντολών, ή ανάµεσα στο κοµµάτι που διαβάζει τα δεδοµένα και το κοµµάτι που τα επεξεργάζεται. double average (int scores[], int size) { int i; sum = 0; for (i=0; i < size; i++) { sum = sum + scores[i]; return (sum/size); Αποφεύγετε να έχετε γραµµές µακρύτερες από 80 χαρακτήρες γιατί είναι πολύ δύσκολο να διαβαστούν. Αν µια έκφραση είναι πολύ µεγάλη, συνεχίστε τη στην επόµενη γραµµή. Όταν µια έκφραση συνεχίζεται στην επόµενη γραµµή κάντε το εµφανές µε το να "χωρίσετε" την έκφραση σε κάποιο τελεστή. Αν πρόκειται για συνάρτηση µε µεγάλο αριθµό ορισµάτων, µπορείτε ακόµη και να τα βάλετε ένα σε κάθε γραµµή ή να τα οµαδοποιήσετε όπως φαίνεται στο παρακάτω παράδειγµα. Εναλλακτικά, µπορείτε να βάλετε ένα \ στο τέλος της γραµµής που συνεχίζεται. Το \ όταν εµφανίζεται στο τέλος της γραµµής (δηλαδή αµέσως µετά από αυτό έχει χαρακτήρα αλλαγής γραµµής) υποδηλώνει ότι η εντολή συνεχίζεται στην επόµενη γραµµή. drawrectangle (lowerleftx, lowerlefty, length, height, slant, solidstyle, fillcolorchoice, linecolorchoice); if ( strcmp( employeename, employeedb[i] ) == 0 && employeeid == inputid && employeestatus == CURRENT) if ( strcmp( employeename, employeedb[i] ) == 0 && \ employeeid == inputid && \ employeestatus == CURRENT)

Η εφαρµογή των κανόνων διάταξης στο αρχικό παράδειγµα οδηγεί στο παρακάτω πρόγραµµα: #include<stdio.h> int i; void func(int a[], int s){ int j, m; int t; for (j = 0; j < s; j++) { m = j; for (i = j+1; i < s; i++) { if (a[i] < a[m]) { m = i; t = a[m]; a[m] = a[j]; a[j] = t; int main(int argc, char *argv[]) { int a[10]={8, 1, -2, 9, 0, 4, 3, 8, 5, 10; func(a, 10); for (i=0; i<10; i++) { printf("%d ", a[i]); return 0; Το πρόγραµµα ήδη βελτιώθηκε πολύ, αλλά είναι ακόµη δύσκολο να καταλάβει ο αναγνώστης τι ακριβώς κάνει.

ΟΝΟΜΑΤΑ ΜΕΤΑΒΛΗΤΩΝ, ΣΥΝΑΡΤΗΣΕΩΝ, ΤΥΠΩΝ Ο βασικός λόγος που προγραµµατίζουµε σε γλώσσες υψηλού επιπέδου είναι για να είναι τα προγράµµατα πιο κατανοητά από τους προγραµµατιστές και, ως αποτέλεσµα, να έχουν λιγότερα λάθη. Άρα η δουλειά του προγραµµατιστή είναι κατά µεγάλο βαθµό να επικοινωνεί αποτελεσµατικά µε ανθρώπους. Γι' αυτό είναι σηµαντικό να χρησιµοποιεί σωστό λεξιλόγιο και, φυσικά, να διατάσσει σωστά τον κώδικά του. Σωστό λεξιλόγιο στα πλαίσια του προγραµµατισµού σηµαίνει σωστή ονοµασία των ονοµάτων των µεταβλητών, συναρτήσεων και user-defined τύπων. Γενικά ονόµατα Σας δίνεται το παρακάτω κοµµάτι κώδικα µε την πληροφορία ότι υπολογίζει το νέο ποσό που χρωστά ένας πελάτης στην πιστωτική του κάρτα µε βάση το προηγούµενο ποσό και τις νέες αγορές που έκανε. x = x xx; xxx = maria + f(maria); x = x + p(x1, x) + xxx; x = x + e(x1, x); Αν τώρα σας ζητηθεί να προσθέσετε µια γραµµή η οποία εκτυπώνει στην οθόνη το συνολικό ποσό για τις νέες αγορές, ποια µεταβλητή θα χρησιµοποιήσετε? Μπορείτε να πείτε τι είναι το xx, το xxx, και τι κάνουν οι συναρτήσεις? Δείτε τώρα το ίδιο κοµµάτι κώδικα µε καλά ονόµατα µεταβλητών και συναρτήσεων. balance = balance lastpayment; monthlytotal = newpurchases + calcsalestax(newpurchases); balance = balance + calclatefee(customerid, balance) + monthlytotal; balance = balance + calcinterest(customerid, balance); Ο πιο σηµαντικός κανόνας στην ονοµασία µεταβλητών είναι ότι το όνοµα πρέπει να περιγράφει πλήρως την οντότητα που εκπροσωπεί η µεταβλητή. Αντίστοιχα, το όνοµα µιας συνάρτησης πρέπει να περιγράφει πλήρως τη λειτουργία της συνάρτησης. Έτσι, η µεταβλητή που αποθηκεύει το καθαρό ποσό νέων αγορών λέγεται newpurchases, η συνάρτηση που υπολογίζει τον τόκο λέγεται calcinterest κτλ. Παρατηρείστε ότι τα ονόµατα µεταβλητών είναι ουσιαστικά ενώ τα ονόµατα συναρτήσεων είναι ρήµατα ή ρηµατικές φράσεις. Ένας εύκολος τρόπος να βρείτε καλά ονόµατα είναι περιγράφοντας το πρόβληµα και τη λύση του σε µια παράγραφο και σηµειώνοντας τα ουσιαστικά και τα ρήµατα που χρησιµοποιήσατε. Όταν διαλέγετε το νέο όνοµα αποφύγετε να χρησιµοποιείτε συντοµογραφίες. Αν θεωρείτε ότι είναι απαραίτητη η συντόµευση του ονόµατος γιατί διαφορετικά θα είναι πολύ µακρύ, προσπαθήστε να βρείτε µια συντόµευση που κάνει φανερό το πλήρες όνοµα. Για παράδειγµα, η συνάρτηση που υπολογίζει το φόρο πωλήσεων ονοµάστηκε calcsalestax έναντι του calculatesalestax. Αποφεύγετε να χρησιµοποιείτε παρεµφερή ονόµατα είτε στη µορφή είτε στη σηµασία γιατί είναι εύκολο να τα µπερδέψετε και να χρησιµοποιήσετε το ένα στη θέση του άλλου. Για παράδειγµα, στο πρόγραµµα που υπολογίζει το νέο οφειλόµενο ποσό της πιστωτικής κάρτας, θα ήταν κακή ιδέα να χρησιµοποιούσαµε total1 και total2 για τα επιµέρους σύνολα. Εξίσου κακή ιδέα θα ήταν να χρησιµοποιήσουµε totalamount και finalamount γιατί έχουν παρόµοια σηµασία. Αποφεύγετε να χρησιµοποιείτε το γράµµα l (el) και τον αριθµό 1 (ένα) σε ονόµατα µεταβλητών γιατί είναι δύσκολο να φανεί ποιο από τα δύο έχει χρησιµοποιηθεί. Για τον ίδιο λόγο αποφεύγετε τη χρήση του 0 (µηδέν) και Ο (κεφαλαίο ο).

Κατά σύµβαση, τα ονόµατα συναρτήσεων και µεταβλητών είναι γραµµένα µε πεζούς χαρακτήρες (σε αντίθεση µε τα ονόµατα σταθερών τα οποία είναι όλα κεφαλαία). Ίσως έχετε παρατηρήσει τα πιο πολλά ονόµατα είναι σύνθετα αποτελούνται από δύο λέξεις. Είναι λοιπόν σηµαντικό να υπάρχει κάποιος τρόπος να τις ξεχωρίσουµε. Υπάρχουν δύο µέθοδοι να γίνει αυτό: Μέθοδος 1: Το πρώτο γράµµα της δεύτερης (και τρίτης, αν υπάρχει) λέξης είναι κεφαλαίο. Λέµε calcsalestax και όχι calcsalestax. Μέθοδος 2: Οι λέξεις χωρίζονται µε underscores. Λέµε calc_sales_tax και όχι calcsalestax. Διαλέξτε όποια µέθοδο προτιµάτε, αλλά να είστε συνεπείς στην επιλογή σας. Χρησιµοποιείτε πάντα την ίδια µέθοδο µέσα σε ένα πρόγραµµα. Ονόµατα µετρητών Μη χρησιµοποιείτε µεταβλητές του ενός χαρακτήρα (πχ. a, x, κτλ). Η µόνη εξαίρεση είναι η χρήση µετρητή σε for-loop που κατά κανόνα είναι i ή j ή k. Αν ο µετρητής πρόκειται να χρησιµοποιηθεί πέραν του loop, τότε ονοµάστε τον περιγραφικά, σύµφωνα µε τους συνήθεις κανόνες. Επίσης, αν έχετε εµφωλευµένα loop είναι συχνά καλύτερο να χρησιµοποιείτε καλά ονόµατα για τους µετρητές για να µη µπερδεύεστε. Για παράδειγµα: Μετρητής που θα ξαναχρησιµοποιηθεί for (wordlength = 0; word[wordlength]!= '\0'; wordlength++); for (i=0; i < SIZE; i++) { printf("%s\n", studentnames[i]); Προσωρινός µετρητής for (i=0; i < numrows; i++) { for (j=0; j < numcols; i++) { printf("%c", crossword[i][j]); Εµφωλευµένο loop που αρκεί η χρήση i, j Εµφωλευµένο loop που χρειάζεται καλά ονόµατα µετρητών for ( courseindex = 0; courseindex < numcourses; courseindex++) { for (studentid= 0; studentid < coursesize[courseindex]; studentid++) { createaccount(studentid, courseindex); Εννοείται πως δεν είναι καλή ιδέα να χρησιµοποιείτε "γενικά" ονόµατα µετρητών όπως counter ή count. Αντίθετα χρησιµοποιείστε numelements, studentid, courseindex, κτλ. Το ίδιο ισχύει και για προσωρινές µεταβλητές. Αποφεύγετε τα γενικά ονόµατα όπως temp.

Ονόµατα flag Συχνά χρειάζεστε µια boolean µεταβλητή ως "σηµαία" (flag) που δηλώνει αν κάποιο γεγονός έχει συµβεί ή όχι. Το όνοµα flag είναι κακό όνοµα µεταβλητής γιατί δεν έχει καµιά πληροφορία για το τι εκπροσωπεί (είναι σα να ονοµάζατε µια µεταβλητή data). Καλύτερα να χρησιµοποιείτε κάτι πιο αντιπροσωπευτικό όπως elementfound, fileexists, printerready, κτλ. Όπως βλέπετε όλα αυτά τα ονόµατα εκπροσωπούν ένα αληθές ή ψευδές γεγονός (fileexists: ή υπάρχει το αρχείο ή όχι). Ονόµατα δεικτών (pointers) Κατά σύµβαση, τα ονόµατα δεικτών ξεκινούν από p ή περιέχουν ptr. Για παράδειγµα, p_node, p_row, node_ptr, κτλ. Ονόµατα τύπων Κατά σύµβαση, τα ονόµατα τύπων ξεκινούν από t ή τελειώνουν σε T. Για παράδειγµα, colort, t_color, t_list, κτλ. Ονόµατα σταθερών Κατά σύµβαση, τα ονόµατα σταθερών γράφονται πάντα µε κεφαλαία. Το ίδιο ισχύει και για τιµές απαριθµήσεων (enum) #define MAX_COURSE_ID 999 #define NUM_STUDENTS 10 const int PI = 3.14159; typedef enum {RED, AMBER, GREEN t_trafficlightcolor;

Η εφαρµογή των κανόνων διάταξης και ονοµασίας στο αρχικό παράδειγµα οδηγεί στο παρακάτω πρόγραµµα: #include<stdio.h> int i; void selectionsort(int numbers[], int size){ int boundaryindex, minindex; int savedvalue; for (boundaryindex = 0; boundaryindex < size; boundaryindex++) { minindex = boundaryindex; for (i = boundaryindex + 1; i < size; i++) { if (numbers[i] < numbers[minindex]) { minindex = i; savedvalue = numbers[minindex]; numbers[minindex] = numbers[boundaryindex]; numbers[boundaryindex] = savedvalue; int main(int argc, char *argv[]) { int numbers[10] = {8, 1, -2, 9, 0, 4, 3, 8, 5, 10; selectionsort(numbers, 10); for (i=0; i<10; i++) { printf("%d ", numbers[i]); return 0; Είναι πια φανερό τι κάνει η συνάρτηση: χρησιµοποιεί τον αλγόριθµο selection sort για να ταξινοµήσει τα στοιχεία ενός πίνακα ακεραίων. Ακόµα όµως το πρόγραµµα χρειάζεται βελτίωση. Παρόλο που ο κώδικας είναι αρκετά "καθαρός", λείπουν πληροφορίες για το πώς ακριβώς έχει υλοποιηθεί ο αλγόριθµος και πώς επιδρά στον πίνακα ακεραίων.

ΣΧΟΛΙΑ Κάποιοι προγραµµατιστές θεωρούν ότι τα σχόλια είναι περιττά όταν ο κώδικας έχει σωστή διάταξη και καλά ονόµατα. Υποστηρίζουν ότι ο καλός κώδικας είναι self-documenting, δηλαδή ό,τι χρειάζεται να ξέρεις είναι ήδη µέσα στον κώδικα. Άλλοι, ανάµεσά τους κι εµείς, υποστηρίζουν ότι τα σχόλια είναι απαραίτητα για την κατανόηση του κώδικα από αυτούς που προσπαθούν να τον διορθώσουν ή µεταβάλλουν. Όλοι πάντως συµφωνούν ότι κακογραµµένα σχόλια είναι χειρότερα από καθόλου σχόλια. Ας δούµε λοιπόν πώς πρέπει να γράφει κανείς σχόλια σε κώδικα. Συγκεκριµένες προδιαγραφές για τη σύνταξη και το περιεχόµενο σχολίων στα προγράµµατα του Προγραµµατισµού 1 θα σας δοθούν σε φυλλάδια του εργαστηρίου. Τα σχόλια πρέπει να είναι συνοπτικά και να εξηγούν το σκοπό ενός κοµµατιού κώδικα. Δεν πρέπει να επαναλαµβάνουν αυτό που κάνει κάθε εντολή. Δεν πρέπει να ξεχνάµε ότι τα σχόλια απευθύνονται σε άλλους προγραµµατιστές. Όλοι καταλαβαίνουν ότι έκφραση row++ αυξάνει τη µεταβλητή row κατά ένα. Αλλά τι ακριβώς σηµαίνει αυτό? Ποιος είναι ο σκοπός του? Μπορεί, για παράδειγµα να είναι µέρος µιας συνάρτησης που µετακινεί τον παίκτη ενός παιχνιδιού και να σηµαίνει ότι ο παίκτης µετακινήθηκε µια θέση δεξιά. Αυτό είναι που πρέπει να γραφτεί στο σχόλιο, όχι το γεγονός ότι αυξήθηκε µια µεταβλητή. /* set product to num */ product = num; /* Raise the integer 'num' to the power 'power' and print the result */ /* loop from 2 to power */ for (i = 2; i <= power; i++) { /* multiply num by product */ product = product * num; /* print the result */ printf("product = %d\n", product); product = num; for (i = 2; i <= power; i++) { product = product * num; printf("product = %d\n", product); (παράδειγµα από εργασία χειµ. 2007) /*H sygkekrimenh synarthsh pairnei ws orisma enan deikth. Se ayth th synarthsh elegxoyme an to c einai iso me 0 kai an symbainei ayto tote den yparxei xarakthras. An twra to c einai iso me A-Z tote to metatrepei se mikro xarakthra pairnwntas ton ASCII kwdiko toys kai to kataxwrei sto s[i].*/ /* Η συνάρτηση αυτή παίρνει µια συµβολοσειρά και µετατρέπει όλα τα κεφαλαία γράµµατά της σε µικρά */ (Δε θα σχολιάσουµε εδώ το αν ο κώδικας είναι καλογραµµένος ή σωστός) void lower(char *s) { int i; for (i=0; 1; i+=1) { char c=s[i]; if (c==0) break; if (c>='a' && c<='z') s[i]=c+'a'-'a';

ΣΙΓΟΥΡΑ /* if the student flag is zero */ if (studentflag == 0) {... /* if the student is new */ if (studentflag == 0) {... /* create a new student account */ if (studentstatus == NEW) {... Παρατηρείστε πως στο τελευταίο παράδειγµα αλλάξαµε το όνοµα και τύπο της µεταβλητής. Αντί να χρησιµοποιήσουµε ένα απλό flag χρησιµοποιήσαµε µια απαρίθµηση (enum). Τώρα ο κώδικας είναι πιο καθαρός, δε χρειάζεται να αναρωτιόµαστε τι αντιπροσωπεύει η µεταβλητή studentflag ούτε τι ακριβώς σηµαίνει να έχει την τιµή µηδέν. Το studentstatus είναι η κατάσταση φοίτησης του εν λόγω φοιτητή και οι δυνατές τιµές του είναι για παράδειγµα {NEW, CURRENT, FORMER. Είναι σηµαντικό να επαναλάβουµε ότι τα σχόλια πρέπει να εξηγούν το σκοπό ενός κοµµατιού κώδικα κι όχι απλά να δίνουν µια περίληψη του τι κάνει. Πολλές φορές, τα σχόλια περιέχουν πληροφορίες που δεν είναι προφανείς αν κανείς απλά διαβάζει τον κώδικα. /* check each character in "password" until you find a $ or a @ or until all characters have been checked. */ i = 0; while (password[i]!= '\0') { if (password[i] == '$' password[i] == '@') { return TRUE; i++; return FALSE; /* check whether a password is valid, i.e. whether it contains at least one $ or @ */ i = 0; while (password[i]!= '\0') { if (password[i] == '$' password[i] == '@') { return TRUE; i++; return FALSE; Η στοίχιση σχολίων πρέπει να ακολουθεί πάντα τη στοίχιση του κώδικα. Ας δούµε και πάλι τον αρχικό κώδικα, αυτή τη φορά µε σχόλια. #include<stdio.h> int i; /* selectionsort(numbers, size) * Purpose: Sort an array of integers in ascending order using the selection sort algorithm * Parameters: numbers: an array of integers size: the size of the array * Preconditions: none * Postconditions: the array is sorted in ascending order */

void selectionsort(int numbers[], int size){ int boundaryindex, minindex; int savedvalue; /* The section between indices 0 and boundary_index-1 is maintained in sorted order. */ for (boundaryindex = 0; boundaryindex < size; boundaryindex++) { /* find the smallest element in the unsorted part */ minindex = boundaryindex; for (i = boundaryindex + 1; i < size; i++) { if (numbers[i] < numbers[minindex]) { minindex = i; /* swap smallest unsorted element with element at boundary */ savedvalue = numbers[minindex]; numbers[minindex] = numbers[boundaryindex]; numbers[boundaryindex] = savedvalue; /* * main */ int main(int argc, char *argv[]) { int numbers[10] = {8, 1, -2, 9, 0, 4, 3, 8, 5, 10; selectionsort(numbers, 10); for (i=0; i<10; i++) { printf("%d ", numbers[i]); return 0; Ο κώδικάς µας είναι σχεδόν έτοιµος. Μένουν µόνο δύο θέµατα να αγγίξουµε. Το πρώτο είναι η χρήση της καθολικής µεταβλητής i. Ο προγραµµατιστής που έγραψε το αρχικό πρόγραµµα αναµφίβολα σκέφτηκε πως αφού το i χρησιµοποιείται και στη main και στη selectionsort απλά ως µετρητής, θα είναι περιττό να το δηλώσει δύο φορές, µία σε κάθε συνάρτηση. Δυστυχώς, τέτοιες σκέψεις είναι επικίνδυνες. Το δεύτερο θέµα είναι η χρήση της τιµής 10 σε αρκετά σηµεία του προγράµµατος, το οποίο επίσης δυσκολεύει τη συντηρησιµότητά του όπως θα δούµε. Σηµείωση: Στην τάξη του Προγραµµατισµού Ι θα έχουµε συγκεκριµένα πρότυπα για το σχολιασµό προγραµµάτων τα οποία πρέπει να ακολουθούνται σε όλες τις εργασίες. Τα πρότυπα σχολιασµού περιγράφονται σε διαφορετικό φυλλάδιο που µπορείτε να βρείτε στην ιστοσελίδα του εργαστηρίου.

ΚΑΘΟΛΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ Οι καθολικές µεταβλητές είναι προσβάσιµες σε οποιοδήποτε σηµείο του προγράµµατος. Ο κίνδυνος σε αυτό είναι ότι µπορεί κατά λάθος να αλλαχθεί η τιµή της µεταβλητής σε ένα σηµείο του προγράµµατος αλλά αυτή η ενδεχόµενη αλλαγή να µη ληφθεί υπόψη σε κάποιο άλλο σηµείο. Ένα άλλο πρόβληµα είναι ότι µπορεί να οριστεί κάποια τοπική µεταβλητή ή παράµετρος µε το ίδιο όνοµα, πράγµα που θα δηµιουργήσει "σύγκρουση" ονοµάτων (η τοπική µεταβλητή κερδίζει). Αυτό είναι ένα λάθος που εµφανίζεται πολύ συχνά σε κώδικα αρχάριων προγραµµατιστών. int player_pos; void move_player (int new_pos) { int player_pos; player_pos = new_pos; void play_round() { player_pos = 0; move_player(3); /* Η τιµή του player_pos σε αυτό το σηµείο εξακολουθεί να είναι 0! */... ΣΤΑΘΕΡΕΣ ΤΙΜΕΣ (LITERALS) Τι θα συµβεί αν θέλουµε να αλλάξουµε το µέγεθος του πίνακα στο παράδειγµά µας? Θα πρέπει να ψάξουµε όλες τις εµφανίσεις του αριθµού 10 και να τις αλλάξουµε. Δε γίνεται να κάνουµε find+replace γιατί τότε θα αλλαχτεί και το τελευταίο στοιχείο που είναι αποθηκευµένο στον πίνακα πράγµα που θα οδηγήσει σε λάθος αποτελέσµατα. Η λύση είναι η χρήση του preprocessor directive #define η οποία µας επιτρέπει να θέσουµε το µέγεθος σε ένα σηµείο και να κάνουµε οποιεσδήποτε αλλαγές µόνο σε αυτό το σηµείο. Ο ΚΥΚΝΟΣ Μπορούµε τώρα να δούµε το πρόγραµµα στην τελική του µορφή (έγινε πια κύκνος...) #include<stdio.h> #define SIZE 10 /* number of elements in array to be sorted */ /* selectionsort(numbers, size) * Purpose: Sort an array of integers in ascending order using the selection sort algorithm * Parameters: numbers: an array of integers size: the size of the array * Preconditions: none * Postconditions: the array is sorted in ascending order */

void selectionsort(int numbers[], int size){ int boundaryindex, minindex, i; int savedvalue; /* The section between indices 0 and boundary_index-1 is maintained in sorted order. */ for (boundaryindex = 0; boundaryindex < size; boundaryindex++) { /* find the smallest element in the unsorted part */ minindex = boundaryindex; for (i = boundaryindex + 1; i < size; i++) { if (numbers[i] < numbers[minindex]) { minindex = i; /* swap smallest unsorted element with element at boundary */ savedvalue = numbers[minindex]; numbers[minindex] = numbers[boundaryindex]; numbers[boundaryindex] = savedvalue; /* * main */ int main(int argc, char *argv[]) { int numbers[size] = {8, 1, -2, 9, 0, 4, 3, 8, 5, 10; selectionsort(numbers, SIZE); for (i = 0; i < SIZE; i++) { printf("%d ", numbers[i]); return 0; ΒΙΒΛΙΟΓΡΑΦΙΑ McConnell, Steve. Code Complete: A Practical Handbook of Software Construction. 2nd ed. Microsoft Press, 2004 Ranade, Jay and Nash, Alan. The Elements of C Programming Style. Mcgraw-Hill, 1992 http://www.oualline.com/style/index.html Kernighan, Brian W. and Pike, Rob. The Practice of Programming. Addison-Wesley, 1999 Goodliffe, Pete. Code Craft: The Practice of Writing Excellent Code. No Starch Press, 2006 -- Βάνα Ντουφεξή