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

Η Γλώσσα Προγραμματισμού C
(Μέρος 1 - Εισαγωγή)

 

Σύντομη Ιστορία της C

Η γλώσσα προγραμματισμού C δημιουργήθηκε από τον Dennis Ritchie στα Bell Labs το 1972 όταν αυτός και ο Ken Thompson ασχολούνταν με τον σχεδιασμό του λειτουργικού συστήματος Unix. Η C ήταν μια εξέλιξη της γλώσσας Β του Ken Thompson και εκείνη με τη σειρά της ήταν μια εξέλιξη της γλώσσας BCPL και δημιουργήθηκε για να μπορέσει να καλύψει κάποιες αυξημένες ανάγκες στον προγραμματισμό.

Αργότερα αναπτύχθηκαν πολλές παραλλαγές της C που ήταν επόμενο να έχουν ασυμφωνίες μεταξύ τους. Έτσι, δημιουργήθηκε μια επιτροπή στις αρχές του καλοκαιριού του 1983 που άρχισε να δουλεύει πάνω στη δημιουργία ενός προτύπου Ansi το οποίο και θα όριζε μια για πάντα τη γλώσσα C.

 

Μια Σύγκριση των Γλωσσών Προγραμματισμού

Η C θεωρείται γενικά γλώσσα μέσου επιπέδου και αυτό γιατί συνδυάζει στοιχεία των γλωσσών υψηλού επιπέδου (high level languages), όπως είναι η Cobol και η Pascal και στοιχεία των γλωσσών χαμηλού επιπέδου (low level languages), όπως είναι η Assembly.

Για να διευκρινίσουμε, πρέπει να πούμε ότι σαν γλώσσα υψηλού επιπέδου θεωρείται η γλώσσα εκείνη που είναι αρκετά περιγραφική και που είναι έτσι πιο κοντά στην ανθρώπινη γραπτή γλώσσα και σαν γλώσσα χαμηλού επιπέδου θεωρείται εκείνη που είναι πιο κοντά στη μηχανή. Αυτός ο χαρακτηρισμός δεν έχει καμία απολύτως σχέση με τις δυνατότητες της γλώσσας.

Σίγουρα, η κάθε γλώσσα προγραμματισμού έχει κάποιες προτεραιότητες να εκπληρώσει. Η Pascal, για παράδειγμα, χρησιμοποιείται κυρίως για τη σωστή διδασκαλία των αρχών του προγραμματισμού, ενώ η Basic δημιουργήθηκε έτσι ώστε να δώσει τη δυνατότητα σε αρχάριους στον προγραμματισμό να κάνουν με άνεση και ευκολία τα πρώτα τους βήματα στον ιδιόμορφο αυτό χώρο. Ο Clipper και η Cobol είναι καθαρά επαγγελματικές γλώσσες προγραμματισμού.

Η C, όμως, μπόρεσε να φέρει τον προγραμματιστή πιο κοντά στο hardware, που με τις άλλες γνωστές γλώσσες προγραμματισμού κάτι τέτοιο θα ήταν πολύ δύσκολο να γίνει. Βέβαια, η κάθε γλώσσα προγραμματισμού κάνει και διαφορετική δουλειά και δεν θα ήταν σωστό να κάνουμε συγκρίσεις, για τον ίδιο λόγο που δεν μπορούμε να συγκρίνουμε ένα αεροπλάνο μ’ ένα ποδήλατο καθώς το καθένα είναι προορισμένο να κάνει διαφορετική δουλειά.

 

Τα Πλεονεκτήματα της C

Τα τελευταία χρόνια η C έχει καθιερωθεί ως μια από τις σημαντικότερες και δημοφιλέστερες γλώσσες προγραμματισμού. Τα σημαντικότερα πλεονεκτήματα που εξηγούν αυτήν την προτίμησή της, αναφέρονται παρακάτω.

Αυτή η ελευθερία είναι και πλεονέκτημα, αλλά είναι και επικίνδυνη όπως είναι φυσικό. Στη C τα πάντα (σχεδόν) επιτρέπονται. Δεν γίνεται έλεγχος των τύπων, άρα μπορεί κανείς να ανακατέψει ό,τι δεδομένα θέλει, κάτι που είναι πολύ χρήσιμο όταν προγραμματίζουμε σε επίπεδο συστήματος. Ακόμη, η C έχει μια τεράστια βιβλιοθήκη από χρήσιμες συναρτήσεις.

 

Τα Μειονεκτήματα της C

Η C έχει και μειονεκτήματα, γιατί όπως πολύ καλά ξέρουμε η πολύ ελευθερία βλάπτει. Για παράδειγμα, η ελευθερία έκφρασης που αναφέραμε παραπάνω ότι έχει η C, απαιτεί από τον προγραμματιστή μια αυξημένη επαγρύπνηση και υπευθυνότητα.

Ακόμη, η λακωνικότητα της C σε συνδυασμό με τον πλούτο των τελεστών που έχει, έχει σαν αποτέλεσμα τη δημιουργία προγραμμάτων που είναι τόσο δυσανάγνωστα, ώστε να είναι δύσκολο να τα κατανοήσει κάποιος με την πρώτη ματιά και πολλές φορές ακόμα και αυτός που τα έγραψε.

Επιπλέον, συχνά είναι πολύ δύσκολο να ανιχνευθούν και τα λογικά λάθη σ’ ένα πρόγραμμα της C. Η C έχει τελικά τόσες πολλές δυνατότητες έκφρασης, ώστε να χρειαστεί πολύς καιρός για να μπορεί να πει κανείς με βεβαιότητα ότι την έμαθε καλά.

 

Γράψιμο Προγράμματος σε C

Όπως είπαμε στα προηγούμενα, η C επιβάλλει τον καταμερισμό του προγράμματος σε ενότητες, που ονομάζονται συναρτήσεις (functions). Εάν είναι απαραίτητο, οι συναρτήσεις μπορούν να χωριστούν και σε μικρότερες συναρτήσεις. Επίσης, στη C το κύριο πρόγραμμα είναι κι αυτό μια συνάρτηση, που ονομάζεται main().

Μια μέθοδος για το γράψιμο ενός προγράμματος στη C είναι να ξεκινήσουμε γράφοντας τη συνάρτηση main(), την ενότητα του πιο πάνω επιπέδου και μετά να ασχοληθούμε με τις συναρτήσεις των πιο κάτω επιπέδων. Η διαδικασία αυτή ονομάζεται πάνω-προς-τα-κάτω προγραμματισμός (top-down programming).

Η αντίστροφη διαδικασία, δηλ. το να ασχοληθούμε πρώτα με τις συναρτήσεις των κατώτερων επιπέδων και μετά να ανεβαίνουμε προς τα πάνω, ονομάζεται κάτω-προς-τα-πάνω προγραμματισμός (bottom-up programming). Ένα πλεονέκτημα του πάνω-προς-τα-κάτω προγραμματισμού είναι ότι μπορούμε να χαράξουμε καλύτερα τη ροή του προγράμματος, μια και δεν ασχολούμαστε από την αρχή με τις λεπτομέρειες των επί μέρους συναρτήσεων.

 

Αντικατάσταση της Assembly από τη C

Όπως ίσως ξέρουμε, η γλώσσα Assembly χρησιμοποιεί μια συμβολική αναπαράσταση του πραγματικού δυαδικού κώδικα που εκτελεί απευθείας ο υπολογιστής και η κάθε εντολή της Assembly αντιστοιχεί σε μία μόνο ενέργεια που θα πρέπει να εκτελέσει ο υπολογιστής.

