Professional Documents
Culture Documents
Γλώσσα C
Πανεπιστήμιο Πελοποννήσου
Τμήμα Πληροφορικής & Τηλεπικοινωνιών
Νικόλαος Δ. Τσελίκας
Προγραμματισμός Ι
Προγραμματισμός Ι
Power Shell σε Windows 10 (2/7)
Στη συνέχεια κατεβάζουμε/εγκαθιστούμε από το Windows Store
κάποια LTS (long term support) έκδοση Ubuntu
Προσοχή!!!
6 Κατά την εκκίνηση θα σας
ζητηθεί να δώσετε ένα
username κι ένα password
(2 φορές, για επιβεβαίωση).
...και ξεκινάμε τα Ubuntu Μπορείτε να
πληκτρολογήσετε ό,τι
7 θέλετε, αλλά δεν θα πρέπει
να το ξεχάσετε ποτέ (να το
σημειώσετε κάπου)
Προγραμματισμός Ι
Προγραμματισμός Ι
Power Shell σε Windows 10 (4/7)
Εγκατάσταση του gcc compiler που θα χρησιμοποιούμε στο μάθημα
Προγραμματισμός Ι
Κaι να το μεταγλωττίσουμε
Το όνομα του «εκτελέσιμου»
(συνήθως ίδιο με το όνομα του Το όνομα του αρχείου
αρχείου πηγαίου κώδικα χωρίς πηγαίου κώδικα
την κατάληξη)
Προγραμματισμός Ι
Δεν υπάρχουν συντακτικά λάθη!!
Power Shell σε Windows 10 (6/7)
Ενώ αν είχαμε λάθη...
ALT+SHIFT+3
(εμφάνιση
γραμμών)
Προγραμματισμός Ι
./όνομα_εκτελέσιμου
Προγραμματισμός Ι
Προγραμματισμός Ι
Εισαγωγή
Σύντομη Αναδρομή
Αναδρομή
Η γλώσσα προγραμματισμού C είναι μία γλώσσα υψηλού
επιπέδου
Δημιουργήθηκε από τον Dennis Richie στις αρχές της
δεκαετίας του 1970 στα εργαστήρια Bell Labs της εταιρείας
AT&T
Η γλώσσα ονομάστηκε C, γιατί πολλά από τα χαρακτηριστικά
της προήλθαν από μια παλαιότερη γλώσσα, η οποία είχε
αναπτυχθεί από τον Ken Thompson και ονομαζόταν “B”
Γιατί δημιουργήθηκε η C ?
Ο κύριος σκοπός της δημιουργίας της γλώσσας C ήταν η χρήση
της για την ανάπτυξη του λειτουργικού συστήματος UNIX
Προγραμματισμός Ι
Το πρότυπο ANSI (Ι)
Το πρόβλημα:
Η Γρήγορη και Άμεση Αποδοχή της C είχε σαν
αποτέλεσμα
διάφοροι οργανισμοί και εταιρείες να δημιουργούν τις δικές
τους εκδόσεις της γλώσσας, οι οποίες όμως εμφάνιζαν
διαφορές μεταξύ τους
η ύπαρξη πολλών εκδόσεων είχε σαν συνέπεια να
εμφανιστούν προβλήματα ασυμβατότητας, δηλαδή
προγράμματα τα οποία να μεταγλωττίζονται επιτυχώς με μία
έκδοση να μην μεταγλωττίζονται με κάποια άλλη
Η λύση (1983):
ANSI (American National Standard Institute)
ορισμός επιστημονικής επιτροπής για την καθιέρωση ενός
προτύπου της C, το οποίο να καθορίζει πλήρως τους
κανόνες, τα χαρακτηριστικά και τη λειτουργικότητα της
γλώσσας
Προγραμματισμός Ι
Προγραμματισμός Ι
Προγραμματισμός Ι
Κύκλος δημιουργίας ενός προγράμματος C
Το πρόγραμμα γράφεται σε έναν
Συγγραφή κώδικα (Edit) Editor Disk συντάκτη κειμένου και αποθηκεύεται
στον δίσκο με την κατάληξη .c
Ο μεταγλωττιστής μεταγλωττίζει το
Μεταγλώττιση (Compile) Compiler Disk πρόγραμμα σε κώδικα γλώσσας
μηχανής, δημιουργεί και αποθηκεύει
το αποτέλεσμα στο δίσκο ως αρχείο
με κατάληξη .ο (ή .obj)
Primary Memory
Εκτέλεση (Execute) CPU Η CPU παίρνει τις εντολές
του προγράμματος και τις
εκτελεί «σειριακά», πιθανώς
αποθηκεύοντας νέες τιμές
..
.. δεδομένων καθώς εκτελείται
..
το πρόγραμμα
Προγραμματισμός Ι
Το πρώτο πρόγραμμα
Προγραμματισμός Ι
Η οδηγία #include
#include <stdio.h>
Προγραμματισμός Ι
Παρατηρήσεις
Το αρχείο stdio.h συμπεριλαμβάνεται σχεδόν πάντα σε ένα C
πρόγραμμα, αφού περιέχει τις συναρτήσεις για εμφάνιση και
διάβασμα δεδομένων
Η εντολή printf()
printf("Ramones: Hey Ho, Let’s Go\n");
Οι εντολές γράφονται συνήθως μία σε κάθε γραμμή και
σχεδόν πάντα τελειώνουν με το ελληνικό ερωτηματικό (;)
Η εντολή που χρησιμοποιείται στο παραπάνω πρόγραμμα
είναι η printf()
Η printf() δηλώνεται μέσα στο αρχείο stdio.h και γι’
αυτό το λόγο συμπεριλαμβάνουμε αυτό το αρχείο με την
οδηγία #include
Η εντολή printf() χρησιμοποιείται για την εμφάνιση
δεδομένων στην οθόνη
Ο χαρακτήρας '\n' μέσα στην εντολή printf()
δημιουργεί μία νέα γραμμή μετά την εμφάνιση του
μηνύματος στην οθόνη
Ισοδυναμεί δηλ. με το πάτημα του πλήκτρου Enter
Προγραμματισμός Ι
Η εντολή return
return 0;
Στην απλούστερη μορφή της, η συνάρτηση main()
γράφεται όπως στο παράδειγμά μας, δηλαδή σαν
int main(void)
Η ειδική λέξη int υποδηλώνει ότι η συνάρτηση main()
πρέπει να επιστρέψει έναν ακέραιο αριθμό (integer) στο
λειτουργικό σύστημα
O ακέραιος αυτός αριθμός επιστρέφεται με την εντολή
return (που αποτελεί δεσμευμένη λέξη της C)
Κατά σύμβαση, όταν ο αριθμός που επιστρέφεται είναι
το μηδέν (0), τότε σημαίνει ότι το πρόγραμμά μας
τερματίστηκε κανονικά
Προγραμματισμός Ι
Παρατηρήσεις (I)
Ένα πρόγραμμα γραμμένο σε C πρέπει να περιέχει ΜΟΝΟ ΜΙΑ
συνάρτηση main()
Δηλ.
int main(void)
{
...
}
Προγραμματισμός Ι
Παρατηρήσεις (II)
Η δεσμευμένη λέξη void μέσα στις παρενθέσεις
δηλώνει ρητά ότι η συνάρτηση main() δεν δέχεται
κάποια ορίσματα
Προγραμματισμός Ι
Επίσης σχόλιο είναι και το κείμενο στην ίδια γραμμή μετά από //
Προγραμματισμός Ι
Εισαγωγή Σχολίων σε πρόγραμμα (ΙΙ)
π.χ.
π.χ.
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις
Η χρήση των πλάγιων Αντίθετα, η χρήση των /* */ για
καθέτων // σαν ένδειξη εισαγωγή σχολίων υποστηρίζεται από
εισαγωγής σχολίων δεν είναι όλους τους C μεταγλωττιστές, αφού
σύμφωνη με το ANSI C υποστηρίζεται από το ANSI C πρότυπο
πρότυπο
Προτείνεται η εισαγωγή περιγραφικών
Άρα, αν και υπάρχουν σχολίων σε πολύπλοκα σημεία του
μεταγλωττιστές που την κώδικα, ώστε ο κώδικας να γίνεται πιο
υποστηρίζουν, δεν είναι κατανοητός τόσο στον ίδιο τον
υποχρεωτικό να προγραμματιστή όσο και σε συνεργάτες
υποστηρίζεται από όλους τους του που ενδέχεται να πρέπει να
C μεταγλωττιστές κατανοήσουν τον κώδικά του
Προγραμματισμός Ι
Μεταγλώττιση Προγράμματος
Όταν έχουμε γράψει τον κώδικα του προγράμματός μας π.χ.
αρχείο my_example.c, θα πρέπει αρχικά να τον
μεταγλωττίσουμε (να κάνουμε compilation) στη γλώσσα που
αντιλαμβάνεται ο υπολογιστής (γλώσσα μηχανής)
Προγραμματισμός Ι
Σύνδεση Προγράμματος (1/2)
Η επόμενη διαδικασία πραγματοποιείται από το πρόγραμμα
σύνδεσης (linker), το οποίο συνδέει τον κώδικα αντικείμενου που
δημιουργήθηκε στη φάση μεταγλώττισης με πρόσθετο κώδικα που
χρειάζεται για τη δημιουργία του τελικού εκτελέσιμου
Προγραμματισμός Ι
Προγραμματισμός Ι
Εκτέλεση Προγράμματος
Η εκτέλεση ενός προγράμματος γίνεται με αρκετούς τρόπους
$ a.out
./a.out
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Η C είναι μία γλώσσα προγραμματισμού που κάνει διάκριση μεταξύ πεζών και
κεφαλαίων γραμμάτων (case sensitive)
Δηλαδή, αν γράψουμε Printf() αντί για printf() ο μεταγλωττιστής
θα εμφανίσει μήνυμα λάθους, γιατί ο χαρακτήρας 'P' είναι διαφορετικός
από τον χαρακτήρα 'p'
Προγραμματισμός Ι
Παρατηρήσεις (ΙI)
O μεταγλωττιστής ανιχνεύει λανθασμένη εφαρμογή των κανόνων
της γλώσσας που τον εμποδίζει να μεταγλωττίσει το πρόγραμμα
σωστά (π.χ. ορθογραφικά λάθη, συντακτικά λάθη, αδήλωτες
μεταβλητές, ...) και όχι λάθη λογικής που ενδέχεται να
περιέχονται στο πρόγραμμά σας
Προγραμματισμός Ι
Παρατηρήσεις (ΙII)
Π.χ. αν θέλετε να δημιουργήσετε ένα πρόγραμμα που να εμφανίζει τη λέξη
OLE, μόνο αν η τιμή μίας ακέραιας μεταβλητής a είναι μεγαλύτερη από 5,
και εσείς γράψετε:
Τα λογικά λάθη ονομάζονται και bugs και είναι λάθη τα οποία εισάγει άθελά
του ο προγραμματιστής και μόνο αυτός μπορεί να τα εντοπίσει και να τα
διορθώσει
Κάθε θέση μνήμης μπορεί να έχει ένα όνομα και ένα περιεχόμενο
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις
Το όνομα που επιλέγετε να δώσετε σε μία μεταβλητή είναι
χρήσιμο να περιγράφει όσο το δυνατόν καλύτερα τον σκοπό της
μεταβλητής μέσα στο πρόγραμμα, ώστε ο κώδικας να είναι πιο
ευανάγνωστος
Π.χ. το όνομα μίας μεταβλητής που υπολογίζει το άθροισμα
κάποιων αριθμών είναι προτιμότερο να είναι sum αντί για
var
Δήλωση Μεταβλητών
Για να χρησιμοποιήσετε μία μεταβλητή μέσα σε ένα πρόγραμμα
πρέπει πρώτα να τη δηλώσετε
τύπος_δεδομένων όνομα_μεταβλητής;
Προγραμματισμός Ι
Τύποι Μεταβλητών
Συνηθισμένο μέγεθος Εύρος τιμών Ψηφία
Τύπος
(bytes) (min-max) ακρίβειας
Π.χ.
int a; /* Δήλωση ακέραιας μεταβλητής με όνομα a. */
float b; /* Δήλωση πραγματικής μεταβλητής με όνομα b. */
Προγραμματισμός Ι
Παρατηρήσεις (1/3)
Πολλές μεταβλητές του ίδιου τύπου μπορούν να δηλωθούν στην ίδια
γραμμή, αρκεί να διαχωρίζονται μεταξύ τους με κόμμα (,)
Δηλαδή, αντί να δηλώσετε τις μεταβλητές a, b και c σε τρεις
ξεχωριστές γραμμές:
int a;
int b;
int c;
μπορείτε να τις δηλώσετε σε μία γραμμή ως εξής:
int a, b, c;
Προγραμματισμός Ι
Παρατηρήσεις (3/3)
Να χρησιμοποιείτε τον τύπο float μόνο όταν η ακρίβεια των
δεκαδικών ψηφίων δεν είναι τόσο σημαντική στο πρόγραμμά σας
#include <stdio.h>
int main(void)
{ Μεγάλη ήττα...!!!
float a = 3.1; Περιμέναμε η έξοδος του
προγράμματος να είναι Yes,
if(a == 3.1) αλλά εμφανίζει... No !!!!
printf("Yes\n"); Αν δηλώναμε τη μεταβλητή a
else ως double θα εμφάνιζε
printf("No\n");
σίγουρα Yes
return 0;
}
Προγραμματισμός Ι
Εκχώρηση τιμών σε Μεταβλητές (Ι)
Η εκχώρηση μίας τιμής σε μία μεταβλητή γίνεται είτε μαζί με
τη δήλωση της μεταβλητής είτε αργότερα
int a;
a = 100;
Προγραμματισμός Ι
int a = 0100;
int a = 0x10;
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Η τιμή μίας μεταβλητής μπορεί (προφανώς) να αλλάζει μέσα στο
πρόγραμμα
Όταν γίνεται χρήση μίας μεταβλητής στο πρόγραμμα
χρησιμοποιείται πάντα η τελευταία τιμή της και όχι κάποια από
τις προηγούμενες τιμές της
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
Η τιμή που εκχωρείται σε μία μεταβλητή πρέπει να συμβαδίζει με
τον τύπο της μεταβλητής
Π.χ. με την εντολή:
int a = 10.9;
η τιμή της μεταβλητής a γίνεται 10, γιατί η μεταβλητή a
δηλώνεται σαν ακέραια μεταβλητή και όχι σαν πραγματική και το
δεκαδικό μέρος αποκόπτεται (Προσοχή!! Δεν στρογγυλοποιείται)
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙΙ)
Η τιμή μίας πραγματικής μεταβλητής μπορεί να είναι και ακέραια
Π.χ. επιτρέπεται να γράψουμε:
float a = 50;
γιατί είναι ισοδύναμο με:
float a = 50.0;
Η τιμή μίας πραγματικής μεταβλητής μπορεί να γραφεί και με
επιστημονική σημειογραφία (συνήθως χρησιμοποιείται όταν η τιμή
είναι πολύ μικρή ή πολύ μεγάλη)
Π.χ. αντί για
a = 0.085;
μπoρούμε να γράψουμε
a = 85E-3;
Το γράμμα Ε ή e αναπαριστά το 10, ενώ ο αριθμός που το
ακολουθεί είναι η θετική ή αρνητική δύναμη του 10.
Σταθερές (Ι)
Σταθερά ονομάζεται μία μεταβλητή που η τιμή της δεν μπορεί να
αλλάξει μέσα στο πρόγραμμα
Για να δηλωθεί μία μεταβλητή σαν σταθερά, πρέπει να προηγηθεί
η λέξη const πριν (ή μετά) από τον τύπο της μεταβλητής
Επίσης, μαζί με τη δήλωση της σταθεράς, πρέπει να της
εκχωρηθεί και μία αρχική τιμή, η οποία δεν θα μπορεί να αλλάξει
μέσα στο πρόγραμμα
Π.χ. η εντολή:
#define NUM 100
δηλώνει τη μακροεντολή με όνομα NUM και τιμή 100
Παρατηρήσεις
Οι δηλώσεις των μακροεντολών με την οδηγία #define είναι
προτιμότερο να γίνονται πριν από τη συνάρτηση main()
Τα ονόματα των μακροεντολών με την οδηγία #define συνηθίζεται να
δηλώνονται με κεφαλαία γράμματα
Στο τέλος της οδηγίας #define δεν μπαίνει ελληνικό ερωτηματικό (;)
Π.χ.
vs.
Προγραμματισμός Ι
const vs. #define
Μπορούμε να δημιουργήσουμε ονόματα σταθερών, χρησιμοποιώντας
είτε τη λέξη-κλειδί const είτε με τον ορισμό μακροεντολής
(#define), αλλά υπάρχουν αρκετές σημαντικές διαφορές μεταξύ των
δύο τρόπων δημιουργίας σταθερών
Η συνάρτηση printf()
Η συνάρτηση printf() χρησιμοποιείται για την εμφάνιση δεδομένων
στο αρχείο εξόδου stdout (standard output stream) , το οποίο εξ’
ορισμού συνδέεται με την οθόνη
Προγραμματισμός Ι
Προσδιοριστικό Μετατροπής
Ένα προσδιοριστικό μετατροπής (conversion specification)
αρχίζει με τον χαρακτήρα % και ακολουθείται από έναν ή
περισσότερους χαρακτήρες μετατροπής που έχουν ειδική σημασία
Προγραμματισμός Ι
Παραδείγματα (Ι)
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Προγραμματισμός Ι
Εμφάνιση μεταβλητών
Τα ονόματα των μεταβλητών εισάγονται στην printf() μετά τα
διπλά εισαγωγικά (" ") με τη χρήση κόμματος (,) και αν οι
μεταβλητές είναι περισσότερες από μία πρέπει και αυτές να
διαχωρίζονται μεταξύ τους με κόμμα (,)
Προγραμματισμός Ι
Παράδειγμα
Προγραμματισμός Ι
Προαιρετικά Πεδία
Ένα προσδιοριστικό μετατροπής, στην απλή μορφή
του, αρχίζει με τον χαρακτήρα % και ακολουθείται από
τον κατάλληλο χαρακτήρα μετατροπής
%
% +
flag 8
width .3 L
precision modifier
g
type
flags
σημαία ακρίβεια
Ακρίβεια
Όταν εμφανίζουμε την τιμή μίας πραγματικής μεταβλητής (τύπου float ή
double) μπορούμε να καθορίσουμε πόσα ψηφία ακρίβειας θα
εμφανιστούν στην οθόνη
Προγραμματισμός Ι
Προγραμματισμός Ι
Πλάτος Πεδίου
Όταν εμφανίζουμε την τιμή μίας ακέραιας ή πραγματικής μεταβλητής
μπορούμε να καθορίσουμε το συνολικό πλήθος των χαρακτήρων που θα
εμφανιστούν στην οθόνη, μαζί με τα ψηφία ακρίβειας και την
υποδιαστολή
Παράδειγμα
Προγραμματισμός Ι
Πρόθεμα
Για την εμφάνιση ενός short ακεραίου μπορεί να χρησιμοποιηθεί
προαιρετικά το γράμμα h, ενώ για την εμφάνιση ενός long
ακεραίου μπορεί να χρησιμοποιηθεί το γράμμα l ή L, όπως
φαίνεται στο παρακάτω παράδειγμα
Προγραμματισμός Ι
Σημαίες
Οι σημαίες χρησιμοποιούνται για περαιτέρω
μορφοποίηση των εμφανιζόμενων τιμών, όπως φαίνεται
στον παρακάτω πίνακα
Προγραμματισμός Ι
Παράδειγμα
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Οταν χρησιμοποιείτε συχνά μία πραγματική μεταβλητή σε διάφορες
εκφράσεις μέσα στο πρόγραμμα (π.χ. συγκρίσεις, πράξεις, ...), τότε να
προτιμάτε τον τύπο double και όχι τον τύπο float, γιατί είναι πιθανό
να μην γίνει η διαχείριση των δεκαδικών ψηφίων με τον τρόπο που θα
αναμένατε
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
Αν θέλετε η ακολουθία χαρακτήρων της printf(), για λόγους
εμφάνισης, να εκτείνεται σε περισσότερες από μία γραμμές στον κώδικά
σας, τότε να χρησιμοποιείτε τον χαρακτήρα της ανάστροφης κεκλιμένης
'\' (backslash)
Λόγω της ειδικής σημασίας του χαρακτήρα %, για την εμφάνιση του
χαρακτήρα '%' πρέπει να γραφούν δύο χαρακτήρες %
Προγραμματισμός Ι
(τύπος_δεδομένων) (παράσταση)
Η έκφραση (float)i
προσαρμόζει προσωρινά τον
τύπο της μεταβλητής i από
int σε float, έτσι ώστε
το αποτέλεσμα της διαίρεσης
να είναι πραγματικός
αριθμός
Προγραμματισμός Ι
Προγραμματισμός Ι
Είσοδος Δεδομένων
Η συνάρτηση scanf()
Η συνάρτηση scanf() χρησιμοποιείται για την είσοδο δεδομένων από
ένα αρχείο εισόδου, το οποίο ονομάζεται stdin (standard input
stream) και εξ’ ορισμού συνδέεται με το πληκτρολόγιο
Παράδειγμα 1
Π.χ.
int i;
scanf("%d", &i);
Προγραμματισμός Ι
Παράδειγμα 2 (Ι)
Μπορούμε να χρησιμοποιήσουμε τη συνάρτηση scanf() για να διαβάσουμε
περισσότερες από μία τιμές από το πληκτρολόγιο και να τις αποθηκεύσουμε
ως τιμές σε κάποιες μεταβλητές του προγράμματος
Π.χ.
int i;
float j;
scanf("%d%f", &i, &j);
H πρώτη παράμετρος της scanf() είναι το αλφαριθμητικό μορφοποίησης
%d%f, ενώ οι επόμενες παράμετροι είναι οι διευθύνσεις μνήμης των
μεταβλητών i και j αντίστοιχα
Το %d αντιστοιχεί στη διεύθυνση της μεταβλητής i
Το %f αντιστοιχεί στη διεύθυνση της μεταβλητής j
Δηλαδή η αντιστοίχιση γίνεται ένα προς ένα και από αριστερά προς τα δεξιά
Παράδειγμα 2 (ΙΙ)
Στο προηγούμενο παράδειγμα, αν ο χρήστης εισάγει π.χ. τις τιμές
10 και 4.65, αυτές θα πρέπει να απέχουν μεταξύ τους ένα ή
περισσότερα κενά
Προγραμματισμός Ι
Παραδείγματα 3 & 4
Στο επόμενο παράδειγμα, η scanf() διαβάζει έναν χαρακτήρα και τον
αποθηκεύει στη μεταβλητή ch
char ch;
scanf("%c", &ch);
Στο επόμενο παράδειγμα, η scanf() διαβάζει ένα αλφαριθμητικό και το
αποθηκεύει στον πίνακα χαρακτήρων str
Παρατηρήστε, ότι πριν από τη μεταβλητή str δεν χρησιμοποιείται ο
τελεστής &, γιατί - όπως θα δούμε στο κεφάλαιο των “Πινάκων της C”- το
όνομα ενός πίνακα ισοδυναμεί με τη διεύθυνση του πρώτου στοιχείου του
char str[100];
scanf("%s", str);
Aν ο χρήστης εισάγει το αλφαριθμητικό sample και πατήσει Enter, τότε οι
χαρακτήρες του θα αποθηκευτούν στις αντίστοιχες θέσεις του πίνακα str
Δηλαδή, η τιμή του str[0] θα γίνει 's', του str[1] θα γίνει 'a', του
str[2] θα γίνει 'm', κ.ο.κ.
Το παράδειγμα αυτό θα το κατανοήσετε καλύτερα αργότερα, αφού θα
μιλήσουμε για πίνακες, χαρακτήρες και αλφαριθμητικά
Προγραμματισμός Ι
Παρατηρήσεις
Να θυμάστε ότι η scanf() απαιτεί τον τελεστή διεύθυνσης & πριν από
το όνομα κάθε αριθμητικής μεταβλητής (π.χ. int, double, char,
float, …)
π.χ.: scanf("%[^\n]",str);
Προγραμματισμός Ι
Τί επιστρέφει η συνάρτηση scanf() ???
Η συνάρτηση scanf() επιστρέφει έναν ακέραιο αριθμό που δηλώνει
πόσα από τα δεδομένα εισόδου διαβάστηκαν και εκχωρήθηκαν στις
μεταβλητές του προγράμματος, ενώ οι τιμές που δεν διαβάστηκαν
παραμένουν στο stdin
Παρατηρήσεις
Η συνάρτηση scanf() δεν είναι μία ασφαλής συνάρτηση και πρέπει να
τη χρησιμοποιείτε με μεγάλη προσοχή
Σε επαγγελματικές εφαρμογές πρέπει να ελέγχετε την τιμή επιστροφής
της
#include <stdio.h>
int main(void)
{
int a, b;
scanf("%d , %d", &a, &b);
printf("%d %d\n", a, b);
return 0;
}
Για να λειτουργήσει σωστά αυτό το πρόγραμμα πρέπει οι ακέραιες τιμές
που θα εισάγει ο χρήστης να διαχωρίζονται μεταξύ τους με κόμμα (,)
Προγραμματισμός Ι
#include <stdio.h>
int main(void)
{
int a, b;
scanf("%dm%d", &a, &b);
printf("%d %d\n", a, b);
return 0;
}
Παράδειγμα (Ι)
Η συνάρτηση scanf() δεν διαβάζει τον χαρακτήρα νέας γραμμής που
πληκτρολογεί ο χρήστης στο τέλος της εισαγωγής δεδομένων
Προγραμματισμός Ι
Παράδειγμα (ΙΙ)
Αν αντιστρέψουμε στο προηγούμενο παράδειγμα τη σειρά του
διαβάσματος, τότε το πρόγραμμα θα εκτελεστεί σωστά, αφού –
σύμφωνα με προηγούμενη παρατήρηση – ο χαρακτήρας νέας
γραμμής που υπάρχει πριν από την αριθμητική τιμή αγνοείται
Προγραμματισμός Ι
while(getchar() != '\n');
fflush(stdin);
Προγραμματισμός Ι 16
Παραδείγματα (2)
Γράψτε ένα πρόγραμμα, το οποίο να διαβάζει δύο ακέραιες τιμές, να τις
αποθηκεύει σε δύο ακέραιες μεταβλητές και να αντιμεταθέτει τις τιμές
τους
Προγραμματισμός Ι 17
Προγραμματισμός Ι
Τελεστές
Ο τελεστής εκχώρησης =
Ο τελεστής = χρησιμοποιείται για την απόδοση τιμής (ή αλλιώς ανάθεση
τιμής) σε μία μεταβλητή
Π.χ. με την εντολή:
a = 10;
η τιμή της μεταβλητής a γίνεται 10 (μπορούμε επίσης να πούμε ότι στη
μεταβλητή a εκχωρήθηκε η τιμή 10)
int a, b, c;
a = b = 10 = c;
printf("%d %d %d\n",a,b,c);
Παρατηρήσεις (IΙ)
Ο δεξιός τελεστέος (right operand) πρέπει να είναι τύπου rvalue,
δηλ. μία έκφραση που έχει τιμή, όπως μία σταθερά ή μία μεταβλητή
10 = a; /* Δεν επιτρέπεται. */
a+b = 20; /* Δεν επιτρέπεται. */
Αν ο τύπος της μεταβλητής δεν είναι ίδιος με τον τύπο της τιμής,
τότε, εφόσον η μετατροπή είναι δυνατή, η τιμή πρώτα
μετατρέπεται στον τύπο της μεταβλητής και μετά εκχωρείται σε
αυτήν
Π.χ.
int a;
float b;
b = a = 10.96;
Προγραμματισμός Ι
Παρατηρήσεις (IV)
Σε περίπτωση υπερχείλισης (overflow), σε υπολογισμούς με τιμές
προσημασμένων μεταβλητών όπως π.χ. κατά την πρόσθεση δύο
μεγάλων ακεραίων, το αποτέλεσμα δεν θα έχει νόημα και δεν είναι
δυνατόν να προσδιοριστεί
int a, b, c, d;
a = 11;
b = 3;
c = a%b;
d = a%c%b;
Παρατηρήσεις (ΙΙ)
Οι πέντε αυτοί τελεστές λέγονται και «δυαδικοί» (binary), επειδή
απαιτούν δύο τελεστέους
Προγραμματισμός Ι
Έξοδος: a = 5 b = 4 Έξοδος: a = 5 b = 5
Προγραμματισμός Ι
Ο τελεστής μείωσης --
Ο τελεστής μείωσης -- μπαίνει πριν ή μετά από το
όνομα μίας μεταβλητής
Παραδείγματα
Ποια είναι η έξοδος του καθενός προγράμματος?
Προγραμματισμός Ι
Παρατηρήσεις
Μην εφαρμόζετε τους τελεστές ++ και –- ταυτόχρονα στην ίδια
μεταβλητή και μην δημιουργείτε εκφράσεις των οποίων η τελική
τιμή εξαρτάται από τη σειρά που μπορεί να εφαρμοστούν οι επί
μέρους τελεστές
a * a++;
Προγραμματισμός Ι
Π.χ.
Προγραμματισμός Ι
Τελεστές Σύγκρισης (ΙΙ)
Μία έκφραση χαρακτηρίζεται αληθής (true), όταν η τιμή της είναι
διαφορετική από το μηδέν, ενώ - αν είναι μηδέν- χαρακτηρίζεται
ψευδής (false)
Π.χ. το αποτέλεσμα της έκφρασης (a > 10) είναι ένα (1) μόνο
αν η τιμή της μεταβλητής a είναι μεγαλύτερη από το 10, αλλιώς
είναι μηδέν (0)
Έξοδος: 1 0
Προγραμματισμός Ι
Παρατηρήσεις
Μην συγχέετε τον τελεστή ελέγχου ισότητας (==) με τον τελεστή
εκχώρησης (=)
a = 10
είναι πάντοτε 1 και η έκφραση εκχωρεί την τιμή 10 στη
μεταβλητή a (η εκχώρηση μη μηδενικής τιμής είναι πάντα αληθής
έκφραση, ενώ η εκχώρηση του μηδενός είναι πάντα ψευδής
έκφραση, αντίστοιχα)
Προγραμματισμός Ι
Ο τελεστής !
Ο τελεστής ! είναι μοναδιαίος, δηλαδή εφαρμόζεται σε
έναν μόνο τελεστέο
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος:
Έξοδος: Num = 0
Έξοδος: Num = 1
Προγραμματισμός Ι
Παρατηρήσεις
Συνήθως, ο τελεστής ! χρησιμοποιείται σε συνθήκες
ελέγχου στην εντολή if
Π.χ.
η εντολή:
if(!a)
είναι ισοδύναμη με
if(a == 0)
και η εντολή:
if(a)
είναι ισοδύναμη με
if(a != 0)
Προγραμματισμός Ι
Συνδυαστικοί τελεστές
Οι συνδυαστικοί τελεστές χρησιμοποιούνται για να γραφούν μαθηματικές
εκφράσεις με πιο σύντομο τρόπο, βάσει του παρακάτω τύπου:
Π.χ. η έκφραση:
a += b;
είναι ισοδύναμη με:
a = a + b;
ενώ η έκφραση:
a *= 3;
είναι ισοδύναμη με:
a = a * 3;
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος:
Έξοδος: Num = 2
Προγραμματισμός Ι
Λογικοί τελεστές
Ο τελεστής &&
Η τιμή μίας έκφρασης που περιέχει τον τελεστή && είναι ένα (1),
δηλαδή αληθής, μόνο αν όλοι οι όροι της έκφρασης είναι αληθείς
η τιμή της έκφρασης που περιέχει τον τελεστή && είναι μηδέν (0),
δηλαδή ψευδής, αν έστω και ένας όρος έχει ψευδή τιμή
Ο τελεστής && εφαρμόζει δηλαδή τη λογική πράξη ΚΑΙ (λογική
πράξη AND) μεταξύ των όρων στους οποίους εφαρμόζεται
Ο τελεστής ||
Μία έκφραση που περιέχει τον τελεστή || είναι ένα (1), δηλαδή
αληθής, αν έστω και ένας όρος της έκφρασης είναι αληθής
Μία έκφραση που περιέχει τον τελεστή || είναι μηδέν (0), δηλαδή
ψευδής, αν κανένας όρος της έκφρασης δεν είναι αληθής
Ο τελεστής || εφαρμόζει δηλαδή τη λογική πράξη Ή (λογική
πράξη OR) μεταξύ των όρων στους οποίους εφαρμόζεται
Προγραμματισμός Ι
Παραδείγματα
Η έκφραση (10 == 10) && (5 > 3) είναι αληθής, γιατί και οι
δύο όροι της έκφρασης είναι αληθείς
Αν γράφαμε:
a = (10 == 10) && (5 > 3); τότε η τιμή της μεταβλητής a
θα γινόταν ίση με 1
Προγραμματισμός Ι
Παραδείγματα
Η έκφραση (10 == 10) || (3 > 5) είναι αληθής, γιατί ένας
όρος της έκφρασης είναι αληθής
Αν γράφαμε:
a = (10 == 10) || (3 > 5); τότε η τιμή της μεταβλητής a
θα γινόταν ίση με 1
Προγραμματισμός Ι
Παρατηρήσεις
Αν ο όρος που ελέγχεται σε μία έκφραση με τον τελεστή && έχει
ψευδή τιμή, τότε ο μεταγλωττιστής δεν ελέγχει τους υπόλοιπους
όρους και θέτει κατευθείαν την τιμή της συνολικής έκφρασης ίση
με 0
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος?
Έξοδος: 1
0
Προγραμματισμός Ι
Ο τελεστής ,
Ο τελεστής κόμμα (,) διαχωρίζει επί μέρους εκφράσεις οι
οποίες αποτελούν μία έκφραση:
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος?
Έξοδος: 50
Προγραμματισμός Ι
Παρατηρήσεις
Δεδομένου ότι η χρήση του τελεστή κόμμα (,) μπορεί να οδηγήσει
σε δυσνόητο και περίπλοκο κώδικα, καλό θα ήταν να αποφεύγεται
int a, b;
for(a = 1, b = 2; b < 10; a++, b++)
Ο τελεστής sizeof
Ο τελεστής sizeof υπολογίζει τις οκτάδες που δεσμεύει στη μνήμη του
υπολογιστή ο τύπος δεδομένων ή η μεταβλητή που δηλώνεται στις
παρενθέσεις του
Π.χ.
Προγραμματισμός Ι
Ο τύπος enum (Ι)
Ο τύπος απαρίθμησης enum (enumeration type) χρησιμοποιείται
για να οριστεί ένα σύνολο ακεραίων με συγκεκριμένα ονόματα και
σταθερές τιμές
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις
Θυμηθείτε ότι η οδηγία #define αποτελεί έναν εναλλακτικό τρόπο
δήλωσης συμβολικών ονομάτων που αντιστοιχούν σε συγκεκριμένες
τιμές
Προγραμματισμός Ι
Οι τελεστές bit
Οι τελεστές bit χρησιμοποιούνται για το χειρισμό των bits μίας
ακέραιας μεταβλητής ή σταθεράς
Ο τελεστής &
Ο τελεστής & εφαρμόζει τη λογική πράξη AND (λογική πράξη
ΚΑΙ) στα bits των δύο τελεστέων και θέτει το bit εξόδου στο 1
μόνο αν τα αντίστοιχα bits και στους δύο τελεστέους είναι 1,
αλλιώς, το bit εξόδου τίθεται στο 0
Π.χ. το αποτέλεσμα της πράξης 19 & 2 είναι 2
Μην συγχέετε τους τελεστές && και & (π.χ., αν a=1 και b=2, το
αποτέλεσμα της έκφρασης a && b είναι 1, ενώ το αποτέλεσμα
της έκφρασης a & b είναι 0)
Προγραμματισμός Ι
Ο τελεστής |
Ο τελεστής | εφαρμόζει τη λογική πράξη OR (λογική πράξη Ή)
στα bits των δύο τελεστέων και θέτει το bit εξόδου στο 0 μόνο
αν τα αντίστοιχα bits και στους δύο τελεστέους είναι 0, αλλιώς,
το bit εξόδου τίθεται στο 1
Π.χ. το αποτέλεσμα της πράξης 19 | 6 είναι 23
Ο τελεστής ^
Ο τελεστής ^ εφαρμόζει τη λογική πράξη XOR (eXclusive OR ,
αποκλειστικό Ή) στα bits των δύο τελεστέων και θέτει το bit
εξόδου στο 1 μόνο αν τα αντίστοιχα bits και στους δύο
τελεστέους είναι διαφορετικά μεταξύ των, αλλιώς, το bit τίθεται
στο 0
Προγραμματισμός Ι
Ο τελεστής ~
Ο τελεστής συμπληρώματος ~ είναι μοναδιαίος, δηλαδή
εφαρμόζεται σε έναν τελεστέο και εφαρμόζει τη λογική πράξη
NOT (λογική πράξη ΔΕΝ)
Προγραμματισμός Ι
Οι τελεστές ολίσθησης
Οι τελεστές ολίσθησης (>> και <<) μετατοπίζουν τα bits μίας
ακέραιας μεταβλητής ή σταθεράς κατά ένα συγκεκριμένο αριθμό
θέσεων, όπως δείχνουν τα «νοητά βέλη»
Προγραμματισμός Ι
Ο τελεστής >>
Η έκφραση i >> n μετατοπίζει τα bits της μεταβλητής i κατά
n θέσεις δεξιά και τοποθετεί μηδενικά στα n υψηλότερης τάξης
bits της μεταβλητής
Προγραμματισμός Ι
Ο τελεστής <<
Η έκφραση i << n μετατοπίζει τα bits της μεταβλητής i κατά
n θέσεις αριστερά και τοποθετεί μηδενικά στα n χαμηλότερης
τάξης bits της μεταβλητής
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Όταν χρησιμοποιείται ο τελεστής << και το αποτέλεσμα
αποθηκεύεται σε μία μεταβλητή, ο τύπος δεδομένων της μεταβλητής
πρέπει να είναι τέτοιος ώστε να μπορεί να αποθηκευτεί η τελική τιμή
Παρατηρήσεις (ΙΙ)
Επειδή η θέση ενός bit αντιστοιχεί σε μία δύναμη του 2:
Προγραμματισμός Ι
Προτεραιότητα Τελεστών
Κάθε τελεστής χαρακτηρίζεται από μία προτεραιότητα
Πίνακας Προτεραιοτήτων
Θέση Τελεστές Συσχέτιση
1 ()(παρενθέσεις-κλήση συνάρτησης) [] -> . αριστερά προς δεξιά
++(επιθεματική αύξηση) --(επιθεματική μείωση)
2 ++(προθεματική αύξηση) --(προθεματική μείωση) ! ~ δεξιά προς αριστερά
*(έμμεση αναφορά) &(διεύθυνση) +(μοναδιαίο +) –
(μοναδιαίο -) (προσαρμογή τύπου) sizeof
3 *(πολλαπλασιασμός) / % αριστερά προς δεξιά
Προγραμματισμός Ι
Παρατηρήσεις
Όπως φαίνεται στον πίνακα προτεραιοτήτων, κάθε τελεστής
χαρακτηρίζεται από μία προτεραιότητα
Προγραμματισμός Ι
Έλεγχος Προγράμματος
Η εντολή if (Ι)
Η εντολή if είναι μία από τις βασικότερες δομές ελέγχου ροής
στη C, αλλά και στις περισσότερες γλώσσες προγραμματισμού
if(συνθήκη)
{
... /* ομάδα εντολών */
}
Προγραμματισμός Ι
Η εντολή if (ΙΙ)
Αν η συνθήκη είναι αληθής (true), τότε εκτελούνται οι εντολές
που περικλείονται στα άγκιστρα {...}
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Αν το μπλοκ εντολών περιέχει μόνο μία εντολή, τότε τα άγκιστρα
μπορούν να παραλειφθούν
Π.χ.
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
ΠΡΟΣΟΧΗ!!!
Μην βάζετε το ελληνικό ερωτηματικό ; στο τέλος της if
εντολής, γιατί ουσιαστικά το ερωτηματικό τερματίζει στο σημείο
εκείνο την εντολή if
Προγραμματισμός Ι
Παρατηρήσεις (ΙV)
ΠΡΟΣΟΧΗ!!!
H εκχώρηση μίας μη μηδενικής τιμής σε μία μεταβλητή ισοδυναμεί
με αληθή συνθήκη, ενώ η εκχώρηση μηδενικής τιμής ισοδυναμεί
με ψευδή συνθήκη
Προγραμματισμός Ι
Παρατηρήσεις (V)
Η έκφραση:
H έκφραση:
Προγραμματισμός Ι
Παρατηρήσεις (VΙ)
Ορισμένοι προγραμματιστές προτιμούν να γράφουν πρώτα τη
σταθερά, όταν θέλουν να συγκρίνουν την τιμή μιας μεταβλητής με
μία σταθερά, π.χ. :
if(-20 == x) /* Αντί για if(x == -20) */
Ο λόγος είναι ότι σε περίπτωση που ξεχάσουν το ένα «ίσον» (=),
ο μεταγλωττιστής θα εμφανίσει μήνυμα λάθους, δεδομένου ότι δεν
επιτρέπεται να ανατεθεί η τιμή μιας μεταβλητής σε μία σταθερά
Προγραμματισμός Ι
Η εντολή if...else (I)
Όταν θέλουμε να προσδιορίσουμε μία ομάδα εντολών που θα
εκτελεστεί όταν μία συνθήκη είναι αληθής (true) και μία άλλη ομάδα
εντολών που θα εκτελεστεί όταν η συνθήκη αυτή είναι ψευδής
(false), τότε χρησιμοποιούμε την εντολή ελέγχου if...else
if(συνθήκη)
{
... /* ομάδα εντολών A */
}
else
{
... /* ομάδα εντολών B */
}
Προγραμματισμός Ι
Π.χ.
Προγραμματισμός Ι
Παρατηρήσεις
Θυμηθείτε ότι στην περίπτωση της εντολής if, αν η ομάδα εντολών
περιέχει μόνο μία εντολή, τότε τα άγκιστρα μπορούν να
παραλειφθούν.
Προγραμματισμός Ι
?
?
Παράδειγμα
Παράδειγμα
Γράψτε ένα πρόγραμμα που να διαβάζει δύο δεκαδικούς αριθμούς
(π.χ., a και b) και εμφανίζει τη λύση (αν υπάρχει) της εξίσωσης:
a*x + b = 0
Προγραμματισμός Ι
Ο τελεστής ?: (Ι)
Ο τελεστής ?: επιτρέπει την εκτέλεση μίας από δύο ενέργειες,
σύμφωνα με την τιμή μίας έκφρασης και η σύνταξή του είναι:
exp1 ? exp2 : exp3;
Σε μία εντολή με τον τελεστή ?: αν η έκφραση exp1 είναι αληθής,
τότε θα εκτελεστεί η έκφραση που ακολουθεί το ερωτηματικό ?
(δηλαδή η exp2), αλλιώς θα εκτελεστεί η έκφραση που ακολουθεί
την άνω-κάτω τελεία : (δηλαδή η exp3)
Π.χ.
Ο τελεστής ?: (ΙΙ)
Η τιμή μίας έκφρασης με τον τελεστή ?: είναι ίση με την τιμή της
έκφρασης που εκτελείται τελευταία
Ποια είναι η τιμή της μεταβλητής max στην παρακάτω έκφραση ;
max = (a > b)? a : b;
Η παραπάνω έκφραση είναι ισοδύναμη με:
if(a > b)
max = a;
else
max = b;
Π.χ.
if(exp1)
k = exp2;
else if(add1)
k = add2;
else
k = add3;
Προγραμματισμός Ι
Παράδειγμα
Τι κάνει το παρακάτω πρόγραμμα???
Προγραμματισμός Ι
Η εντολή switch (I)
Η εντολή ελέγχου
switch
χρησιμοποιείται
εναλλακτικά έναντι της
if-else-if δομής,
όταν επιθυμούμε να
ελέγξουμε μία έκφραση
για όλες τις δυνατές
τιμές που αυτή η
έκφραση μπορεί να
πάρει και να
χειριστούμε την κάθε
περίπτωση με
διαφορετικό τρόπο
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις (I)
Η ύπαρξη της default περίπτωσης στην εντολή switch δεν
είναι υποχρεωτική (όπως δεν ήταν υποχρεωτική και η ύπαρξη της
εντολής else στην εντολή if)
Προγραμματισμός Ι
Παρατηρήσεις (III)
Η τελευταία break σε μία εντολή switch μπορεί να
παραλειφθεί, αφού ούτως ή άλλως η switch τερματίζεται με
το άγκιστρο κλεισίματός της }
Έξοδος:
Α) Two
End
Β) One
Two
End
Γ) Something else
End
Προγραμματισμός Ι
Παράδειγμα (ΙΙ)
Προγραμματισμός Ι
Προγραμματισμός Ι
Βρόχοι Επανάληψης
Ο βρόχος for
Η εντολή for χρησιμοποιείται για τη δημιουργία επαναληπτικών
βρόχων στη C
Επαναληπτικός βρόχος καλείται το τμήμα του κώδικα μέσα σε ένα
πρόγραμμα, το οποίο εκτελείται από την αρχή και
επαναλαμβάνεται όσο μία συνθήκη παραμένει αληθής (true)
Προγραμματισμός Ι
Τα βήματα εκτέλεσης της for
1. Εκτελείται η αρχική_έκφραση
Η αρχική_έκφραση εκτελείται μόνο μία φορά, όταν αρχίζει η εκτέλεση
της for εντολής και μπορεί να είναι οποιαδήποτε έγκυρη έκφραση της C
Συνήθως, είναι μία εντολή εκχώρησης που αρχικοποιεί κάποια
μεταβλητή, η οποία θα χρησιμοποιηθεί από τις άλλες δύο εκφράσεις
2. Γίνεται έλεγχος της τιμής της συνθήκης
Η συνθήκη είναι συνήθως μία σχεσιακή έκφραση
Αν είναι ψευδής, τότε ο for βρόχος τερματίζεται και η εκτέλεση του
προγράμματος συνεχίζει με την πρώτη εντολή που υπάρχει μετά το
άγκιστρο κλεισίματος της for εντολής
Αν είναι αληθής, τότε εκτελείται η ομάδα των εντολών που
ονομάζεται και «σώμα του βρόχου»
3. Εκτελείται η τελική_έκφραση
Συνήθως, η τελική_έκφραση αλλάζει την τιμή κάποιας μεταβλητής
που χρησιμοποιείται στη συνθήκη
4. Επαναλαμβάνονται συνεχώς τα βήματα (2) και (3), μέχρι η
τιμή της συνθήκης να γίνει ψευδής
Προγραμματισμός Ι
Παράδειγμα
Έξοδος: 0 1 2 3 4
Προγραμματισμός Ι
Παρατηρήσεις (I)
Όταν γνωρίζουμε εκ των προτέρων τον αριθμό των επαναλήψεων
που επιθυμούμε να εκτελεστούν, τότε χρησιμοποιούμε συνήθως
την εντολή for και όχι κάποια άλλη επαναληπτική μέθοδο
Προγραμματισμός Ι
Παρατηρήσεις (IΙ)
Μην βάζετε το ελληνικό ερωτηματικό ; στο τέλος της for
εντολής, γιατί το ερωτηματικό θεωρείται ξεχωριστή πρόταση, η
οποία σημαίνει ότι δεν υπάρχει ομάδα εντολών για εκτέλεση (null
statement)
Π.χ. η εντολή:
for(a = 0; a < 1000; a++);
αυξάνει την τιμή του a χίλιες φορές και δεν κάνει τίποτα άλλο
Π.χ.:
Προγραμματισμός Ι
Παρατηρήσεις (IΙΙ)
Στη θέση των αρχική_έκφραση, συνθήκη και
τελική_έκφραση μπορεί να μπει οποιαδήποτε έγκυρη έκφραση
της C
Π.χ.
Προγραμματισμός Ι
Παρατηρήσεις (IV)
Σε μία for εντολή μπορεί να λείπουν κάποια από τα 3 τμήματά
της ή ακόμη και όλα
λείπει η αρχική_έκφραση
Στην εντολή:
for(;;)
Παρατηρήσεις (V)
Όταν σε μία for εντολή λείπει η συνθήκη ή η συνθήκη είναι
πάντα αληθής, τότε αυτός ο for βρόχος ονομάζεται ατέρμονος
βρόχος, γιατί δεν τερματίζεται ποτέ
Π.χ. ο βρόχος:
Επίσης, ο βρόχος:
for(;;)
Προγραμματισμός Ι
Παρατηρήσεις (VI)
Aν η συνθήκη είναι εξ’αρχής ψευδής, τότε δεν θα εκτελεστεί
ποτέ το μπλοκ εντολών της for
Προγραμματισμός Ι
Παρατηρήσεις (VIΙ)
Αν αρχική_έκφραση και η τελική_έκφραση λείπουν, ο for
βρόχος είναι ισοδύναμος με τον αντίστοιχο while βρόχο, όπως
θα δούμε παρακάτω
while(a < 5)
Προγραμματισμός Ι
Παραδείγματα (Ι)
Γράψτε ένα πρόγραμμα που να εμφανίζει τους ακέραιους αριθμούς
από το 1 έως το 10
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει 10 ακέραιους
αριθμούς και να εμφανίζει κάθε φορά το τριπλάσιο του αριθμού,
μόνο αν αυτός είναι μικρότερος του 10 ή μεγαλύτερος του 20
Προγραμματισμός Ι
Παραδείγματα (ΙΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 12 7 End = 2
Test
Test
Test... (ατέρμων βρόχος)
Προγραμματισμός Ι
Παραδείγματα (ΙV)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος:0 1 2
One
Προγραμματισμός Ι
Παραδείγματα (V)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: One
Val1 = 4 Val2 = 2
Προγραμματισμός Ι
H εντολή break
Η εντολή break χρησιμοποιείται για τον άμεσο τερματισμό ενός
επαναληπτικού βρόχου (π.χ. for, while ή do-while) ή για τον
τερματισμό μίας εντολής switch
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος:1 2 3 4
i = 5
Προγραμματισμός Ι
H εντολή continue
Η εντολή continue χρησιμοποιείται μέσα σε έναν επαναληπτικό
βρόχο (π.χ. for, while ή do-while)
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος:1 2 3 4 6 7 8 9 10
i = 11
Προγραμματισμός Ι
Προγραμματισμός Ι
Παραδείγματα (Ι)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙV)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: *
* *
* * *
* * * *
* * * * *
Προγραμματισμός Ι
Παραδείγματα (V)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει τους βαθμούς μίας
ομάδας 5 φοιτητών σε 3 διαφορετικά μαθήματα και να εμφανίζει
στην οθόνη τον μέσο όρο του κάθε φοιτητή στα 3 μαθήματα και
τον συνολικό μέσο όρο της ομάδας σε όλα τα μαθήματα
Προγραμματισμός Ι (συνεχίζεται...)
Παραδείγματα (V)
Προγραμματισμός Ι
Ο βρόχος while
Η εντολή while, όπως και η εντολή for,
χρησιμοποιείται για τη δημιουργία επαναληπτικών
βρόχων στη C
while(συνθήκη)
{
/* ομάδα εντολών που θα εκτελείται όσο η
συνθήκη παραμένει αληθής. */
}
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις (IΙ)
Η εντολή while(x) είναι ισοδύναμη με την while(x != 0)
Προγραμματισμός Ι
Παρατηρήσεις (IΙΙ)
Aν η συνθήκη είναι εξ’αρχής ψευδής, τότε δεν θα εκτελεστεί
ποτέ το μπλοκ εντολών της while
Π.χ.
Προγραμματισμός Ι
Παρατηρήσεις (IV)
Οι εντολές for και while είναι πολύ στενά συνδεδεμένες
exp1;
for(exp1; exp2; exp3) while(exp2)
{ {
/* εντολές */ /* εντολές */
} exp3;
}
Προγραμματισμός Ι
Παραδείγματα (Ι)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει συνεχώς έναν
ακέραιο αριθμό και να τον εμφανίζει μέχρι ο χρήστης να εισάγει
το μηδέν (0). Το μηδέν (0) που θα εισάγει ο χρήστης να μην
εμφανίζεται.
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Πόσες φορές εκτελείται ο while βρόχος στο παρακάτω
πρόγραμμα?
Απάντηση: 2 φορές
Προγραμματισμός Ι
Παραδείγματα (ΙΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙV)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει συνεχώς ακέραιους αριθμούς
μέχρι ο χρήστης να εισάγει το 0. Στο τέλος, το πρόγραμμα να εμφανίζει
το πλήθος των θετικών και αρνητικών αριθμών που εισήγαγε ο χρήστης.
Το μηδέν (0) να μην προσμετράται ούτε στους θετικούς ούτε στους
αρνητικούς αριθμούς
Προγραμματισμός Ι
Ο βρόχος do-while
Η εντολή do-while, όπως και οι εντολές for και while,
χρησιμοποιείται για τη δημιουργία επαναληπτικών βρόχων
στη C
do
{
/* ομάδα εντολών που εκτελείται αρχικά μία φορά
και στη συνέχεια κατ’ επανάληψη όσο η συνθήκη
παραμένει αληθής. */
}while(συνθήκη);
Προγραμματισμός Ι
Προγραμματισμός Ι
Τα βήματα εκτέλεσης της do-while
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Ο βρόχος do-while χρησιμοποιείται πολύ λιγότερο από τους
for και while βρόχους
Όποιο πρόβλημα λύνεται με χρήση του βρόχου
do-while θα μπορούσε να επιλυθεί και με χρήση βρόχων while
ή for
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
Σε περίπτωση που ο βρόχος do-while περιέχει μόνο μία εντολή,
τα άγκιστρα μπορούν, και στην do-while εντολή, να παραλειφθούν
Π.χ.:
do
printf("%d\n", i);
while(++i <= 10);
Προγραμματισμός Ι
Παράδειγμα (Ι)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει έναν θετικό ακέραιο
αριθμό και με χρήση της εντολής do-while να εμφανίζει τη
λέξη This τόσες φορές στην οθόνη όσο και ο αριθμός που
εισήγαγε ο χρήστης.
1 1 1 1 1
...
1 2 3 4 N
Προγραμματισμός Ι
Η εντολή goto
Η εντολή goto χρησιμοποιείται με σκοπό να μεταφέρει την
εκτέλεση του προγράμματος σε κάποια άλλη εντολή μέσα στην ίδια
συνάρτηση, με την προϋπόθεση ότι η εντολή έχει μία ετικέτα
goto lebel;
Προγραμματισμός Ι
Παράδειγμα
Αν ο χρήστης εισάγει την τιμή -1 η εκτέλεση του προγράμματος
μεταβαίνει στη θέση START και ο for βρόχος εκτελείται πάλι
από την αρχή
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Γενικά, δεν προτείνεται η χρήση της εντολής goto, γιατί η
μετάβαση της εκτέλεσης του προγράμματος από ένα σημείο σε
κάποιο άλλο και μετά σε κάποιο άλλο, κ.ο.κ, οδηγεί σε δυσνόητο
κώδικα που δεν είναι καλά οργανωμένος και άρα δύσκολα
ελέγχεται
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
Ίσως, ορισμένες φορές, η χρήση της goto να οδηγεί και σε
απλούστερο κώδικα (π.χ. στην άμεση έξοδο από έναν «αρκετά
ένθετο» for βρόχο, όπως τον παρακάτω)
Προγραμματισμός Ι
Προγραμματισμός Ι
Πίνακες
Πίνακες στη C
Ένας πίνακας στη C είναι μία δομή δεδομένων που αποτελείται από
στοιχεία του ίδιου τύπου (π.χ. πίνακας ακεραίων αριθμών, πίνακας
πραγματικών αριθμών, πίνακας χαρακτήρων, ...)
Προγραμματισμός Ι
Παρατηρήσεις
Το όνομα_πίνακα πρέπει να είναι μοναδικό (να μην υπάρχει άλλη
double arr[5];
/* πίνακας με όνομα arr, ο οποίος περιέχει 5 πραγματικούς
αριθμούς τύπου double */
char x[2000];
/* πίνακας με όνομα x, ο οποίος περιέχει 2000 ακεραίους
τύπου char */
Προγραμματισμός Ι
Γραφική Αναπαράσταση (I)
Όλα τα στοιχεία του πίνακα
Π.χ. char c[10]; έχουν το ίδιο όνομα (c)
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Σημειώστε ότι το πλήθος των στοιχείων του πίνακα (δηλαδή το
μήκος του πίνακα) δεν μπορεί να αλλάξει κατά την εκτέλεση του
προγράμματος. Παραμένει σταθερό.
Παρατηρήσεις (ΙΙ)
Όταν δηλώνεται ένας πίνακας, ο μεταγλωττιστής δεσμεύει ένα
κομμάτι μνήμης για να αποθηκεύσει τα στοιχεία του πίνακα
Οι τιμές των στοιχείων του πίνακα αποθηκεύονται η μία μετά την άλλη
σε διαδοχικές θέσεις μνήμης
Τυπικά, αυτό το κομμάτι μνήμης δεσμεύεται από συγκεκριμένο μέρος της
μνήμης που ονομάζεται στοίβα (stack), και αποδεσμεύεται όταν
τερματιστεί η λειτουργία της συνάρτησης μέσα στην οποία έχει δηλωθεί
ο πίνακας
int arr[10];
Για την εύρεση του μεγέθους της δεσμευμένης μνήμης από έναν
πίνακα, μπορούμε να χρησιμοποιήσουμε τον τελεστή sizeof (π.χ.,
sizeof(arr))
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙΙ)
Το μέγιστο μέγεθος μνήμης που μπορεί να δεσμευτεί με τη δήλωση
ενός πίνακα εξαρτάται από το μέγεθος της στοίβας
Προγραμματισμός Ι
Παρατηρήσεις (ΙV)
Στην περίπτωση που το μέγεθος του πίνακα πρέπει να είναι
αρκετά μεγάλο, τότε προτείνεται η δήλωση του πίνακα με τη
μορφή δείκτη και η δέσμευση μνήμης με χρήση της συνάρτησης
malloc()
double *arr;
arr = (double*)malloc(500000 * sizeof(double));
Για την αντιγραφή ενός πίνακα (π.χ. int a[10]) σε έναν άλλον
(π.χ. int b[10]), μην διανοηθείτε να γράψετε κάτι σαν το
παρακάτω:
b = a;
παρόλο που φαίνεται αρκετά «κομψό»
Παρατηρήσεις (VΙ)
Η C δεν ελέγχει αν κάνετε υπέρβαση των ορίων των θέσεων του
πίνακα, αλλά αφήνει τον προγραμματιστή υπεύθυνο γι’ αυτό... Σε
περίπτωση, όμως, που γίνει υπέρβαση των ορίων του πίνακα, η
συμπεριφορά του προγράμματος είναι απρόβλεπτη.
Προγραμματισμός Ι
Σε αυτό το παράδειγμα:
η τιμή του arr[0] γίνεται 10
η τιμή του arr[1] γίνεται 20
η τιμή του arr[2] γίνεται 30
και η τιμή του τελευταίου στοιχείου arr[3] γίνεται 40
Προγραμματισμός Ι
Δήλωση Πίνακα και απόδοση αρχικών τιμών (ΙΙ)
2. Τη δήλωση του πίνακα την ακολουθεί ο τελεστής = και μέσα
στα άγκιστρα {} δεν υπάρχουν τιμές για όλα τα στοιχεία του
πίνακα
Σε αυτό το παράδειγμα:
η τιμή του arr[0] γίνεται 10
η τιμή του arr[1] γίνεται 20
η τιμή του arr[2] και του arr[3] γίνεται 0
Προγραμματισμός Ι
Προγραμματισμός Ι
Παραδείγματα (Ι)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 40 50 60
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 10
20
30
40
50
Προγραμματισμός Ι
Παραδείγματα (IIΙ)
Ποιες θα είναι οι τιμές των στοιχείων του πίνακα a, κατά την
εκτέλεση του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (IV)
Γράψτε ένα πρόγραμμα το οποίο να δηλώνει έναν πίνακα 5
ακεραίων και να δίνει τις τιμές 10,20,30,40,50 στα στοιχεία
του. Στη συνέχεια, το πρόγραμμα να αντιγράφει τα περιεχόμενά
του σε έναν δεύτερο πίνακα και να εμφανίζει τα στοιχεία του
δεύτερου πίνακα στην οθόνη.
Προγραμματισμός Ι
Παραδείγματα (V)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 100
100
100
100 (κακώς,υπερεγγραφή)
??? (ίσως 20, ίσως 100)
Προγραμματισμός Ι
Παραδείγματα (VΙ)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει 10 ακεραίους, να
τους αποθηκεύει σε έναν πίνακα ακεραίων και στη συνέχεια να
εμφανίζει τα στοιχεία του πίνακα με αντίστροφη σειρά.
Προγραμματισμός Ι
Παραδείγματα (VIΙ)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει 10 ακεραίους
αριθμούς, να τους αποθηκεύει σε έναν πίνακα ακεραίων και να
τους εμφανίζει στην οθόνη. Το πρόγραμμα πριν αποθηκεύσει
κάποιον αριθμό στον πίνακα πρέπει να ελέγχει αν αυτός ο
αριθμός ήδη υπάρχει και μόνο αν δεν υπάρχει να τον αποθηκεύει
στον πίνακα. Δηλαδή, όλα τα στοιχεία του πίνακα πρέπει να
είναι διαφορετικά μεταξύ των.
Προγραμματισμός Ι
(συνεχίζεται )
Παραδείγματα (VIΙ)
Προγραμματισμός Ι
Παραδείγματα (VIII)
Τι κάνει το παρακάτω πρόγραμμα ???
Προγραμματισμός Ι
Παραδείγματα (VIII)
Έξοδος:
Rating Frequency
1 2
2 2
3 2
4 2
5 5
6 11
7 5
8 7
9 1
10 3
Προγραμματισμός Ι
Προγραμματισμός Ι
Δήλωση διδιάστατου Πίνακα
Π.χ. η εντολή int array[10][5]; δηλώνει έναν διδιάστατο
πίνακα με όνομα array, ο οποίος περιέχει 50 στοιχεία και καθένα
από αυτά τα στοιχεία είναι ένας ακέραιος αριθμός (int)
Προγραμματισμός Ι
Γραφική Αναπαράσταση
Π.χ. αν έχουμε δηλώσει τον πίνακα: int a[3][4]
Προγραμματισμός Ι
Διδιάστατοι Πίνακες και Μνήμη
Κατά τη δήλωση του πίνακα, ο μεταγλωττιστής – όπως και στην
περίπτωση των μονοδιάστατων πινάκων – δεσμεύει ένα τμήμα
μνήμης από τη στοίβα (stack) για να αποθηκεύσει τα στοιχεία του
Προγραμματισμός Ι
θέση_στη_μνήμη = (i * COLS) + j + 1
Προγραμματισμός Ι
Δήλωση Πίνακα και απόδοση αρχικών τιμών (ΙΙ)
1. Τη δήλωση του πίνακα την ακολουθεί ο τελεστής = και οι
τιμές των στοιχείων κάθε γραμμής περικλείονται ανάμεσα σε
εσωτερικά άγκιστρα {} διαχωριζόμενες μεταξύ τους με κόμμα
(,)
Σε αυτό το παράδειγμα:
η τιμή του arr[0][0] γίνεται 10
η τιμή του arr[0][1] γίνεται 20
η τιμή του arr[0][2] γίνεται 30 κ.ο.κ.
Προγραμματισμός Ι
Προγραμματισμός Ι
Παραδείγματα (Ι)
Γράψτε ένα πρόγραμμα το οποίο να αρχικοποιεί έναν διδιάστατο
πίνακα 5×5 ως τον μοναδιαίο τετραγωνικό 5×5 πίνακα και να
εμφανίζει τα στοιχεία του πίνακα στην οθόνη υπό τη μορφή
πίνακα 5×5 της άλγεβρας
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Γράψτε ένα πρόγραμμα το οποίο
να διαβάζει ακέραιους αριθμούς,
να τους αποθηκεύει σε έναν
2×4 πίνακα και να εμφανίζει τη
μικρότερη και τη μεγαλύτερη
τιμή κάθε γραμμής του πίνακα
Προγραμματισμός Ι
Προγραμματισμός Ι
Δείκτες
Μνήμη Υπολογιστή
Η μνήμη RAM (Random Access Memory)
ενός υπολογιστή αποτελείται από πολλές
χιλιάδες θέσεις αποθήκευσης δεδομένων
που έχουν διαδοχική αρίθμηση
Προγραμματισμός Ι
Παράδειγμα
Έστω η δήλωση: int a = 10;
Memory
Memory
Ο μεταγλωττιστής συσχετίζει το όνομα της .
μεταβλητής a, με τη διεύθυνση της μεταβλητής 5000 10
0
Όταν το πρόγραμμα χρησιμοποιεί το όνομα της 5001 0
0
μεταβλητής, ο μεταγλωττιστής προσπελαύνει 5002 0
0
αυτομάτως τη διεύθυνση της μεταβλητής 5003
.
0
10
.
Π.χ. με την εντολή a = 80; ο μεταγλωττιστής .
γνωρίζει ότι η διεύθυνση της a είναι η 5000 και N-1
θέτει το περιεχόμενό της ίσο με 80 Memory
Προγραμματισμός Ι
Δήλωση Δείκτη
Ο δείκτης είναι μία μεταβλητή, στην οποία αποθηκεύεται η
διεύθυνση μνήμης μίας άλλης μεταβλητής
τύπος_δεδομένων *όνομα_δείκτη;
Παρατηρήσεις
O τύπος_δεδομένων μπορεί να είναι οποιοσδήποτε από τους
τύπους μεταβλητών της C και δηλώνει τον τύπο της μεταβλητής
στην οποία – συνηθίζουμε να λέμε – «δείχνει ο δείκτης»
Το όνομα_δείκτη πρέπει να ακολουθεί τους κανόνες
ονοματολογίας της C και να μην υπάρχει άλλη δήλωση με το ίδιο
όνομα μέσα στο πρόγραμμα
Ο τελεστής * χρησιμοποιείται για να δηλώσει ότι η μεταβλητή είναι
δείκτης
Προγραμματισμός Ι
Παραδείγματα Δήλωσης Δείκτη
int *ptr;
Η μεταβλητή ptr είναι ένας δείκτης προς κάποια ακέραια
μεταβλητή
Αυτό σημαίνει, ότι στον δείκτη ptr θα αποθηκευτεί η διεύθυνση
κάποιας ακέραιας μεταβλητής τύπου int
double *pt;
Η μεταβλητή pt είναι ένας δείκτης προς κάποια πραγματική
μεταβλητή (και μάλιστα, τύπου double)
Αυτό σημαίνει, ότι στον δείκτη pt θα αποθηκευτεί η διεύθυνση
κάποιας πραγματικής μεταβλητής (και πιο συγκεκριμένα, μιας
μεταβλητής τύπου double)
Προγραμματισμός Ι
Παρατηρήσεις (1/3)
Με τη δήλωση:
int *ptr;
Παρατηρήσεις (3/3)
Όταν δηλώνεται μία μεταβλητή-δείκτης, ο μεταγλωττιστής, όπως κάνει
και για οποιαδήποτε μεταβλητή, δεσμεύει τις απαραίτητες θέσεις μνήμης
για να αποθηκεύσει την τιμή του
Προγραμματισμός Ι
Παρατηρήσεις
Για την εμφάνιση στην οθόνη της διεύθυνσης μνήμης μίας μεταβλητής
συνήθως χρησιμοποιείται το προσδιοριστικό %p, το οποίο εμφανίζει τη
διεύθυνση σε δεκαεξαδική μορφή (μπορούμε να χρησιμοποιήσουμε και το
προσδιοριστικό %d, για την εμφάνιση της διεύθυνσης σε δεκαδική μορφή)
int *ptr;
ptr = 1000;
Προγραμματισμός Ι
Η ειδική τιμή NULL (Ι)
Υπενθυμίζεται ότι, όταν δηλώνεται μία μεταβλητή, τότε ο
μεταγλωττιστής αναθέτει στη μεταβλητή μία τυχαία τιμή (τιμή
«σκουπίδι»)
Προγραμματισμός Ι
Επί της ουσίας πρόκειται για μια μακροεντολή με όνομα NULL και
τιμή ίση με μηδέν (0) ή – ακόμα καλύτερα – με τιμή μηδέν (0)
προσαρμοσμένη στον τύπο void*, δηλαδή τιμή (void*)0
Προγραμματισμός Ι
Η ειδική τιμή NULL (ΙΙΙ)
Παρόλο που είναι δυνατόν να χρησιμοποιηθεί απευθείας κι η τιμή 0
αντί της NULL, σε περίπτωση που πρόκειται για μεταβλητή-δείκτη
είναι προτιμότερο να χρησιμοποιείτε τη μακροεντολή NULL για να
αποφεύγεται η παρακάτω σύγχυση:
Χρήση Δείκτη
Για να αποκτήσουμε πρόσβαση στο περιεχόμενο κάποιας διεύθυνσης
μνήμης με χρήση δείκτη, χρησιμοποιούμε τον τελεστή * (dereference
operator ή αλλιώς indirection operator) πριν από το όνομα του δείκτη
Π.χ.
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙ)
Το επόμενο πρόγραμμα λειτουργεί σωστά, γιατί τώρα ο δείκτης ptr
δείχνει στη διεύθυνση κάποιας υπαρκτής μεταβλητής (της μεταβλητής j)
πριν χρησιμοποιηθεί στην εντολή i = *ptr;
Επομένως, αφού ο δείκτης ptr δείχνει στη διεύθυνση της μεταβλητής j,
το *ptr θα είναι ίσο με την τιμή του j, δηλαδή 20
Άρα, με την εντολή i = *ptr; η τιμή του i θα γίνει ίση με 20
Έξοδος: Val = 20
Προγραμματισμός Ι
Παρατηρήσεις (ΙΙΙ)
Οι τελεστές * (περιεχόμενο διεύθυνσης μνήμης που δείχνει ο δείκτης) και
& (διεύθυνση μνήμης μιας μεταβλητής) είναι μεταξύ τους συμπληρωματικοί ή
αντίστροφοι (αλλιώς λέμε ότι αλληλοαναιρούνται ή αλληλοεξουδετερώνονται ή
ακυρώνει ο ένας τον άλλον)
Έξοδος (π.χ.):
The address of a is 0028F958
The value of ptr is 0028F958
The value of a is 21
The value of *ptr is 21
Προγραμματισμός Ι
Παρατηρήσεις (ΙV)
Δεδομένου ότι οι χαρακτήρες /* σηματοδοτούν την αρχή ενός σχολίου,
σε μία έκφραση σαν την παρακάτω:
a = b/*ptr;
Π.χ.: a = b/ *ptr;
ή a = b/(*ptr);
Προγραμματισμός Ι
Δεν ξεχνώ λοιπόν...
Δήλωση μεταβλητών
Δήλωση «μεταβλητών
δεικτών»
Προγραμματισμός Ι
Παραδείγματα (Ι)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 30
Προγραμματισμός Ι
Παραδείγματα (ΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 30
Προγραμματισμός Ι
Παραδείγματα (ΙΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 11
Προγραμματισμός Ι
Παραδείγματα (ΙV)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 0 1 2
Προγραμματισμός Ι
Παραδείγματα (V)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 200
Προγραμματισμός Ι
Παραδείγματα (VΙ)
Γράψτε ένα πρόγραμμα το οποίο κάνοντας χρήση ενός δείκτη για
να διαβάσει μία δεκαδική τιμή και να εμφανίζει την απόλυτη τιμή
της τιμής αυτής.
Προγραμματισμός Ι
Π.χ.
Προγραμματισμός Ι
Ο δείκτης void* (2/2)
Για να προσπελάσουμε τη μεταβλητή με χρήση ενός void* δείκτη
πρέπει να προσαρμόσουμε τον τύπο του στον τύπο της μεταβλητής,
ώστε ο μεταγλωττιστής να γνωρίζει το αντίστοιχο μέγεθος, όπως
φαίνεται στο παρακάτω πρόγραμμα:
Προγραμματισμός Ι
Π.χ.
Προγραμματισμός Ι
Αριθμητική Δεικτών
Η αριθμητική δεικτών αφορά στην εκτέλεση αριθμητικών πράξεων με
δείκτες
Σύμφωνα με το πρότυπο, η αριθμητική δεικτών παράγει αξιόπιστα
αποτελέσματα όταν εφαρμόζεται σε στοιχεία του ίδιου πίνακα, αλλιώς
το αποτέλεσμα είναι απροσδιόριστο
ptr = ptr + n;
αυξάνει την τιμή του δείκτη κατά n * μέγεθος του τύπου στον
οποίο δείχνει ο ptr και τον κάνει να δείχνει στη διεύθυνση του
n-οστού στοιχείου μετά από αυτό που έδειχνε
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος???
Ο ptr αυξάνεται κατά 8, (όχι κατά 2), δεδομένου ότι ο ptr έχει
δηλωθεί ως δείκτης σε int
Έτσι, το πρόγραμμα εμφανίζει δύο διευθύνσεις (ως ακέραιο του
δεκαδικού συστήματος) με τη δεύτερη να είναι κατά 8 θέσεις
μεγαλύτερη απ’ την πρώτη (π.χ. αν η πρώτη ήταν η διεύθυνση
89234834 η δεύτερη θα είναι η 89234842) κι επειδή ο ptr δείχνει
στο arr[2], το πρόγραμμα εμφανίζει 30, επίσης.
Προγραμματισμός Ι
Δείκτες και Ακέραιοι (Μείωση Δεικτών)
Όμοια με την πρόσθεση, η αφαίρεση ενός θετικού ακέραιου από έναν
δείκτη σε μία ανάθεση όπως η παρακάτω :
ptr = ptr - n;
μειώνει την τιμή του δείκτη κατά n * μέγεθος του τύπου στον
οποίο δείχνει ο δείκτης και κάνει τον δείκτη να δείχνει στη
διεύθυνση του n-οστου στοιχείου πριν από αυτό που έδειχνε
Π.χ.
Η δεύτερη διεύθυνση θα είναι κατά 8
θέσεις μικρότερη απ’την πρώτη και,
όπως και κατά την πρόσθεση, το
αποτέλεσμα θα είναι έγκυρο αν ο
δείκτης δείχνει σε ένα στοιχείο εντός
του πίνακα
Προγραμματισμός Ι
Αφαίρεση Δεικτών
Το αποτέλεσμα της αφαίρεσης δεικτών είναι ο αριθμός των
στοιχείων που μεσολαβούν μεταξύ τους
Προγραμματισμός Ι
Σύγκριση Δεικτών
Το αποτέλεσμα της σύγκρισης δύο δεικτών με τον τελεστή == ή τον
τελεστή != είναι πάντοτε αξιόπιστο
Παρατηρήσεις
Εκτός από τις λειτουργίες που ήδη περιγράφησαν, καμία άλλη
αριθμητική πράξη δεν επιτρέπεται να εκτελεστεί με τη συμμετοχή
κάποιου δείκτη
οι εντολές:
πολλαπλασιασμού ptr *= 2;
Προγραμματισμός Ι
Παραδείγματα (Ι)
Τι εμφανίζει η 2η printf() του παρακάτω προγράμματος ???
Παραδείγματα (ΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙII)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (ΙV)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: Value = 20
Προγραμματισμός Ι
Παραδείγματα (V)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (VI)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 2 5
Προγραμματισμός Ι
Παραδείγματα (VIIΙ)
Γράψτε ένα πρόγραμμα το οποίο να διαβάζει δύο ακέραιους, τους οποίους
να αποθηκεύει σε δύο ακέραιες μεταβλητές με χρήση δύο δεικτών σε
ακέραιους. Με χρήση αυτών των δεικτών, αποθηκεύστε το άθροισμά τους
σε μία τρίτη μεταβλητή με χρήση ενός επιπλέον δείκτη σε ακέραιο και
εμφανίστε τα περιεχόμενα της κάθε μεταβλητής με χρήση των παραπάνω
δεικτών.
Προγραμματισμός Ι
Δείκτες και Πίνακες - Εισαγωγή
Τα στοιχεία ενός πίνακα αποθηκεύονται σε διαδοχικές θέσεις
μνήμης, με το πρώτο στοιχείο στη χαμηλότερη διεύθυνση
Προγραμματισμός Ι
Παράδειγμα
Έστω η δήλωση του πίνακα:
int arr[3];
Προγραμματισμός Ι
Δείκτες και Πίνακες (Ι)
Το όνομα ενός πίνακα (χωρίς αγκύλες) μπορεί να χρησιμοποιηθεί
ως δείκτης στο πρώτο του στοιχείο
int arr[50];
Προγραμματισμός Ι
Σημειώστε ότι παρόλο που η έκφραση &arr εμφανίζει την ίδια τιμή,
είναι διαφορετική απ’ τις υπόλοιπες
Η έκφραση &arr είναι δείκτης σε ολόκληρο τον πίνακα, ενώ οι
υπόλοιπες είναι δείκτες στο πρώτο στοιχείο του πίνακα (ως τιμές είναι
ίδιες, αλλά διαφέρουν στον τύπο τους)
Συγκεκριμένα, ο τύπος &arr είναι “δείκτης σε έναν πίνακα 5
ακεραίων”, ενώ ο τύπος των υπολοίπων είναι “δείκτης σε ακέραιο”.
Ζόρικο???
Και για να το δυσκολέψουμε ακόμα περισσότερο, αν γράψουμε
&arr+1 αντί για &arr, ποια θα είναι η διαφορά με τις άλλες τιμές
(θα είναι ένα, τέσσερα, ή μήπως κάτι άλλο, ...)?
Για να σας δω... Προγραμματισμός Ι
Πιθανή
Έξοδος:
Προγραμματισμός Ι
Παράδειγμα (ΙΙ)
Πιθανή
Έξοδος:
Προγραμματισμός Ι
Παρατηρήσεις (Ι)
Όταν το όνομα ενός πίνακα χρησιμοποιείται ως δείκτης, η C τον
μεταχειρίζεται ως const δείκτη, συνεπώς, δεν επιτρέπεται ούτε
να αλλάξει την τιμή του ούτε να δείξει σε κάποια άλλη διεύθυνση
Παρατηρήσεις (ΙΙ)
Παρόλο που υπάρχει στενή σχέση μεταξύ πινάκων και δεικτών,
πρέπει να είναι ξεκάθαρο ότι ένας πίνακας δεν είναι δείκτης
καθώς και ένας δείκτης δεν είναι πίνακας...
Προγραμματισμός Ι
Παρατηρήσεις (ΙII)
Απλά να θυμάστε ότι, όταν το όνομα ενός πίνακα χρησιμοποιείται
σε μία έκφραση, ο μεταγλωττιστής το μεταφράζει σε δείκτη στο
πρώτο του στοιχείο
Προγραμματισμός Ι
Παρατηρήσεις (ΙV)
Αν και μία μεταβλητή δείκτης δεν είναι πίνακας, μπορεί να
χρησιμοποιηθεί με σημειογραφία πίνακα
Προγραμματισμός Ι
Παραδείγματα (Ι)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (IΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: Val = 58
Προγραμματισμός Ι
Παραδείγματα (IIΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 3
Προγραμματισμός Ι
Παραδείγματα (IV)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (V)
Υπάρχει κάποιο bug στο παρακάτω πρόγραμμα ???
Απάντηση: Όχι...
«σκονάκι No1»: θυμηθείτε ότι *(arr+i)= arr[i]
Κι άλλη υπόδειξη???
«σκονάκι No2»: *(arr+i)= *(i+arr)
Κι άλλο???
«σκονάκι No3»: arr[i]=*(arr+i)= *(i+arr)= i[arr]
Προγραμματισμός Ι
Πίνακας Δεικτών
Ένας πίνακας δεικτών είναι ένας πίνακας, όπου κάθε στοιχείο του
είναι ένας δείκτης σε έναν συγκεκριμένο τύπο δεδομένων
Π.χ.
int *p[3];
Προγραμματισμός Ι
Παρατηρήσεις
Για να μην τρομάζετε, το κάθε στοιχείο ενός πίνακα δεικτών,
μπορεί να θεωρηθεί ως μία απλή μεταβλητή δείκτη
Π.χ. με τη δήλωση:
int (*p)[3];
Προγραμματισμός Ι
Παραδείγματα (I)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Παραδείγματα (IΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Έξοδος: 20 30 40
Προγραμματισμός Ι
Παραδείγματα (IΙΙ)
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Δείκτης σε Δείκτη
Όταν δηλώνεται ένας δείκτης, ο μεταγλωττιστής, όπως κάνει για
οποιαδήποτε μεταβλητή, δεσμεύει τις απαραίτητες θέσεις μνήμης
για να αποθηκεύσει την τιμή του
Επομένως, αφού έχει δεσμευτεί μία διεύθυνση μνήμης για έναν
δείκτη μπορούμε να δηλώσουμε έναν άλλον δείκτη που να δείχνει
σε αυτή τη διεύθυνση
Για να δηλώσουμε έναν δείκτη σε κάποιον άλλον δείκτη
χρησιμοποιούμε δύο φορές τον τελεστή *
Προγραμματισμός Ι
**ptr = * (ptr1) = i
Προγραμματισμός Ι
Παράδειγμα
Ποια είναι η έξοδος του παρακάτω προγράμματος ???
Προγραμματισμός Ι
Προγραμματισμός Ι
Δείκτες και Διδιάστατοι Πίνακες (ΙV)
Αντίστοιχα, το arr[1] μπορεί να χρησιμοποιηθεί σαν δείκτης
προς έναν πίνακα 3 ακεραίων που περιέχει τα στοιχεία της
δεύτερης γραμμής, δηλαδή τα arr[1][0], arr[1][1] και
arr[1][2]
Συγκεκριμένα:
το arr[1] είναι δείκτης στο πρώτο στοιχείο του πίνακα,
δηλαδή στο arr[1][0]
Άρα, η τιμή του *arr[1] είναι ίση με το arr[1][0]
Προγραμματισμός Ι
Δηλαδή,
το πρώτο στοιχείο του πίνακα arr[N][M] είναι το arr[0], το
οποίο είναι δείκτης σε έναν πίνακα που περιέχει τα Μ στοιχεία
της πρώτης γραμμής
το δεύτερο στοιχείο του πίνακα arr[N][M] είναι το arr[1],
το οποίο είναι δείκτης σε έναν πίνακα που περιέχει τα Μ
στοιχεία της δεύτερης γραμμής
...
ενώ το τελευταίο στοιχείο είναι το arr[Ν-1], το οποίο είναι
δείκτης σε έναν πίνακα που περιέχει τα Μ στοιχεία της
τελευταίας (της Ν-οστής) γραμμής
Προγραμματισμός Ι
Παράδειγμα
Τι κάνει το παρακάτω πρόγραμμα ???
Προγραμματισμός Ι
Π.χ. αφού το arr είναι δείκτης σε έναν δείκτη που δείχνει στη διεύθυνση
του στοιχείου arr[0][0], τότε το **arr είναι ίσο με την τιμή
arr[0][0]
Προγραμματισμός Ι
Παράδειγμα
Τι κάνει το παρακάτω πρόγραμμα ???
Προγραμματισμός Ι
Παρατηρήσεις I
Προφανώς, η διαχείριση των στοιχείων ενός διδιάστατου πίνακα
με χρήση δεικτών (είτε απλού δείκτη είτε «δείκτη σε δείκτη»)
οδηγεί σε δυσνόητο και μη ευανάγνωστο κώδικα
Προγραμματισμός Ι
Παρατηρήσεις II
Έστω ότι είχαμε τις ακόλουθες δηλώσεις:
int a[2][3], b[10];
Ερώτηση: Όπως λέμε ότι το b μπορεί να χρησιμοποιηθεί σαν
δείκτης στο b[0], μπορούμε να πούμε ότι και το a είναι δείκτης
στο a[0][0];
Η απάντηση είναι ΟΧΙ, επειδή η C χειρίζεται τον a σαν
μονοδιάστατο πίνακα με στοιχεία πίνακες, οπότε το a είναι δείκτης
στο πρώτο στοιχείο του που είναι το a[0], άρα, αν θέλαμε να
εκχωρήσουμε το a σε έναν δείκτη, ποιος θα έπρεπε να είναι ο
τύπος του δείκτη; Θα έπρπε να είναι δείκτης σε πίνακα, π.χ.:
int (*p)[3]; /* Οι παρενθέσεις είναι απαραίτητες, γιατί
αλλιώς το p θα μεταφραζόταν σαν πίνακας τριών δεικτών σε
ακεραίους. */
p = a;
Προγραμματισμός Ι
Παράδειγμα
Τι κάνει το παρακάτω πρόγραμμα ???
Η γενική μορφή της δήλωσης ενός δείκτη προς μία συνάρτηση είναι:
Προγραμματισμός Ι
Προγραμματισμός Ι
Παρατηρήσεις
Το όνομα του δείκτη πρέπει να βρίσκεται ανάμεσα σε παρενθέσεις,
γιατί ο τελεστής * έχει χαμηλότερη προτεραιότητα από τις
παρενθέσεις που περιβάλλουν τη λίστα παραμέτρων της
συνάρτησης
Π.χ. αν γράψουμε:
Προγραμματισμός Ι
Προγραμματισμός Ι
Παράδειγμα
Δημιουργήστε μία συνάρτηση που να δέχεται σαν παραμέτρους τους
βαθμούς δύο φοιτητών και να επιστρέφει τον μεγαλύτερο από αυτούς.
Στη συνέχεια
γράψτε ένα
πρόγραμμα το
οποίο να
διαβάζει δύο
βαθμούς και να
χρησιμοποιεί
έναν δείκτη
για να καλέσει
τη συνάρτηση
και να
εμφανίσει τον
μεγαλύτερο
βαθμό.
Προγραμματισμός Ι
Προγραμματισμός Ι
Παράδειγμα
Τι κάνει το παρακάτω πρόγραμμα ???
Παράδειγμα
Προγραμματισμός Ι