Η γλώσσα Assembly είναι, όμως, δύσκολη στο γράψιμο προγραμμάτων και επειδή δεν είναι καθόλου δομημένη, κάνει το τελικό πρόγραμμα να είναι ανεπιθύμητο από τους προγραμματιστές. Ο ερχομός της C κάνει περιττή πλέον τη χρήση της Assembly.

Έτσι, με τη C μπορούμε να γράψουμε προγράμματα που να έχουν την ίδια αποτελεσματικότητα με άλλα ανάλογα προγράμματα που είναι γραμμένα στη γλώσσα Assembly, αλλά να έχουμε συγχρόνως και τα σπουδαία πλεονεκτήματα μιας γλώσσας προγραμματισμού ανωτέρου επιπέδου.

 

Μεταγλώττιση και Σύνδεση Προγράμματος

Ο μεταγλωττιστής (compiler) της C μετατρέπει τον πηγαίο κώδικα (source program), δηλ. το πρόγραμμα που γράφουμε σε C, σ’ έναν αντικειμενικό κώδικα (object program) και το πρόγραμμα σύνδεσης (linker) συνδυάζει αυτόν τον κώδικα με άλλους κώδικες και δημιουργείται έτσι το εκτελέσιμο αρχείο (executable file). Τα προγράμματα της C έχουν την επέκταση .c.

Ο ρόλος του προγράμματος σύνδεσης είναι να ενώσει τον τελικό κώδικα, τον κώδικα εκκίνησης (start-up code) του συστήματός μας και τον κώδικα βιβλιοθήκης (library code) στο εκτελέσιμο αρχείο. Ο κώδικας εκκίνησης έχει σχέση με την επικοινωνία μεταξύ του προγράμματος και του λειτουργικού συστήματος και ο κώδικας βιβλιοθήκης περιέχει τον τελικό κώδικα για πολλές συναρτήσεις.

Σε μερικά συστήματα πρέπει να τρέξουμε τα προγράμματα μεταγλώττισης και σύνδεσης ξεχωριστά, ενώ σ' άλλα ο μεταγλωττιστής ενεργοποιεί το πρόγραμμα σύνδεσης αυτόματα μόνος του.

 

Το Περιβάλλον της Turbo-C

Η Turbo-C φορτώνεται με την εντολή tc από το Dos. Θα εμφανιστεί ένα κύριο μενού, που θα έχει τις παρακάτω επιλογές :

 

Ένα Απλό Πρόγραμμα στη C

/* prog01.c – αυτό είναι ένα απλό πρόγραμμα στη γλώσσα C */

#include <stdio.h>

main()

{

            int num;         /* ορίζεται μια ακέραια μεταβλητή με το όνομα num */

            num = 10 ;   /* καταχώρηση τιμής στη μεταβλητή num */

            printf("Ένα πολύ απλό πρόγραμμα σε C.\n"); /* η συνάρτηση printf() */

            printf("Ο αγαπημένος μου αριθμός είναι ο %d.\n", num);

}

Αφού μεταγλωττίσουμε και τρέξετε το παραπάνω πρόγραμμα, τότε θα πρέπει να εμφανισθούν στην οθόνη τα παρακάτω :

Ένα πολύ απλό πρόγραμμα σε C.

Ο αγαπημένος μου αριθμός είναι ο 10.

 

Σύντομη Ανάλυση του Προγράμματος

Η πρώτη γραμμή του προγράμματος χρησιμοποιεί τα σύμβολα /* και */ για να συμπεριλάβουμε εκεί κάποια σχόλια (comments), που θα μας βοηθήσουν να κάνουμε το πρόγραμμά μας πιο ευανάγνωστο. Αυτά τα σχόλια αγνοούνται από τον υπολογιστή. Η δεύτερη γραμμή λέει στον υπολογιστή να συμπεριλάβει (include) τις πληροφορίες που υπάρχουν στο αρχείο stdio.h, το οποίο αποτελεί μέρος του πακέτου της γλώσσας C.

Τα προγράμματα της C αποτελούνται από μία ή περισσότερες συναρτήσεις, που είναι και οι βασικές ενότητες ενός προγράμματος C. Αυτό το πρόγραμμα αποτελείται από μία μόνο συνάρτηση που καλείται main(). Οι παρενθέσεις υποδηλώνουν ότι το main() είναι ένα όνομα μιας συνάρτησης.

Η αγκύλη { δηλώνει την αρχή των προτάσεων που αποτελούν τη συνάρτηση και ο ορισμός της συνάρτησης τελειώνει με την αντίστοιχη αγκύλη }. Οι αγκύλες { και } είναι αντίστοιχες με τα begin και end της Pascal. Η πρόταση δήλωσης μάς λέει ότι θα χρησιμοποιήσουμε μια μεταβλητή με το όνομα num και ότι η num είναι ακέραια μεταβλητή (integer). Η πρόταση καταχώρησης δίνει την τιμή 10 στη μεταβλητή num.

Η επόμενη γραμμή είναι για την εκτύπωση της φράσης που βρίσκεται μεταξύ των εισαγωγικών (" "). Το \n λέει στον υπολογιστή να ξεκινήσει μια νέα γραμμή (σαν να πατούσαμε το πλήκτρο <enter>). Η επόμενη γραμμή είναι για την εκτύπωση της τιμής της num (που είναι το 10) ανάμεσα στη φράση που βρίσκεται μεταξύ των " ". Η εντολή %d λέει στον υπολογιστή πού και με ποια μορφή να εκτυπώσει την τιμή της num. Το πρόγραμμα τελειώνει με την αγκύλη }.

 

Λεπτομερής Ανάλυση του Προγράμματος

Τα Αρχεία Επικεφαλίδας #include

Το αρχείο stdio.h αποτελεί μέρος του μεταγλωττιστή της C και περιέχει πληροφορίες σχετικές με συναρτήσεις εισόδου και εξόδου, όπως είναι η printf(), που χρησιμοποιεί ο μεταγλωττιστής. Το όνομά του προέρχεται από τις λέξεις standard input/output header. Οι χρήστες της C αναφέρουν σαν επικεφαλίδα μια συλλογή πληροφοριών που βρίσκεται στην αρχή ενός αρχείου. Το αποτέλεσμα της εντολής #include <stdio.h> θα ήταν το ίδιο με το να αντιγράφαμε όλο το περιεχόμενο του αρχείου stdio.h στο δικό μας αρχείο, στη θέση όπου εμφανίζεται αυτή η γραμμή προγράμματος.

Στην πραγματικότητα, αυτή η γραμμή προγράμματος δεν είναι καν μια πρόταση της γλώσσας C. Το σύμβολο # σημαίνει ότι τη γραμμή αυτή τη διαχειρίζεται ο προεπεξεργαστής (preprocessor) της C, ο οποίος διαχειρίζεται κάποιες εργασίες πριν από τον μεταγλωττιστή.

Η Συνάρτηση main()

Η εκτέλεση ενός προγράμματος σε C αρχίζει πάντα με μια συνάρτηση που αποκαλείται main(). Είμαστε ελεύθεροι να επιλέξουμε τα ονόματα των άλλων συναρτήσεων που ίσως χρησιμοποιήσουμε, αλλά θα πρέπει υποχρεωτικά να υπάρχει η συνάρτηση main() στην αρχή του προγράμματος. Οι παρενθέσεις δηλώνουν ότι η main() είναι μια συνάρτηση. Γενικά, οι παρενθέσεις περιέχουν πληροφορίες (ορίσματα) που θα περάσουν μέσα στη συνάρτηση. Όταν, βέβαια, δεν υπάρχουν πληροφορίες για να περάσουν (μεταβιβασθούν), τότε οι παρενθέσεις είναι άδειες.

Τα Σχόλια

Όταν στο πρόγραμμά μας έχουμε σχόλια, τότε είναι πολύ ευκολότερο σε κάποιον άλλον, αλλά ακόμα και σε μας, να καταλάβει τι κάνει το πρόγραμμά μας. Ο,τιδήποτε υπάρχει ανάμεσα στο σύμβολο ανοίγματος /* και στο σύμβολο κλεισίματος */ των σχολίων αγνοείται από τον υπολογιστή και τα σχόλια στη C μπορούν να τοποθετηθούν οπουδήποτε, ακόμα και σε πολλές συνεχόμενες γραμμές.

Αγκύλες, Σώματα, Μπλοκ

Οι αγκύλες { και } δηλώνουν την αρχή και το τέλος του σώματος μιας συνάρτησης και μπορούν ακόμη να χρησιμοποιηθούν για να συμπεριλάβουν μαζί προτάσεις μέσα σε μια ομάδα ή σ’ ένα μπλοκ του προγράμματος, κάτι δηλαδή παρόμοιο με τα begin και end της Pascal.

Οι Προτάσεις Δήλωσης

Η πρόταση δήλωσης είναι μια από τις σημαντικότερες προτάσεις της C. Η δήλωση αυτή σημαίνει ότι κάπου μέσα στη συνάρτηση χρησιμοποιούμε τη μεταβλητή που δηλώνουμε και ότι ο τύπος της είναι αυτός που δείχνουμε, π.χ. ακέραιος. Η λέξη int είναι μια λέξη-κλειδί της C, δηλ. δεν μπορεί να χρησιμοποιηθεί αλλού μέσα στο πρόγραμμα σαν όνομα μιας συνάρτησης ή μιας μεταβλητής. Το ερωτηματικό στο τέλος της γραμμής δηλώνει ότι η γραμμή αυτή αποτελεί μια πρόταση ή εντολή της C.

 

Οι Τύποι Δεδομένων και οι Μεταβλητές

Η C έχει διάφορα είδη (τύπους) δεδομένων : ακέραιους, χαρακτήρες, κινητής υποδιαστολής, αριθμούς κ.ά. Για το όνομα μιας μεταβλητής μπορούμε να χρησιμοποιήσουμε μικρά γράμματα, κεφαλαία γράμματα, ψηφία αριθμών και τον χαρακτήρα της υπογράμμισης (_). Ο πρώτος χαρακτήρας, όμως, πρέπει να είναι πάντα γράμμα.

Πρέπει να είναι όλες οι μεταβλητές του προγράμματος συγκεντρωμένες μαζί για να είναι ευκολότερο για τον αναγνώστη να καταλάβει τι κάνει το πρόγραμμα και ακόμη πρέπει να υπάρχουν και σχόλια δίπλα στην κάθε μεταβλητή που να εξηγούν την αποστολή της. Ακόμη, η ονομασία που δίνουμε στις μεταβλητές πρέπει να μας βοηθάει να καταλαβαίνουμε και τη χρήση τους.

Η Εντολή Καταχώρησης

Η πρόταση καταχώρησης είναι μια από τις βασικότερες προτάσεις της C και με τη χρήση της δίνουμε τιμές στις μεταβλητές του προγράμματος. Η πρόταση καταχώρησης ολοκληρώνεται μ’ ένα ερωτηματικό ;.

Η Συνάρτηση printf()

Οι παρενθέσεις δηλώνουν κατ' αρχήν ότι πρόκειται για συνάρτηση. Τα στοιχεία που περιέχονται μεταξύ των παρενθέσεων είναι οι πληροφορίες που περνάμε (μεταβιβάζουμε) από τη συνάρτηση main() στη συνάρτηση printf(). Η πληροφορία που περνάει λέγεται όρισμα της συνάρτησης και η συγκεκριμένη συνάρτηση printf() εξετάζει τι υπάρχει μεταξύ των " " και το απεικονίζει στην οθόνη ενός τερματικού.

Για να καλέσουμε μια συνάρτηση το μόνο που χρειάζεται να κάνουμε είναι να γράψουμε το όνομά της και να συμπεριλάβουμε το επιθυμητό όρισμα μέσα σε παρενθέσεις. Όταν το πρόγραμμα φθάσει σ’ αυτή τη γραμμή, τότε ο έλεγχος περνάει στη συνάρτηση και μετά την ενεργοποίησή της, ο έλεγχος επιστρέφει στο αρχικό πρόγραμμα.

Ο χαρακτήρας \n, που δεν εμφανίζεται όταν τρέξει το πρόγραμμα, είναι στην πραγματικότητα μια εντολή για το ξεκίνημα μιας νέας γραμμής. Ο συνδυασμός \n αποτελεί έναν απλό χαρακτήρα που καλείται χαρακτήρας νέας γραμμής, δηλ. ενεργεί όπως το πλήκτρο <enter>. Ο χαρακτήρας νέας γραμμής είναι ένα παράδειγμα αυτού που ονομάζεται ακολουθία διαφυγής και που χρησιμοποιείται για να παριστάνει δύσκολους ή αδύνατον να πληκτρολογηθούν χαρακτήρες. Άλλα παραδείγματα τέτοιων χαρακτήρων είναι το \t για το πλήκτρο tab και το \b για ένα διάστημα προς τα πίσω (backspace).

Τι είναι, όμως, το σύμβολο %d;

Δείχνει σε ποιο σημείο θα εμφανιστεί η τιμής μιας μεταβλητής και ότι η μεταβλητή αυτή είναι ένας ακέραιος αριθμός.

Μια συνάρτηση στη C αποτελείται από μια επικεφαλίδα και ένα σώμα. Η επικεφαλίδα περιέχει τις προτάσεις του προεπεξεργαστή, όπως είναι η #include, και το όνομα της συνάρτησης. Το σώμα της συνάρτησης βρίσκεται μέσα στις αγκύλες { και } και αποτελείται από μια σειρά προτάσεων, που η κάθε μια τελειώνει μ’ ένα ελληνικό ερωτηματικό ;. Μέσα στο σώμα της συνάρτησης μπορεί να υπάρχουν προτάσεις δήλωσης, καταχώρησης και κλήσης άλλων συναρτήσεων.

 

Τεχνικές για πιο Ευανάγνωστα Προγράμματα

Δύο τέτοιες τεχνικές που είδαμε στα προηγούμενα ήταν η χρήση σχολίων και η σωστή ονομασία των μεταβλητών. Μια άλλη τεχνική είναι η χρήση κενών γραμμών για να ξεχωρίζουν τα τμήματα του προγράμματος. Ακόμη, στη C μπορούμε να τοποθετήσουμε πολλές προτάσεις σε μια γραμμή ή και να χωρίσουμε μια πρόταση σε πολλές γραμμές.

Το ελληνικό ερωτηματικό λέει στον μεταγλωττιστή πού τελειώνει μια πρόταση και πού αρχίζει η επόμενη. Πιο σωστό είναι πάντως να γράφουμε μια πρόταση ανά γραμμή.

 

Ένα Ακόμη Παράδειγμα στη C

/* prog02.c – το πρόγραμμα αυτό μετατρέπει τα μέτρα σε εκατοστά */

#include <stdio.h>

main()

{

            int cm, metres;

 

            metres = 2;

            cm = 100 * metres;

            printf("Υπάρχουν %d εκατοστά σε %d μέτρα. \n", cm, metres);

 

}

Όπως βλέπουμε, το πρώτο σχόλιο του προγράμματος περιέχει το όνομά του και το τι ακριβώς κάνει. Ακόμη, το πρόγραμμα δηλώνει δύο ακέραιες μεταβλητές μαζί, τις οποίες και διαχωρίζει με κόμμα. Χρησιμοποιεί τον τελεστή του πολλαπλασιασμού, που είναι το * και εκτυπώνει πολλές μεταβλητές μαζί στη συνάρτηση printf(). Όταν τρέξει το πρόγραμμα, θα δώσει το εξής αποτέλεσμα :

Υπάρχουν 200 εκατοστά σε 2 μέτρα.

 

Κλήση Συνάρτησης

Στο επόμενο παράδειγμα θα δούμε πώς μπορούμε να συμπεριλάβουμε και να καλούμε και μια δική μας συνάρτηση.

/* prog03.c – ένα πρόγραμμα που καλεί μια συνάρτηση */

#include <stdio.h>

main()

{

            printf("Θα καλέσω τη συνάρτηση της Φλώρινας.\n");

            florina();

            printf("Η κλήση της συνάρτησης έγινε.\n");

}

 

florina()

{

            printf("Γεια σας από τη Φλώρινα.\n");

}

Το αποτέλεσμα του προγράμματος θα είναι το παρακάτω :

Θα καλέσω τη συνάρτηση της Φλώρινας.

Γεια σας από τη Φλώρινα.

Η κλήση της συνάρτησης έγινε.

Η συνάρτηση florina) ορίζεται με τον ίδιο τρόπο, όπως και η main(), με το σώμα της να βρίσκεται ανάμεσα σε αγκύλες. Η συνάρτηση καλείται δίνοντας απλά το όνομά της μαζί με τις παρενθέσεις. Όταν η συνάρτηση florina() τελειώσει τη δουλειά της, το πρόγραμμα προχωράει στην επόμενη πρόταση της main().

Πρέπει να έχουμε υπόψη μας ότι οι συναρτήσεις μπορούν να γραφούν είτε πριν ή μετά από την κύρια συνάρτηση main(), αλλά εκτελούνται μόνο όταν και όπου η main() τις καλεί.

 

Έλεγχος της Ορθότητας των Προγραμμάτων

Συντακτικά Λάθη

Το συντακτικό λάθος στη C είναι κάτι ανάλογο με το γραμματικό λάθος στη γλώσσα που μιλάμε. Συντακτικά λάθη στη C μπορούν να γίνουν και με τη χρήση επιτρεπτών συμβόλων σε λανθασμένες θέσεις. Παραδείγματα τέτοιων λαθών μπορεί να είναι η μη σωστή χρήση των αγκυλών { και } ή ακόμη το να ανοίγουμε μια αγκύλη και να μην την κλείνουμε, το να ανοίγουμε κάπου σχόλια και να ξεχνάμε να τα κλείσουμε κοκ.

Όπως ξέρουμε, μέρος της δουλειάς του μεταγλωττιστή είναι και η ανακάλυψη των συντακτικών λαθών του προγράμματος. Υπάρχουν, όμως, και περιπτώσεις όπου ένα λάθος παράγει, άθελά μας, και άλλα λάθη.

Εννοιολογικά Λάθη

Το εννοιολογικό λάθος είναι το λάθος στο νόημα των προτάσεων. Στη C εννοιολογικά λάθη μπορούμε να κάνουμε, όταν ακολουθούμε μεν σωστά τους κανόνες της γλώσσας, αλλά με λανθασμένο αποτέλεσμα. Τέτοιο λάθος μπορεί να γίνει, όταν π.χ. αντί να προσθέσουμε δύο μεταβλητές, τις πολλαπλασιάζουμε. Με τα λάθη αυτά βέβαια δεν έχει καμία σχέση ο μεταγλωττιστής. Είναι δική μας δουλειά να τα ανακαλύψουμε και να τα διορθώσουμε. Ο καλύτερος τρόπος για να ανακαλύψουμε τέτοια λάθη είναι να εξετάσουμε το πρόγραμμα βήμα-βήμα.

Μπορούμε ακόμα να χρησιμοποιούμε επιλεκτικά και τη συνάρτηση printf() μέσα στο πρόγραμμα, ώστε να ελέγχουμε τις τιμές κάποιων μεταβλητών του προγράμματος. Τις εντολές printf() τις απομακρύνουμε μετά όταν το πρόγραμμά μας λειτουργήσει κανονικά. Και η χρήση των σχολίων μπορεί να αποδειχθεί χρήσιμη εδώ, γιατί με τη βοήθειά τους μπορούμε να απομονώσουμε κάποιο κομμάτι του προγράμματος προσωρινά και να ελέγξουμε έτσι την ορθότητα του υπόλοιπου προγράμματος.

Υπάρχουν και ειδικά προγράμματα που λέγονται αποσφαλματωτές (debuggers) και που μας επιτρέπουν να βλέπουμε τις τιμές των μεταβλητών του προγράμματος και ποια γραμμή του προγράμματος εκτελείται.

 

Οι Λέξεις-Κλειδιά της ANSI C

Οι λέξεις-κλειδιά ή δεσμευμένες λέξεις (reserved words) αποτελούν το λεξιλόγιο της C και γι’ αυτόν τον λόγο δεν μπορούμε να τις χρησιμοποιούμε για να δηλώσουμε ονόματα μεταβλητών ή συναρτήσεων στα προγράμματά μας.

Οι λέξεις αυτές είναι οι εξής :

auto   break               case                 char                 const              
continue default            do                    double else                
enum               extern float                for                   goto
if int                    long register           return             
short               signed             sizeof              static struct 
switch             typedef           union               unsigned         void
volatile           while      

Θα δούμε τώρα τα δεδομένα και τις ιδιότητές τους και θα μελετήσουμε κυρίως τις τρεις μεγάλες οικογένειες, των ακεραίων αριθμών, των αριθμών κινητής υποδιαστολής και των χαρακτήρων.

 

Ένα Απλό Πρόγραμμα

Ακολουθεί ένα απλό πρόγραμμα σε C.

/* prog04.c – η αξία ενός ποσού σε ευρώ */

#include <stdio.h>

main()

{

            float draxmes, euro;              /* 2 μεταβλητές κινητής υποδιαστολής */

            char beep;                               /* μια μεταβλητή τύπου χαρακτήρα */

 

            beep = ‘\007’             /* καταχώρηση ενός ειδικού χαρακτήρα */

            printf("Θέλετε να μάθετε την αξία των χρημάτων σας σε δραχμές;\n");

            printf("Παρακαλώ δώστε την αξία σε ευρώ \n");

            printf("και θα δούμε.\n");

            scanf("%f", &euro);   /* παίρνουμε δεδομένα από τον χρήστη */

            draxmes = 340.75 * euro;   /* ο συντελεστής 340.75 μετατρέπει τις δραχμές σε ευρώ */

            printf("%c Η αξία σε δραχμές είναι %.2f%c. \n", beep, draxmes, beep);

}

Αφού τρέξουμε αυτό το πρόγραμμα, θα πάρουμε το εξής αποτέλεσμα :

Θέλετε να μάθετε την αξία των χρημάτων σας σε δραχμές;

Παρακαλώ δώστε την αξία σε ευρώ και θα δούμε.

100.00

Η αξία σε δραχμές είναι 34075.00

 

Τι Καινούργια Στοιχεία Υπάρχουν

Πρώτα απ' όλα χρησιμοποιούμε δύο νέα είδη μεταβλητών, μια μεταβλητή κινητής υποδιαστολής (float) και μια μεταβλητή χαρακτήρων (char) και συνεπώς μπορούμε τώρα να διαχειριστούμε περισσότερα δεδομένα. Για την εμφάνιση στην οθόνη αυτών των νέων ειδών μεταβλητών χρησιμοποιούμε τους κώδικες %f και %c της printf() αντίστοιχα. Η χρήση του .2 σημαίνει δύο δεκαδικά ψηφία στην εμφάνιση του δεκαδικού αριθμού, άσχετα αν με τις δραχμές δεν είχαμε δεκαδικά ψηφία.

Για την εισαγωγή δεδομένων από το πληκτρολόγιο χρησιμοποιούμε τη συνάρτηση scanf(). Ο κώδικας %f καθοδηγεί το πρόγραμμα να διαβάσει έναν αριθμό κινητής υποδιαστολής και το &euro λέει στη συνάρτηση scanf() να καταχωρήσει την τιμή στη μεταβλητή euro. Το σύμβολο & θα αναλυθεί αργότερα.

Οι δύο συναρτήσεις printf() και scanf() επιτυγχάνουν τη διαλογική επικοινωνία μας με τον υπολογιστή, αφού η μεν scanf() διαβάζει δεδομένα από το πληκτρολόγιο και τα μεταφέρει για επεξεργασία στο πρόγραμμα και η printf() διαβάζει δεδομένα από το πρόγραμμα και τα εμφανίζει στην οθόνη. Υπάρχει ακόμα και ο χαρακτήρας beep που παριστάνει το ηχητικό σήμα.

 

Οι Τύποι Δεδομένων

Ο τύπος μιας μεταβλητής μπορεί να καθοριστεί σε μια πρόταση δήλωσης. Η C χρησιμοποιεί τις εξής επτά λέξεις-κλειδιά για τους τύπους δεδομένων της :

int, long, short, unsigned, char, float και double.

Η int δηλώνει τον βασικό τύπο ακεραίων και οι long, short και unsigned χρησιμοποιούνται σε παραλλαγές του βασικού τύπου. Η char χρησιμοποιείται γενικά για τους χαρακτήρες και οι float, double και ο συνδυασμός long double χρησιμοποιούνται για την παράσταση αριθμών κινητής υποδιαστολής.

Οι πέντε πρώτες λέξεις-κλειδιά δημιουργούν ακέραιους τύπους, ενώ οι δύο τελευταίες τύπους κινητής υποδιαστολής. Οι ακέραιοι αποθηκεύονται σε μορφή ψηφιακών αριθμών, ενώ για τους αριθμούς κινητής υποδιαστολής υπάρχουν πολλοί τρόποι για να τους παραστήσουμε μέσα στον υπολογιστή.

Ο πιο γνωστός είναι με τη χρήση του συμβόλου Ε, όπου και έχουμε το κλασματικό και το εκθετικό τμήμα του αριθμού, τα οποία και αποθηκεύονται ξεχωριστά. Έτσι, ο 7 γράφεται σαν 0.7Ε1, που σημαίνει 0.7 Χ 101 = 7.

Κάτι που πρέπει να τονιστεί για τους αριθμούς κινητής υποδιαστολής είναι τα συχνά σφάλματα στρογγυλοποίησης που μπορεί να συμβούν μ' αυτούς και έτσι σαν γενικό κανόνα πρέπει να έχουμε υπόψη μας το ότι όταν οι ακέραιοι αριθμοί κάνουν τη δουλειά μας, να τους χρησιμοποιούμε ανεπιφύλακτα.

 

Οι Ακέραιοι Τύποι Δεδομένων

Ο τύπος int που ήδη ξέρουμε είναι ένας ακέραιος με πρόσημο, δηλ. πρέπει να είναι ένας ολόκληρος ακέραιος και μπορεί να είναι θετικός, αρνητικός ή και μηδέν. Συνήθως χρησιμοποιούνται δύο ψηφιολέξεις (bytes) για να αποθηκευθεί ένας ακέραιος της μορφής αυτής και έτσι το εύρος τιμών του είναι από -32768 έως και +32767. Η λέξη-κλειδί int χρησιμοποιείται για τη δήλωση μεταβλητών αυτού του τύπου. Για να δηλώσουμε περισσότερες μεταβλητές αυτού του τύπου, μπορούμε είτε να τις δηλώσουμε χωριστά, ή να τις δηλώσουμε όλες μαζί, αλλά χωρισμένες με κόμμα.

Οι δηλώσεις δημιουργούν μεταβλητές, αλλά δεν καταχωρούν τιμές σ' αυτές. Η καταχώρηση των τιμών γίνεται μέσα στο πρόγραμμα με τις εντολές καταχώρησης ή και μέσω της συνάρτησης scanf(). Απόδοση αρχικής τιμής σε μια μεταβλητή σημαίνει να ορίσουμε την τιμή εκκίνησης της μεταβλητής. Στη C αυτό μπορεί να γίνει σε μια πρόταση δήλωσης, όπου μετά το όνομα της μεταβλητής υπάρχει ο τελεστής καταχώρησης (=) και μετά η αρχική τιμή της μεταβλητής, ως εξής :

int a=10;

int b, cs=20;

Στη C ειδικά προθέματα δηλώνουν ποια βάση αρίθμησης χρησιμοποιούμε. Το πρόθεμα 0 (μηδέν) σημαίνει ότι γράφουμε στο οκταδικό και το πρόθεμα 0x ή 0X σημαίνει ότι ο αριθμός είναι δεκαεξαδικός. Έτσι, ο δεκαδικός αριθμός 16 γράφεται στο οκταδικό σύστημα σαν 020 και στο δεκαεξαδικό σύστημα σαν 0x10 ή 0X10. Σ' όλες τις περιπτώσεις χρησιμοποιείται ο δυαδικός κώδικας από τον υπολογιστή για την αποθήκευση του αριθμού.

Το σύμβολο %d που είδαμε στα προηγούμενα παραδείγματα αντιστοιχεί σε μια ακέραια τιμή αριθμού, που μπορεί να είναι μια μεταβλητή τύπου int, μια ακέραια σταθερά τύπου int ή και οποιαδήποτε άλλη έκφραση, που έχει όμως μια ακέραια τιμή int. Ακολουθεί ένα απλό πρόγραμμα που επεξηγεί τα παραπάνω :

/* prog05.c – μερικές ιδιότητες της printf() */

#include <stdio.h>

main()

{

            int ten = 10;

            printf("%d μείον %d ίσον %d\n", ten, 2, ten-2);

}

Το αποτέλεσμα του προγράμματος θα είναι :

10 μείον 2 ίσον 8

Μπορούμε, όμως, να εκτυπώσουμε τους ακέραιους αριθμούς στο οκταδικό σύστημα με το σύμβολο %o και στο δεκαεξαδικό με το σύμβολο %x. Ακολουθεί ένα απλό παράδειγμα :

/* prog06.c – εκτύπωση του αριθμού 100 σε τρία αριθμητικά συστήματα */

#include <stdio.h>

main()

{

            int x = 100;

            printf("δεκαδ = %d; οκταδ = %o; δεκαεξ = %x\n", x, x, x);

}

Το αποτέλεσμα του προγράμματος θα είναι :

δεκαδ = 100; οκταδ = 144; δεκαεξ = 64

Παρατηρούμε ότι τα προθέματα 0 και 0x δεν παρουσιάζονται στην έξοδο.

 

Άλλοι Τύποι Ακεραίων

Η C προσφέρει τρεις τύπους λέξεις-κλειδιά για την τροποποίηση του βασικού τύπου ακεραίου : unsigned, long και short. Ο τύπος short int ή short είναι ένας τύπος με πρόσημο και χρησιμοποιεί λιγότερο χώρο αποθήκευσης, απ' ό,τι ο int και έτσι μπορεί να χρησιμοποιηθεί για μικρούς αριθμούς. Ο τύπος long int ή long είναι ένας τύπος με πρόσημο που χρησιμοποιεί περισσότερο χώρο αποθήκευσης απ' ό,τι ο int και συνεπώς επιτρέπει τη χρήση μεγάλων ακεραίων. Ο τύπος unsigned επιτρέπει τη χρήση της κλίμακας από το 0 μέχρι το 65535 αντί για την κλίμακα από το -32768 μέχρι το +32767.

Όσον αφορά τώρα τη χρήση αυτών των τύπων ακεραίων, πρέπει να έχουμε υπόψη μας ότι ο τύπος unsigned μπορεί να χρησιμοποιηθεί για μέτρημα, αφού δεν υπάρχουν σ' αυτόν τον τύπο αρνητικοί αριθμοί. Ο τύπος long χρησιμοποιείται αν έχουμε πολύ μεγάλους αριθμούς, που δεν μπορεί να τους διαχειριστεί ο τύπος int. Δεν πρέπει, όμως, να χρησιμοποιείται ο τύπος long αν αυτό δεν είναι απαραίτητο, γιατί επιβραδύνει τους υπολογισμούς και καταλαμβάνει πολύ μνήμη. Μπορούμε να χρησιμοποιήσουμε τον τύπο short όταν χρησιμοποιούμε μεγάλους πίνακες ακεραίων στο πρόγραμμά μας.

Για να αποθηκευθεί μια σταθερά σαν τύπου long, θα πρέπει να προσθέσουμε την κατάληξη l ή L και οι καταλήξεις αυτές μπορούν να χρησιμοποιηθούν ακόμα και με τους οκταδικούς ή τους δεκαεξαδικούς ακέραιους. Για την εκτύπωση ενός αριθμού τύπου unsigned χρησιμοποιούμε το σύμβολο %u, ενός αριθμού τύπου long το %ld και ακόμη μπορούμε να συνδυάσουμε το l με τα o και x. Ακόμη, το %h χρησιμοποιείται για τον τύπο short.

 

Οι Χαρακτήρες

Όπως ήδη ξέρουμε, ο τύπος char χρησιμοποιείται για την αποθήκευση χαρακτήρων, αν και στην πραγματικότητα αποθηκεύει ακέραιους. Για τον χειρισμό των χαρακτήρων ο υπολογιστής χρησιμοποιεί έναν αριθμητικό κώδικα, όπου συγκεκριμένοι ακέραιοι παριστάνουν συγκεκριμένους χαρακτήρες. Ο πιο συχνά χρησιμοποιούμενος κώδικας είναι ο ASCII και για παράδειγμα ο ακέραιος 65 παριστάνει το γράμμα Α. Οι μεταβλητές τύπου char δηλώνονται όπως όλες οι μεταβλητές :

char name, city;

Υπάρχουν εκδόσεις της C που έχουν τον τύπο char με πρόσημο και με περιοχή τιμών από -128 έως +127 και άλλες εκδόσεις της C έχουν τον τύπο char χωρίς πρόσημο και με περιοχή τιμών από 0 έως 255. Μπορούμε να δώσουμε αρχικές τιμές στις μεταβλητές τύπου char με δύο τρόπους :

char grade = 65;    /* εδώ χρησιμοποιούμε τον ASCII κώδικα του Α */

ή

char grade = 'A';    /* εδώ τα πράγματα είναι πιο απλά για μας */

Τα απλά εισαγωγικά ' ' δηλώνουν στη C μια σταθερά χαρακτήρα, ενώ τα διπλά εισαγωγικά " " θεωρούνται μια συμβολοσειρά, που θα την δούμε αναλυτικά παρακάτω.

 

Οι μη Εκτυπούμενοι Χαρακτήρες

Υπάρχουν μερικοί ASCII χαρακτήρες που είναι μη εκτυπούμενοι, όπως το διάστημα προς τα πίσω (backspace), το enter και το ηχητικό σήμα (beep). Η C μάς παρέχει τρεις τρόπους για την αναπαράσταση τέτοιων χαρακτήρων. Ο πρώτος είναι χρησιμοποιώντας τον κώδικα ASCII του χαρακτήρα, ως εξής :

char beep = 7;

Ο δεύτερος είναι χρησιμοποιώντας μια ειδική μορφή του κώδικα ASCII, όπου τοποθετούμε ανάμεσα σε απλά εισαγωγικά τον οκταδικό κώδικα ASCII μαζί με μια πλάγια κάθετο \ πριν απ’ αυτόν, ως εξής :

beep = '\007';

Οι αριθμοί ερμηνεύονται σαν οκταδικοί, ακόμη και αν δεν υπάρχει μπροστά ένα 0. Η ANSI C και πολλές νέες εκδόσεις δέχονται μια δεκαεξαδική μορφή για τις σταθερές χαρακτήρα, όπου η πλάγια κάθετος \ ακολουθείται από ένα x ή X και από 1 μέχρι 3 δεκαεξαδικά ψηφία. Έτσι, ο χαρακτήρας Control-P θα μπορεί να παρασταθεί σαν '\x10' ή '\X010'. Ο τρίτος τρόπος είναι να χρησιμοποιήσουμε μια ειδική ακολουθία συμβόλων, που ονομάζεται ακολουθία διαφυγής (escape sequence) :

\a         ειδοποίηση - beep (ANSI C)

\b         ένα διάστημα προς τα πίσω (προσοχή δεν σβήνει τους χαρακτήρες)

\f         τροφοδότηση σελίδας

\n         νέα γραμμή (enter)

\r         επιστροφή στην αρχή της τρέχουσας γραμμής

\t          οριζόντια στηλοθέτηση (tab)

\v         κάθετη στηλοθέτηση (ANSI C)

\\          πλάγια κάθετος (\)

\'          απλά εισαγωγικά (')

\"          διπλά εισαγωγικά (") (ANSI C)

Όλοι αυτοί οι χαρακτήρες κλείνονται σε απλά εισαγωγικά όταν καταχωρούνται σε μια μεταβλητή χαρακτήρα :

next = '\n';

Η εκτύπωση της μεταβλητής next προχωράει την εκτύπωση κατά μια γραμμή στην οθόνη ή στον εκτυπωτή. Η συνάρτηση printf() χρησιμοποιεί το %c για να δείξει ότι πρέπει να τυπωθεί ένας χαρακτήρας. Θα πρέπει να θυμόμαστε ότι οι χαρακτήρες είναι αποθηκευμένοι σαν ακέραιοι, οπότε αν τυπώσουμε την τιμή μιας μεταβλητής τύπου char, θα πάρουμε έναν ακέραιο.

Ο προσδιορισμός %c λέει στην printf() να μετατρέψει τον ακέραιο στον αντίστοιχο χαρακτήρα. Αυτά φαίνονται καθαρά στο παρακάτω πρόγραμμα :

/* prog07.c - εμφανίζει τον κωδικό αριθμό κάποιου χαρακτήρα */

#include <stdio.h>

main()

{

            char ch;

            printf("Δώστε έναν χαρακτήρα : \n");

            scanf("%c", &ch);

            printf("Ο κώδικας του %c είναι το %d. \n", ch, ch);

}

Το αποτέλεσμα θα είναι :

Δώστε έναν χαρακτήρα :

C

Ο κώδικας του C είναι το 67.

Η printf() τυπώνει την τιμή της ch δύο φορές, την πρώτη σαν χαρακτήρα (προτρεπόμενη από τον κώδικα %c) και τη δεύτερη σαν ακέραιο (προτρεπόμενη από τον κώδικα %d). Οι προσδιοριστές της printf() αποφασίζουν για το πώς θα εμφανιστούν τα δεδομένα και όχι για το πώς θα αποθηκευθούν.

 

Οι Τύποι float και double

Σε προγράμματα μαθηματικής φύσης συχνά χρησιμοποιούμε αριθμούς κινητής υποδιαστολής που στη C λέγονται τύπου float και είναι αντίστοιχοι με τους τύπους real της Pascal. Έτσι, μπορούμε να παραστήσουμε ένα πολύ μεγαλύτερο εύρος αριθμών, μεγάλων και μικρών. Υπάρχουν ακόμα και οι τύποι double (για διπλή ακρίβεια) και long double. Οι μεταβλητές αυτές δηλώνονται όπως και οι άλλες :

float a=10.25e-3;

double b;

long double c;

Ένα πρόθεμα f ή F στην ANSI C σ’ έναν αριθμό κινητής υποδιαστολής τον κάνει τύπου float, π.χ. 2.3f και 9.11E9F, ενώ μια κατάληξη l ή L τον κάνει τύπου long double, π.χ. 54.31l και 4.32e4L.

Η συνάρτηση printf() χρησιμοποιεί τον προσδιοριστή μορφής %f για να τυπώσει τύπου float και double αριθμούς με δεκαδικό συμβολισμό και τη μορφή %e για να τους τυπώσει σε εκθετικό συμβολισμό. Για τους τύπους long double έχουμε αντίστοιχα τους προσδιοριστές %Lf και %Le.

 

Ο Τελεστής sizeof

Η C έχει έναν εσωτερικό τελεστή, τον sizeof, που δίνει το μέγεθος κάποιων πραγμάτων σε bytes. Αυτό θα το δούμε καλύτερα μ’ ένα παράδειγμα :

/* prog08.c – τυπώνει τα μεγέθη των τύπων δεδομένων */

#include <stdio.h>

main()

{

            printf("Ο τύπος int έχει μέγεθος %d bytes. \n", sizeof(int));

            printf("Ο τύπος char έχει μέγεθος %d bytes. \n", sizeof(char));

            printf("Ο τύπος long έχει μέγεθος %d bytes. \n", sizeof(long));

            printf("Ο τύπος double έχει μέγεθος %d bytes. \n", sizeof(double));

}

Το αποτέλεσμα θα είναι :

Ο τύπος int έχει μέγεθος 2 bytes.

Ο τύπος char έχει μέγεθος 1 bytes.

Ο τύπος long έχει μέγεθος 4 bytes.

Ο τύπος double έχει μέγεθος 8 bytes.

 

Εισαγωγή στις Συμβολοσειρές

Ακολουθεί ένα πρόγραμμα που κάνει έναν διάλογο με τον χρήστη.

/* prog09.c – ζητούνται στοιχεία χρήστη */

#include <stdio.h>

main()

{

            float weight;

            int size, letters;

            char name[40];

 

            printf("Γεια σου! Πώς λέγεσαι; \n");

            scanf("%s", name);

            printf("%s, Ποιο είναι το βάρος σου σε κιλά; \n", name);

            scanf("%f", &weight);

            size = sizeof name;

            letters = strlen(name);

            printf("Γεια σου, %s, το βάρος σου είναι %2.2f κιλά. \n", name, volume);

            printf("Επίσης, το σου όνομά σου έχει %d γράμματα, \n", letters);

            printf("και χρειάζονται %d bytes για την αποθήκευσή του.\n", size);

}

Τρέχοντας αυτό το πρόγραμμα, παίρνουμε τα εξής αποτελέσματα :

Γεια σου! Πώς λέγεσαι;

Κώστας

Κώστας, ποιο είναι το βάρος σου σε κιλά;

100

Γεια σου, Κώστας, το βάρος σου είναι 100,00 κιλά.

Επίσης,  το όνομά σου έχει 6 γράμματα,

και χρειάζονται 40 bytes για για την αποθήκευσή του.

Τα κυριότερα νέα χαρακτηριστικά αυτού του προγράμματος είναι τα εξής :

1. Έχουμε χρησιμοποιήσει έναν πίνακα που περιέχει μια συμβολοσειρά και συγκεκριμένα κάποιο όνομα.

2. Χρησιμοποιήσαμε τον προσδιοριστή μετατροπής %s για να χειριστούμε την είσοδο και την έξοδο μιας συμβολοσειράς. Η μεταβλητή name, σε αντίθεση με την weight, δεν χρησιμοποιεί το πρόθεμα & όταν χρησιμοποιείται με την scanf().

4. Χρησιμοποιήσαμε τη συνάρτηση της C strlen() για να βρούμε το μήκος μιας συμβολοσειράς.

Τι είναι, όμως, μια συμβολοσειρά;

Μια συμβολοσειρά είναι μια σειρά από έναν ή περισσότερους χαρακτήρες, όπως για παράδειγμα : "Το ΙΕΚ Φλώρινας λειτουργεί από το 1993". Τα διπλά εισαγωγικά δεν είναι μέρος της συμβολοσειράς και υπάρχουν για να οριοθετούν τη συμβολοσειρά, όπως ακριβώς τα απλά εισαγωγικά χρησιμοποιούνται για να οριοθετούν έναν χαρακτήρα. Η C αποθηκεύει τις συμβολοσειρές σ’ έναν πίνακα τύπου char με κάθε χαρακτήρα της συμβολοσειράς να είναι αποθηκευμένος σε κάθε κελί. Η C χρησιμοποιεί τον χαρακτήρα \0 στην τελευταία θέση του πίνακα για να σημειώνει το τέλος μιας συμβολοσειράς.

Αυτός ο χαρακτήρας δεν είναι το ψηφίο 0, αλλά είναι ο μη απεικονιζόμενος χαρακτήρας του οποίου ο κώδικας ASCII είναι 0. Ο πίνακας λοιπόν πρέπει να έχει τουλάχιστον ένα περισσότερο κελί από τον αριθμό των χαρακτήρων που πρόκειται να αποθηκευτούν. Η δήλωση ενός πίνακα μπορεί να γίνει με την εξής εντολή :

char name[40];

απ' όπου καταλαβαίνουμε ότι η μεταβλητή name είναι πίνακας με μέγεθος 40 και το κάθε στοιχείο της είναι ένας χαρακτήρας.

 

Η Χρήση των Συμβολοσειρών

Δείτε το παρακάτω πρόγραμμα :

/* prog10.c – πρόγραμμα με συμβολοσειρές */

#include <stdio.h>

#define PRAISE "Έχεις ένα σπουδαίο όνομα!"

main()

{

            char name[50];

 

            printf("Πώς σε λένε;\n");

            scanf("%s", name);

            printf("Γεια σου, %s. %s\n", name, PRAISE);

}

Η έξοδος του προγράμματος θα είναι :

Πώς σε λένε;

Μάκη Παπαδόπουλο

Γεια σου, Μάκη. Έχεις ένα σπουδαίο όνομα!

Παρατηρούμε ότι η scanf() διαβάζει μόνο το μικρό όνομα του Παπαδόπουλου. Η συνάρτηση σταματάει λοιπόν μόλις βρει το πρώτο κενό διάστημα. Γενικά, η scanf() χρησιμοποιούμενη με το %s διαβάζει απλές λέξεις και όχι φράσεις σαν συμβολοσειρές. Η C έχει άλλες συναρτήσεις για διάβασμα εισόδου, όπως την gets(), για να χειρίζεται γενικευμένες συμβολοσειρές, που θα τις δούμε αργότερα.

Η συμβολοσειρά "x" δεν είναι το ίδιο με τον χαρακτήρα 'x' και αυτό γιατί η 'x' είναι ένας βασικός τύπος (char), ενώ η "x" είναι ένας παραγόμενος τύπος, ένας πίνακας από στοιχεία τύπου char. Ακόμη, η "x" αποτελείται από δύο χαρακτήρες, τον 'x' και τον μηδενικό χαρακτήρα. Η συνάρτηση srtlen() μας δίνει το μήκος μιας συμβολοσειράς σε χαρακτήρες, ενώ ο τελεστής sizeof επιστρέφει τον αριθμό των συνολικών κελιών μνήμης που είχαν δηλωθεί αρχικά γι αυτή τη μεταβλητή.

 

Οι Σταθερές και ο Προεπεξεργαστής της C

Ξέρουμε από τις άλλες γλώσσες προγραμματισμού τη σημασία που έχει η δήλωση μιας σταθεράς σ’ ένα πρόγραμμα. Στη C υπάρχουν δύο τρόποι για να δηλωθεί μια σταθερή τιμή. Ένας τρόπος είναι να ορίσουμε μια μεταβλητή και να την εξισώσουμε με την επιθυμητή σταθερά, ως εξής :

float taxrate;

taxrate = 0.2;

Μ’ αυτόν τον τρόπο η αντικατάσταση της τιμής της μεταβλητής taxrate θα γίνεται όταν το πρόγραμμα τρέχει. Ο προεπεξεργαστής της C διαθέτει έναν καλύτερο τρόπο, όπου απλά προσθέτουμε μια γραμμή στην αρχή του αρχείου που περιέχει το πρόγραμμά μας, ως εξής :

#define TAXRATE 0.2

Όταν το πρόγραμμα μεταγλωττιστεί, η τιμή 0.2 θα αντικατασταθεί παντού όπου έχει χρησιμοποιηθεί η TAXRATE. Έτσι, όταν τρέξουμε το πρόγραμμα, όλες οι αντικαταστάσεις θα έχουν ήδη γίνει. Πρέπει να προσέξουμε τη σύνταξη της #define, στην οποία δεν χρησιμοποιείται το ελληνικό ερωτηματικό (;), αφού δεν είναι μια πρόταση της C και ακόμη αποτελεί παράδοση στη C να γράφονται όλες οι σταθερές με κεφαλαία γράμματα για να τις αναγνωρίζουμε αμέσως και να τις ξεχωρίζουμε έτσι από τις άλλες μεταβλητές.

Ακολουθεί ένα παράδειγμα με χρήση της #define.

/* prog11.c – χρήση της σταθεράς π = 3.14159  */

#include <stdio.h>

#define PI 3.14159

main()

{

            float area, circum, radius;

 

            printf("Δώστε την ακτίνα του κύκλου : \n");

            scanf("%f", &radius);

            area = PI * radius * radius;

            circum = 2.0 * PI * radius;

            printf("Τα στοιχεία του κύκλου είναι :\n");

            printf("Περίμετρος = %1.2f, εμβαδόν = %1.2f\n", circum, area);

}

Το αποτέλεσμα θα είναι :

Δώστε την ακτίνα του κύκλου :

6.0

Τα στοιχεία του κύκλου είναι :

Περίμετρος = 37.70, εμβαδόν = 113.10

Η εντολή #define μπορεί να χρησιμοποιηθεί τόσο για χαρακτήρες όσο και για σταθερές συμβολοσειρές. Χρησιμοποιούμε απλά εισαγωγικά για την πρώτη περίπτωση και διπλά για τη δεύτερη. Ακολουθούν παραδείγματα :

#define BEEP '\007'

#define TEE 'T'

#define ESC '\033'

#define OOPS "Τώρα το πέτυχες"

Αν κατά λάθος γράψουμε #define TOES = 20, τότε η TOES θα αντικατασταθεί με το = 20 και όχι με το 20.

 

Οι Δυνατότητες της #define

Μπορούμε να μαζέψουμε όλες τις προτάσεις #define σ’ ένα αρχείο και να το ονομάσουμε, π.χ. const.h. Μετά, στην αρχή κάθε προγράμματος μπορούμε να εισάγουμε την πρόταση #include "const.h" και όταν τρέξει το πρόγραμμα, ο προεπεξεργαστής θα διαβάσει το αρχείο const.h και θα χρησιμοποιήσει όλες τις προτάσεις #define που θα βρει εκεί.

Χρησιμοποιούμε την ονομασία "const.h" για να ψάξει πρώτα στον τρέχοντα κατάλογο και μετά στους καταλόγους του συστήματος, ενώ η ονομασία <const.h> σημαίνει να ψάξει στον κανονικό κατάλογο πρώτα. Μια άλλη σπουδαία δυνατότητα της #define είναι ότι μπορούμε να κάνουμε τέτοιες αντικαταστάσεις, ώστε τα προγράμματα της C να θυμίζουν Pascal, ως εξής :

#define program main()

#define begin {

#define end }

#define times *

Έτσι, όπου ο προεπεξεργαστής βρει τους αριστερούς όρους, τους αντικαθιστά μ’ ό,τι είναι δεξιά, δηλ. με εντολές της C, αλλά εμείς γράφουμε σαν να είμαστε στην Pascal.

 

Τυπώνοντας Μεγάλες Συμβολοσειρές

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

/* prog12.c – τυπώνοντας μεγάλες συμβολοσειρές */

#include <stdio.h>

main()

{

            printf("Να ένας τρόπος να τυπώσετε μια ");

            printf("μεγάλη συμβολοσειρά.\n");

            printf("Να ένας άλλος τρόπος να τυπώσετε μια \

                        μεγάλη συμβολοσειρά.\n");

            printf("Να ο πιο καινούργιος τρόπος να τυπώσετε μια "

                        " μεγάλη συμβολοσειρά.\n");

}

Το αποτέλεσμα θα είναι :

Να ένας τρόπος να τυπώσετε μια μεγάλη συμβολοσειρά.

Να ένας άλλος τρόπος να τυπώσετε μια μεγάλη συμβολοσειρά.

Να ο πιο καινούργιος τρόπος να τυπώσετε μια μεγάλη συμβολοσειρά.

 

 

back.gif (9867 bytes)

Επιστροφή