Professional Documents
Culture Documents
Κωνσταντίνος Κουκουλέτσος
Τμήμα Αυτοματισμού
Ενότητα # 1: Εισαγωγή
Περιεχόμενα
• Περιβάλλον ανάπτυξης
• Διαδικασία συγγραφής & εκτέλεσης
προγράμματος
• Καλές πρακτικές παρουσίασης προγράμματος
• Αλφάβητο, Λεξιλόγιο, Αναγνωριστικά, Βασικοί
τύποι δεδομένων, Μεταβλητές, Σταθερές της C++
• Αριθμητικοί, Σχεσιακοί & Λογικοί τελεστές της
C++
Περιβάλλον Ανάπτυξης
Dev C++ της εταρείας Bloodshed
http://www.bloodshed.net/devcpp.html
Online tutorials
English
http://www.cplusplus.com/doc/tutorial/
http://www.cprogramming.com/
http://www.netspace.org/~mts/cpp/
http://www.functionx.com/cpp/index.htm
6
Διαδικασία συγγραφής και εκτέλεσης
προγράμματος
Πρόγραμμα:
Εμφάνιση μηνύματος στην οθόνη
Απλό πρόγραμμα
Εκτύπωση μίας γραμμής
To πρόγραμμα παρουσιάζει βασικά χαρακτηριστικά της C++
9
Επεξήγηση προγράμματος (1)
Οδηγία προς το Προ-επεξεργαστή
(Preprocessor) να συμπεριλάβει τα
αρχεία επικεφαλίδας (header file)
<cstdlib> και <iostream>
Οι εντολές τελειώνουν με ;
Η συνάρτηση main
εμφανίζεται μόνο μία φορά
σε κάθε πρόγραμμα C++
Χρήση εσοχών
11
Το πρόγραμμα τρέχει σωστά
12
13
Καλές Πρακτικές Παρουσίασης
Προγράμματος
1. Κάθε πρόγραμμα αρχίζει με κάποια σχόλια
2. Σχόλια μπαίνουν και μέσα στο πρόγραμμα
3. Χρησιμοποιούμε εσοχές για καλύτερη
αναγνωσιμότητα του προγράμματος
4. Οι εσοχές είναι σύμφωνα με ισχύοντες πρακτικές
14
Μεταβλητές
- Θέσεις στην μνήμη του υπολογιστή
- Ο τύπος των μεταβλητών πρέπει να δηλώνεται
- Οι βασικοί τύποι μεταβλητών είναι
int – ακέραιοι αριθμοί
char – χαρακτήρες
double – πραγματικοί (κινητής υποδιαστολής)
- Οι μεταβλητές πρέπει να δηλώνονται με όνομα και τύπο πριν από την χρήση
τους
int arithmos1;
int arithmos2;
int sinolo;
- Αναγνωριστικά (identifiers) είναι τα ονόματα που χρησιμοποιούνται για τις
μεταβλητές
15
Πρόγραμμα πρόσθεσης αριθμών
16
- Ψηφία 0, 1, 2, …, 9
- Ειδικούς χαρακτήρες
+ = - /( ) * & % $ # ! | ~ \ ^ < > . , ; : ? { } [ ] _
17
Το λεξιλόγιο της C++
Σε ένα πρόγραμμα της C++ διακρίνονται τα
παρακάτω είδη στοιχείων:
- Σχόλια (comments) και Λέξεις κλειδιά (reserved words)
- Μεταβλητές (variables) με τα αναγνωριστικά τους (identifiers)
και Σταθερές (constants)
- Συμβολοσειρές (strings) και Τελεστές (operators)
- Σημεία στίξης και διαχωριστές (punctuators & separators)
18
Λέξεις κλειδιά
19
Αναγνωριστικά Ονόματα
(Identifiers)
Δηλώνουν συναρτήσεις και μεταβλητές
- Ισχύουν οι παρακάτω κανόνες
- To όνομα μπορεί να αποτελείται από γράμματα μικρά και
κεφαλαία, ψηφία και τον χαρακτήρα υπογράμμισης underscore
- Ο πρώτος χαρακτήρας πρέπει να είναι γράμμα ή ο χαρακτήρας
υπογράμμισης _ (underscore)
- Δεν επιτρέπεται η χρήση δεσμευμένων λέξεων
20
Αναγνωριστικά Ονόματα-
Παραδείγματα
Καλό είναι τα ονόματα να είναι τα ονόματα να έχουν σχέση με
την μεταβλητή που αντιπροσωπεύουν. Με τον τρόπο αυτό το
πρόγραμμα γίνεται πιο ευανάγνωστο
πχ. plithos, poso, pososto, perimetros, fpa, AnoOrio, KatoOrio …..
Ονόματα μη αποδεκτά
1num, poso-forou, φπα
21
Βασικοί τύποι Δεδομένων και
Ακρίβεια
22
Δηλώσεις μεταβλητών-
παραδείγματα
int poso;
float a,b,c;
int fpa= 18, kefalaio=100000;
double mikos1=18.9, mikos2=5.8
23
Δηλώσεις Μεταβλητών-Εκχωρήσεις
Δηλώνονται σε οποιοδήποτε σημείο του προγράμματος αρκεί να
γίνει η δήλωση πριν από την χρήση
float a,b,c;
int fpa= 23, kefalaio=100000;
int totalfpa;
foros=kefalaio*fpa/100;
int ipoloipo;
ipoloipo=kefalaio-foros;
Η εκχώρηση δεν σημαίνει ισότητα αλλά σημαίνει βάλε στο αριστερό
μέρος την τιμή που προκύπτει μετά το υπολογισμό του δεξιού
μέρους
int k=10;
k=k+2;
24
Εύρος ακεραίου
Ο ακέραιος τύπος έχει περιορισμένο
εύρος μέχρι 2 εκατομμύρια.
Αν η τιμή που προκύπτει είναι εκτός
εύρους τότε έχουμε υπερχείλιση
(overflow) αλλά δεν εμφανίζεται
ΛΑΘΟΣ
25
Σταθερές
Εάν θέλουμε η τιμή μιας Το ίδιο επιτυγχάνεται και με την οδηγία
μεταβλητής να μην αλλάξει #define προς τον pre-processor
κατά την εκτέλεση τότε #define FPA 18 //xoris ; sto telos
χρησιμοποιούμε το πρόθεμα #define PI 3.1415926535897932384626433832795
const (από τη λέξη constant, //paradeigma
σταθερά) πριν τον τύπο float rad ;
δεδομένων της μεταβλητής const float PI=3.1415 ;
const int fpa=18; cout<< “Dose aktina tou kiklou” ;
cin>> rad ;
float embado = PI * rad * rad ;
cout<< "Εμβαδόν= "<< embado << endl;
26
Αριθμητικοί Τελεστές
27
Προσοχή στις πράξεις ακεραίων
Εάν και οι δύο αριθμοί είναι Τι εμφανίζεται αν εκτελεστεί
ακέραιοι το ενδιάμεσο το παρακάτω πρόγραμμα;
αποτέλεσμα είναι ακέραιο.
Έτσι 7/3 είναι 2 και όχι 2.5
28
Παραδείγματα Εκχώρησης
int a,b; H εκχώρηση χρησιμοποιείται int a,b;
a=5; μέσα σε μία άλλη εκχώρηση
a=a+3; a=5;
b=++a;
a=4+(b=2);
cout<<a<<b;
66
a=14%7;
a=16%7; a=5;
b=a++;
a=5/2; cout<<a<<b;
a=6/4; 65
29
Σύνθετες εκχωρήσεις
(+=, -=, *=, /=, %= )
compound assignment
operators
Αλλάζει η τιμή της μεταβλητής
με πράξη που γίνεται στην
τρέχουσα τιμή της.
30
Σχεσιακοί Τελεστές
Οι τελεστές χρησιμοποιούνται για να σχηματίσουμε
λογικές συνθήκες. Το αποτέλεσμα είναι μία λογική
τιμή, είτε αληθής (true) είτε ψευδής (false).
== ίσο
!= διάφορο
> μεγαλύτερο
< μικρότερο
>= μεγαλύτερο ή ίσο
<= μικρότερο ή ίσο
31
Λογικοί Τελεστές
Οι λογικοί τελεστές
! (not)
&& (and)
|| (or)
χρησιμοποιούνται για να σχηματίσουν λογικές προτάσεις.
32
Τι θα εμφανίσει το παρακάτω;
int k;
k=(7==5)&&(5>4); cout<<k;
33
Προτεραιότητα τελεστών
1. Οι πράξεις εκτελούνται
σύμφωνα με την προτεραιότητα
2. Τελεστές με την ίδια
προτεραιότητα εκτελούνται από
τα αριστερά προς τα δεξιά
3. Χρησιμοποιούνται
παρενθέσεις για να αλλαχτεί η
εκτέλεση των πράξεων
a=6/2+1;
a=6/(2+1);
b=a+2+6/2;
a= (a+2+6)/2;
34
Ενότητα # 2: Εντολή If
Περιεχόμενα
• Εντολή if
• if.. else
• Ένθετη εντολή if..else
• Πολλαπλά if..else
• Εντολή switch
• Ισοδυναμία if..else με switch
• Παραδείγματα
5
Εντολή if
• Με την εντολή αυτή γίνεται έλεγχος (αλλαγή) της ροής του προγράμματος
• Σύνταξη εντολής:
Απλή πρόταση
if (λογική παράσταση)
Block εντολών
• Το Block εντολών είναι εντολές που περικλείονται σε { } Π.χ.
if (a==5) {
a=2*a;
cout<<a;
}
• Σε περίπτωση μία εντολής δεν χρειάζονται { }
if (a==5)
cout<<a;
6
Πρόταση if..else (1)
Πρόταση if…else
if (λογική παράσταση)
Block εντολών1
else
Block εντολών2
Π.χ.
if (a==5) {
a=2*a;
cout<<a;
}
else {
a=b;
cout<<a<<b;
}
8
Ένθετη εντολή if..else (nested if)
Πρόκειται για εντολές if που H στοίχιση του παραδείγματος
περικλείονται σε άλλες μπορεί να διαφοροποιηθεί:
εντολές if…else if (x > 0)
cout << «Το x einai thetiko";
else
πχ if (x < 0)
cout << “To x einai arnitiko";
else
if (x > 0) cout << “To x einai miden";
cout << «Το x einai thetiko"; Μπορεί να γραφεί
else if (x > 0)
cout << «Το x einai thetiko";
if (x < 0) else if (x < 0)
cout << “To x einai arnitiko"; cout << “To x einai arnitiko«
else else
cout << “To x einai miden"; cout << “To x einai miden";
υπόλοιπο πρόγραμμα
10
Αντιστοίχιση else με If (1)
a=9, b=3;
a=9, b=7;
a=2, b=3;
a=2, b=7
Το else αντιστοιχεί στο τελευταίο if που δεν έχει δικό του else.
11
a=9, b=3;
a=9, b=7;
a=2, b=3;
a=2, b=7
Το else αντιστοιχεί στο τελευταίο if που δεν έχει δικό του else.
12
Εντολή switch
• Χρησιμοποιείται για πολλαπλή επιλογή αντι if..elseif..else if else…
switch (παράσταση)
{case τιμή1:
Block εντολών1
break;
case τιμή2:
Block εντολών2
break;
case τιμή2:
Block εντολών3
break;
……..
……
default
Block εντολώνΝ
}
Η παράσταση πρέπει να εκτιμάται σαν ακεραία
Η τιμη1, τιμή2 είναι ακέραιοι αριθμοί ή χαρακτήρες (όχι πραγματικοί ή strings )
13
14
Ισοδυναμία if..else με εντολή switch (1)
15
Απάντηση
16
Ενότητα # 3: Επαναλήψεις
Περιεχόμενα
• Εντολή for
• Εντολή while
• Εντολή do..while
• break & continue
• Παραδείγματα
5
Εντολές Επαναλήψεων
•H C++ διαθέτει τις παρακάτω εντολές
επανάληψης (βρόγχος)
– Εντολή for
– Εντολή while
– Εντολή do… while
Εντολή for
Αρχική τιμή
–Εκτελείται η εντολή1_αρχικοποίησης
– Ελέγχεται η συνθήκη και αν ισχύει, εκτελείται το block, διαφορετικά η for τερματίζει.
– Εκτελείται η εντολή2
– Εκτελείται το b)
• Έλεγχος της συνθήκης που καθορίζει αν θα συνεχιστεί ή όχι η επανάληψη
γίνεται στην αρχή
7
Εντολή for-Παραδείγματα
Εντολή for-Παραδείγματα
9
Εντολή while
while (συνθήκη) {
block;
}
Λειτουργία εντολής
• Αν η συνθήκη είναι αληθής (τιμή =1) τότε εκτελείται το block των εντολών και
μετά εξετάζεται και πάλι ή συνθήκη.
• Αν η συνθήκη είναι ψευδής τότε η επαναληπτική διαδικασία σταμάτα και
εκτελείται η εντολή που βρίσκεται αμέσως μετά το block της δομής while.
• Συνήθως η εντολή while χρησιμοποιείται στην περίπτωση που το πλήθος των
επαναλήψεων δεν είναι γνωστό ή εάν το πλήθος των επαναλήψεων δεν παίζει
ρόλο αλλά εξαρτάται από την ικανοποίηση ή όχι μίας συνθήκης.
10
Στο παρακάτω πρόγραμμα η επανάληψη δεν εκτελείται καμία φορά. Δεν είναι
λάθος γιατί υπάρχουν τέτοιες περιπτώσεις που δεν θέλουμε να γίνει εκτέλεση
αν δεν ισχύει κάποια αρχική συνθήκη
11
Εντολή while-Περιπτώσεις-λάθη (2)
Ποιο είναι το αποτέλεσμα των τριών
επόμενων επαναλήψεων
12
Εντολή do..while
do {
block;
} while (συνθήκη);
Λειτουργία εντολής
• Εκτελείται το block των εντολών και μετά γίνεται έλεγχος της συνθήκης. Εάν η
συνθήκη είναι αληθής (τιμή =1 η ακόμη πιο γενικά ≠0 ) τότε εκτελείται και πάλι το
block των εντολών και μετά εξετάζεται πάλι ή συνθήκη.
• Αν η συνθήκη είναι ψευδής τότε η επαναληπτική διαδικασία σταμάτα και
εκτελείται η εντολή που βρίσκεται αμέσως μετά το block των εντολών της δομής
do…while.
• Η επαναληπτική διαδικασία do…while είναι παρόμοια με την while, όμως οι
εντολές εντός του block εντολών θα εκτελεστούν τουλάχιστον μια φορά
ανεξαρτήτως αν είναι αληθής ή όχι η συνθήκη γιατί η συνθήκη εξετάζεται στο
τέλος της διαδικασίας.
13
Παραδείγματα εφαρμογής do..while (1)
Το do…while εκτελεί μία σειρά εντολών και μετά ελέγχει την
συνθήκη επανάληψης.
Εφαρμόζεται ευρέως στην περίπτωση που ο χρήστης αφού
εισάγει μία τιμή γίνεται έλεγχος της τιμής αυτής.
15
Ισοδύναμες επαναλήψεις
17
Παράδειγμα 1ο
• Πόσοι αριθμοί που εισάγει χρήστης από το
πληκτρολόγιο πρέπει να προστεθούν για να
ξεπεράσει το άθροισμά τους το 100, και ποιο
το συνολικό άθροισμα;
int total, num;
int plithos=0;
total=0;
while (total<100) {
cout<<"dose arithmo ";cin>>num;
plithos++; total+=num;
}
18
Παράδειγμα 2ο
Μπάλα ρίπτεται από ύψος και const double orio=0.02;
αναπηδά. double ArxikoYpsos; int anapidiseis=0;
Δεδομένου ότι η μπάλα αναπηδά cout<<"\nDoste arxiko ipsos ";
στα 2/3 του προηγούμενου ύψους cin>>ArxikoYpsos;
cout <<"Starting Height: "<<ArxikoYpsos<<"
πόσες φορές αναπήδησε και ποιο το meters "<<endl;
ύψος που φθάνει κάθε φορά. double ipsos=ArxikoYpsos;
Να ληφθεί υπόψη ότι κάτω από το
while (ipsos >=orio) {
0.2cm η μπάλα σταματά να ipsos *=2./3.;
αναπηδά διότι δεν διαθέτει την anapidiseis++;
cout <<" anapidisi "<<anapidiseis<<" = ";
απαιτούμενη ενέργεια. cout<<ipsos<<" meters"<<endl;
To αρχικό ύψος να εισάγεται από το }
πληκτρολόγιο. cout<<"H balla anapidise"<<anapidiseis<<"
fores \n\n";
system("PAUSE");
return 0;
19
break και continue (1)
Η εντολή break:
Η εντολή break χρησιμοποιείται για τον τερματισμό της εκτέλεσης
μιας επαναληπτικής δομής (for, while. do…while). Η εκτέλεση του
προγράμματος μεταφέρεται στην εντολή που υπάρχει αμέσως μετά
την for, while. do…while.
20
21
Παραδείγματα (1)
Να βρείτε το πλήθος ψηφίων ενός ακέραιου αριθμού. Nα χρησιμοποιηθούν και
οι δύο επαναληπτικές διαδικασίες while και do….while. Να παρατηρήσετε ότι
για τον αριθμό 0 οι δύο διαδικασίες δίνουν διαφορετικό αποτέλεσμα.
22
Παραδείγματα (2)
Να εισάγεται αριθμός χ που να μην γίνεται αποδεκτός παρά
μόνον αν είναι στο διάστημα 0-100.
Κατόπιν να βρίσκεται το άθροισμα των που διαιρούνται με το 4
από το 0 έως τον αριθμό x
23
Ενότητα # 4: Πίνακες
Περιεχόμενα
• Δήλωση πίνακα
• Αρχικοποίηση πίνακα
• Συνάρτηση size of
• Επεξεργασία πίνακα
• Πολυδιάστατοι πίνακες
• Παραδείγματα & Ασκήσεις
5
Πίνακας
Ένας πίνακας είναι μία ομάδα δεδομένων του ιδίου τύπου. Οι
πίνακες δίνουν την δυνατότητα επεξεργασίας πολλών
δεδομένων με γρήγορο και από τρόπο.
Πχ. Για την επεξεργασία των βαθμών των σπουδαστών σε ένα
τμήμα απαιτείται μεγάλο πλήθος μεταβλητών. Για 50
σπουδαστές χρειαζόμαστε 50 μεταβλητές (v1,v2, v3…v50).
Πράξεις και γενικά χειρισμός τόσων μεταβλητών είναι
πρακτικά αδύνατος.
Με την χρήση πίνακα όλες οι μεταβλητές έχουν ένα κοινό
όνομα και διαφέρουν μόνο ως προς τον δείκτη.
Ορισμός-Δήλωση πίνακα
• Η δήλωση ορισμός γίνεται ως εξής:
type name[size]
Π.χ. float vathmos[50]
// dilonei ena pinaka me 50 theseis kai stoixeia pragmatikous
Π.χ. int v[5]
// dilonei ena pinaka me 5 theseis kai stoixeia akeraious
• H προσπέλαση των στοιχείων γίνεται ως εξής
– Το 1o στοιχεία του ανωτέρω πίνακα είναι το v[0],
– Tο 2o στοιχείο είναι το v[1]
– To τελευταίο στοιχείο του πίνακα είναι το v[4] στη περίπτωση
που έχει δηλωθεί ένας πίνακας v[5] ή το v[49] στην περίπτωση
που έχει δηλωθεί ένας πίνακας v[50]
7
Αρχικοποίηση πίνακα
Τιμές σε πίνακα μπορούν να δοθούν με τον παρακάτω τρόπο
int v[5]={101,102,103,104,105 }
Αν το μέγεθος του πίνακα δεν έχει γραφεί τότε με μία
αρχικοποίηση το πλήθος των στοιχείων του πίνακα ορίζεται
από το πλήθος των τιμών τις τιμές που πίνακα
int v[ ]={ 100,200,300}
Με τον τρόπο αυτό ορίζεται πίνακας 3 θέσεων
Αν στην αρχικοποίηση ενός πίνακα παραληφθούν κάποιες
τιμές τότε είναι 0
int v[5]={101,102}
Οι υπόλοιπες θέσεις του πίνακα δηλ. v[2] =0 , v[3] =0 , v[4] =0
Η δήλωση int v[50]={0} μηδενίζει όλες τις θέσεις σε ένα πίνακα
Δήλωση πίνακα
Δήλωση πίνακα
int a[10];
Όνομα πίνακα a
Τύπος int
Σύνολο στοιχείων 10
Συνολικά bytes
4X10=40
9
Μέγεθος πίνακα-Συνάρτηση sizeof
Η συνάρτηση sizeof μπορεί να χρησιμοποιηθεί με πίνακες
και επιστρέφει σαν τιμή το συνολικό μέγεθος σε bytes που
καταλαμβάνει ο πίνακας.
cout<<sizeof(int); //4
cout<<sizeof(double); //8
int i; sizeof(i) ; //4
Όλα τα στοιχεία του πίνακα έχουν το ίδιος μέγεθος. Για να
βρεθεί το μέγεθος που καταλαμβάνει ένας πίνακας μπορεί
να χρησιμοποιηθεί η εντολής
int plithos = sizeof(pin)/sizeof(pin[0])
To ίδιο θα ήταν αν χρησιμοποιηθεί η εντολή
float pin[ ];
int plithos = sizeof(pin)/sizeof(float)
10
Επεξεργασία πίνακα
Γίνεται με την χρήση της εντολής for.
O λόγος που χρησιμοποιείται το for, αντί για
κάποια άλλη δομή επανάληψης, είναι γιατί είναι
γνωστό το πλήθος των επαναλήψεων που πρέπει
να γίνουν για την πρόσβαση σε όλα τα στοιχεία
του πίνακα.
11
Εισαγωγή και εμφάνιση στοιχείων (1)
12
13
Εισαγωγή και εμφάνιση στοιχείων (3)
14
Πολυδιάστατος πίνακας
Ένα πολυδιάστατος πίνακας έχει περισσότερες από μία
διαστάσεις. Πίνακες με παραπάνω από 3 διαστάσεις
συναντιόνται σπάνια στην πράξη.
Δήλωση πίνακα δύο διαστάσεων
Ένα πίνακας με δύο διαστάσεις που θα είχε την
δυνατότητα να αποθηκεύει τους βαθμούς μίας τάξης 50
ατόμων σε 6 μαθήματα θα οριζόταν ως εξής
float vat[50][6];
Για τους πίνακες δύο διαστάσεων ισχύουν ότι και για
τους μονοδιάστατους πίνακες σχετικά με την
αρχικοποίηση και τον χειρισμό τους
15
Πίνακας δύο διαστάσεων
Αρχικοποίηση
int pinax[ 2 ][ 2 ] = { { 11, 22 }, { 33, 44 } };
16
Παράδειγμα 1
Να εμφανίζεται πίνακας δύο διαστάσεων στην οθόνη.
Ο πίνακας να αρχικοποιείται μέσα στο πρόγραμμα.
17
Παράδειγμα 2
18
19
Άσκηση 1: Λύση
20
Παρατήρηση
showpoint: Όταν εμφανίζονται αριθμοί εμφανίζονται πάντα με δεκαδικό σημείο
fixed: Οι αριθμοί εμφανίζονται με τόσα δεκαδικά ψηφία όσα καθορίζονται από την
setprecision
right: Στοιχίζει δεξιά
setprecision(2): καθορίζει το πλήθος των δεκαδικών ψηφίων
21
Άσκηση 2: Εμφάνιση βαθμολογίας
22
25
Παράδειγμα
Να εμφανίζονται τα αποτελέσματα 10 ρίψεων που κάνει
παίκτης με δύο ζάρια:
26
Ενότητα # 5: Pointers
Περιεχόμενα
• Διευθύνσεις και μνήμη
• Δείκτες
• Πράξεις με δείκτες
• NULL
• Πίνακες & δείκτες
• Παραδείγματα
6
Δείκτες (Pointers)
Μία μεταβλητή καταλαμβάνει μία ή περισσότερες θέσεις στην μνήμη.
Οι θέσεις (bytes) που καταλαμβάνει μία μεταβλητή εξαρτάται από τον
τύπο του δεδομένου. Στην Dev C++ για τους γνωστούς τύπους οι θέσεις
είναι :
char 1 byte
int 4 bytes
float 4 bytes
double 8 bytes
Επειδή η μεταβλητή καταλαμβάνει συνήθως περισσότερα από ένα byte
σαν διεύθυνση της μεταβλητής θεωρείται ότι είναι η διεύθυνση του
πρώτου byte που καταλαμβάνει η μεταβλητής
Για να υπολογιστεί το μέγεθος μίας μεταβλητής χρησιμοποιώ την
συνάρτηση sizeof
πχ. cout<<sizeof(int) // εμφανίζει τον αριθμό 4
Ορισμός Δείκτη
Ο δείκτης είναι μία μεταβλητή που σαν περιεχόμενο έχει μία
διεύθυνση της μνήμης.
Πχ. int a=11;
int * pa;
H pa είναι μία μεταβλητή που σαν περιεχόμενο έχει μία
διεύθυνση μίας ακεραίας μεταβλητής (δηλαδή δείχνει μία
μεταβλητής ακέραιου τύπου).
Για να δώσω μία τιμή στο pa χρησιμοποιώ τον τελεστή & που
ονομάζεται τελεστής διεύθυνσης (reference operator)
pa=&a;
Η pa έχει σαν περιεχόμενο την διεύθυνση της μεταβλητής a
(&a = address of a)
8
Χρήση Δείκτη
Επειδή με τον δείκτη έχω πρόσβαση στην διεύθυνση μίας μεταβλητής μπορώ να
έχω και πρόσβαση στο περιεχόμενο της διεύθυνσης αυτής δηλαδή στον αριθμό
που αποθηκεύεται στην μεταβλητή που εχει αυτήν την διεύθυνση
Αυτό γίνεται με το τελεστή * που μέχρι τώρα χρησιμοποιείται για
πολλαπλασιασμό αλλά και στην δήλωση δείκτη
Το σύμβολο * χρησιμοποιείται επίσης και σαν
τελεστής έμμεσης αναφοράς (dereference operator, indirection operator) για την
από-αναφοροποιηση (dereferencing) στην τιμή της μεταβλητής που δείχνει ένας
δείκτης, δηλαδή o τελεστής επιτρέπει την έμμεση αναφορά σε τιμή μίας
μεταβλητής.
Με το * εμφανίζεται η τιμή που βρίσκεται στην διεύθυνση που δείχνει (περιέχει ο
δείκτης) δηλαδή:
int a=11;
int * pa=&a;
cout<<*pa //εμφανίζει τον αριθμό 11
Παράδειγμα 1
Παρατηρήστε ότι :
οι τιμές του a και *pa είναι οι ίδιες και
το περιεχόμενο του δείκτη pa που είναι μια διεύθυνση
συμπίπτει με την διεύθυνση που έχει αποθηκευτεί η a.
H διεύθυνση που έχει αποθηκευτεί η μεταβλητή a
εμφανίζεται με το &a.
10
Παρατηρήσεις
Για τον ορισμό του ενός δείκτη τα παρακάτω είναι ισοδύναμα.
int* a;
int * a;
int *a;
Για τον ορισμό περισσοτέρων του ενός δεικτών ο τελεστής * πρέπει να
επαναλαμβάνεται:
int * a,* b,* c, d;
Όλες οι μεταβλητές εκτός από την d είναι τύπου δείκτη, ενώ η d είναι ακέραια
μεταβλητή.
Ένας δείκτης είναι σαν μία ακεραίου τύπου μεταβλητή. Απλά σαν τιμή έχουν
ένα 16-δικό αριθμό που αναφέρεται σε μία διεύθυνση όπου περιέχεται ένας
αριθμός του ιδίου τύπου με τον τύπο του δείκτη.
Αν έχω δύο δείκτες πχ int * pa, * pb τότε η εκχώρηση pa=pb σημαίνει ότι ο
δείκτης pa έχει την ίδια τιμή με το δείκτη pb δηλαδή και οι δύο δείκτες δείχνουν
προς την ιδία διεύθυνση, αυτή που δείχνει ο pb
11
Παράδειγμα 2
12
Σύνοψη
Η δήλωση ενός δείκτη γίνεται με Η εντολή *pb=44 έχει σαν
int * pa, *pb; float * pd; αποτέλεσμα τιμή της μεταβλητής
Αφού δηλωθούν οι μεταβλητές η που δείχνει ο δείκτης pb γίνεται 44
αρχικοποίηση των δεικτών γίνεται Το σύμβολο * χρησιμοποιείται για
με εκχωρήσεις διευθύνσεων να δηλώσει δείκτες και σαν
pa=&a ; pb=&b; pd=&d; τελεστής έμμεση αναφοράς
Με την εντολή pa=pb ο δείκτης pa (indirection operator – dereference
και ο pb έχουν το ίδιο περιεχόμενο operator) για την από–
δηλαδή δείχνουν στην ίδια θέση αναφοροποιηση (dereferencing)
της μνήμης στην τιμή της μεταβλητής που
Με την εντολή *pa=*pb το δείχνει ένας δείκτης, δηλαδή για
περιεχόμενο της μεταβλητής που την έμμεση αναφορά σε τιμή μίας
δείχνει ο pa αλλάζει τιμή μεταβλητής.
13
Συχνά λάθη
Ο δείκτης είναι διεύθυνση (δεκαεξαδικός αριθμός ) Για την αποφυγή τέτοιων
και παίρνει τιμή με την χρήση του τελεστή & και όχι λαθών καλό είναι με την
με απόδοση αριθμητικής τιμής δήλωση δείκτη ταυτόχρονα να
int* d, x=200 ; αρχικοποιείται
d=&x; // sosto int x=100;
cout<<x<<*d<<endl;; int* d=&x, //arxikopoihsh
d=3000; //lathos (invalid conversion from int to int*
Με την δήλωση ενός δείκτη ο δείκτης περιέχει μία Aν αυτό δεν μπορεί να γίνει
τυχαία διεύθυνση. Ενώ μπορώ να εμφανίσω την μπορώ κάνω χρήση μίας
διεύθυνση αυτή αν κάνω χρήση αυτής θα προκαλέσει ειδικής τιμής ώστε ο δείκτης
λάθος-κόλλημα στο πρόγραμμα (crash). Στο να μην δείχνει πουθενά
παρακάτω παράδειγμα ο compiler δεν «ξερει» πού να
βάλει την τιμή 100.
int* d; //xoris arxikopoihsh
cout<<d;
*d=100;
cout<<*d<<endl;
14
NULL
Αν δηλωθεί ένας δείκτης και δεν είμαι σε θέση να τον αρχικοποιήσω
μπορώ να του αποδώσω την τιμή NULL. Στην περίπτωση αυτή ο
δείκτης δεν δείχνει πουθενά.
15
Πράξεις με δείκτες
Οι δείκτες είναι σαν ακέραιες μεταβλητές.
Επιτρέπονται πράξεις πρόσθεσης αφαίρεσης αύξησης και μείωσης
δηλαδή επιτρέπεται η χρήση των τελεστών
+ - ++ --
16
Παράδειγμα 1
int a[ ]={50,55,60,65};
int* dk=&a[2];
int m;
m=*dk+1; cout<<m<<" "; //emfanizei to 61
m=*(dk+1); cout<<m<<" "; //emfanizei to 65
dk--; cout<<*dk<<" ";//emfanizei to 55
17
Παράδειγμα 2
18
Πίνακες και δείκτες
1. Στην C++ δείκτες και πίνακες έχουν στενή σχέση.
Ο πίνακας a είναι ένας δείκτης του ιδίου τύπου με τον
πίνακα και δείχνει στο πρώτο στοιχείο του πίνακα.
19
Για να δηλώσω ένα δείκτη που δείχνει στο πρώτο στοιχείο του πίνακα μπορώ να το
κάνω με δύο τρόπους:
int a[ ]={50,55,60,65};
int * da=a;
εναλλακτικά χρησιμοποιώ την δήλωση
int * da=&a[0]
20
Παράδειγμα 1
Να ορισθεί πίνακας με 4 θέσεις και να μηδενιστούν τα στοιχεία του
1ος τρόπος
float p1[4];
cout<<"times for p1"<<endl;
for( int k=0;k<4;k++){
p1[k]=0;
cout<<setw(4)<<p1[k];}
2ος τρόπος
float p2[4];
cout<<"times for p2"<<endl;
for(int k=0;k<4;k++){
*(p2+k)=0;
cout<<setw(4)<<p2[k];}
21
Παρατηρήσεις (1)
Οι τελεστές ++ και - - έχουν μεγαλύτερη προτεραιότητα από τον τελεστή *
(indirection operator). Επομένως η έκφραση *p++ όταν ο p έχει οριστεί σαν
δείκτης είναι ισοδύναμη με την *(p++), δηλαδή αυξάνεται η τιμή του p ώστε να
δείχνει στο επόμενο στοιχείο.
Σε εκφράσεις του τύπου κ=*p++ επειδή το ++ χρησιμοποιείται σαν επίθεμα η
παράσταση υπολογίζεται σαν την τιμή που δείχνει ο δείκτης πριν γίνει αύξηση
του δείκτη δηλαδή η *p++ πρώτα εφαρμόζεται ο τελεστής *και μετά ο ++.
Επίσης θα πρέπει να τονιστεί ότι ακόμη και η χρήση παρενθέσεων δεν αλλάζει το
αποτέλεσμα και η παράσταση κ= *(p++) υπολογίζεται σαν την τιμή που δείχνει ο
δείκτης πριν γίνει αύξηση του δείκτη. Δηλαδή οι παραστάσεις κ=*p++ και η κ=
*(p++) είναι ισοδύναμες
Παράδειγμα
int a[2]={10,20};
int* d, k ;
d=&a[0];k=*(d++); cout<<" k= "<<k<<" *d= "<<*d<<endl;
d=&a[0];k=*d++; cout<<" k= "<<k<<" *d= "<<*d<<endl;
// emfanizontai oi idies times k=10 *d=20
22
Παρατηρήσεις (2)
Μόνο στην περίπτωση που χρησιμοποιηθεί το ++
σαν πρόθεμα τότε υπολογίζεται η τιμή που δείχνει ο
δείκτης αφού γίνει η αύξηση
d=&a[0];
k=*++d;
cout<<" z= "<<k<<" *d= <<*d<<endl;
// emfanizontai oi times z=20 *d=20
23
Παράδειγμα 2
24
Παρατήρηση
Το αναγνωριστικό ενός πίνακα (όνομα) είναι ένας δείκτης
που δείχνει στο πρώτο στοιχείο του πίνακα. Ενώ επιτρέπεται
αλλαγή τιμής σε μία μεταβλητή τύπου δείκτη δεν
επιτρέπεται αλλαγή τιμής σε ένα δείκτη όταν αυτός έχει
δηλωθεί ότι είναι πίνακας.
25
Παράδειγμα 3
26
Ενότητα # 6: Συναρτήσεις
Περιεχόμενα
• Συναρτήσεις της C++
• Συναρτήσεις που ορίζονται από τον χρήστη
• Πρωτότυπα Συναρτήσεων
• Τύπος αναφοράς
• Κλήση δια τιμής και κλήση με αναφορά
• Εμβέλεια μεταβλητών
• Παραδείγματα
5
Συναρτήσεις
Με την χρήση των συναρτήσεων ένα πρόγραμμα
μπορεί να χωριστεί σε άλλα μικρότερα κομμάτια,
δομές.
Ο δομημένος προγραμματισμός βασίζεται στην αρχή
της δόμησης μίας εφαρμογής προγραμματισμού
κάνοντας χρήση μικρότερων δομημένων στοιχείων.
Με την χρήση συναρτήσεων επιτυγχάνεται η
διάσπαση ενός προβλήματος σε μικρότερα.
Η συνάρτηση είναι ένα σύνολο εντολών που καλείται
και χρησιμοποιείται από ένα σημείο ενός
προγράμματος. Στην C++ ακόμη και το main θεωρείται
ότι είναι μία συνάρτηση.
6
7
Συναρτήσεις που ορίζονται από το
χρήστη (1)
Μία τέτοια συνάρτηση πρέπει να δηλωθεί και να οριστεί πριν γίνει χρήση
της συνάρτησης από το πρόγραμμα. Ο ορισμός μίας συνάρτησης έχει την
παρακάτω μορφή:
Τύπος_επιστροφής συνάρτηση (τύπος παράμετρος1,
τύπος παράμετρος2,…)
{
εντολές
}
9
Παράδειγμα
using namespace std;
int addition (int a, int b)
{ int p;
p=a+b;
return (p);
}
int main ()
{ int z;
z = addition (15, 8);
cout << "The result is " << z<<"\n";
int k=40,l=50;
z=addition (k, l);
cout << "The result is " << z<<"\n";
system("PAUSE");
return 0;
}
10
Παρατηρήσεις
Υπάρχει αντιστοιχία μεταξύ του τύπου και του αριθμού των παραμέτρων
που χρησιμοποιούνται στον ορισμό και στην κλήση της συνάρτησης.
Οι παράμετροι που χρησιμοποιούνται για να ορίσουν την συνάρτηση
λέγονται τυπικές παράμετροι (formal parameters). Οι παράμετροι που
χρησιμοποιούνται στην κλήση μίας συνάρτησης λέγονται ορίσματα
(arguments). Τα ορίσματα αναφέρονται στην βιβλιογραφία και σαν
παράμετροι κλήσης ή πραγματικές παράμετροι (actual parameters)
Μόλις γίνει κλήση της συνάρτησης, οι τιμές των ορισμάτων μεταφέρονται
στις παραμέτρους που βρίσκονται στον ορισμό της συνάρτησης. Η
μεταβλητή p που ορίζεται στην συνάρτηση χρησιμοποιείται για να
υπολογιστεί το άθροισμα και να γίνει επιστροφή του αθροίσματος από
την συνάρτηση στο main.
Εάν η συνάρτηση δεν επιστρέφει καμία τιμή τότε ορίζεται σαν τύπου void
και δεν υπάρχει return ή υπάρχει χωρίς τιμή (return;) H τιμή που
επιστρέφεται είναι του ιδίου τύπου με την συνάρτηση
11
Πρωτότυπα Συναρτήσεων
Για να γίνει κλήση μίας συνάρτησης (δηλαδή για να
χρησιμοποιηθεί η συνάρτηση) πρέπει προηγουμένως να έχει
δηλωθεί.
Η δήλωση γίνεται μέσω του λεγόμενου πρωτότυπου της
συνάρτησης (function prototype) και επιτρέπει στον compiler
να γνωρίζει τα απαραίτητα στοιχεία που αφορούν την
συνάρτηση. Αυτά τα στοιχεία είναι ο τύπος και το όνομα της
συνάρτησης καθώς και ο τύπος και ο αριθμός των
παραμέτρων της συνάρτησης.
12
Παράδειγμα
int addition(int , int ); //prototypo sinartiseis
int main( )
{ int z;
z = addition (15,8);
cout << "The result is " << z<<"\n";
int k=40,l=50;
z=addition (k,l);
cout << "The result is " << z<<"\n";
system("PAUSE"); return 0;
}
int addition (int a, int b)
{ int p; p=a+b;
return (p);
}
Σημείωση: Τα ονόματα των παραμέτρων της συνάρτησης μπορούν να
παραληφθούν, όπως γίνεται στο παραπάνω πρωτότυπο
13
Τύπος Αναφοράς
Το σύμβολο & χρησιμοποιείται σαν τελεστής διεύθυνσης
(address-of operator) για να αποδώσει τιμή σε ένα δείκτη.
Το ίδιο σύμβολο επίσης χρησιμοποιείται για να δηλώσει
μία μεταβλητή που λέγεται αναφορά ( reference) και είναι
ένα εναλλακτικό όνομα μίας άλλης μεταβλητής
Π.χ
int x;
int & ax=x;
Με την δήλωση αυτή η μεταβλητή ax είναι ένα συνώνυμο
της x. Οι δύο μεταβλητές έχουν το ίδιο περιεχόμενο.
14
15
Παράδειγμα (χρήση παραμέτρων τιμής)
void func2values (int, int );
// Stin defteri parametro ginetai klisi me anafora
int main ( )
{ int a=10, b=30;
cout << "The result is " << a<< b <<"\n";
func2values(a, b);
cout << "The result is " << a<< b <<"\n";
system("PAUSE");
return 0; }
void func2values (int x, int y )
{ x=2*x; y=2*y;
cout<<"oi times x kai y edo einai "<< x <<" "<< y <<"\n“; }
Η κλήση μέσω τιμής δεν μπορεί να επιστρέψει την αλλαγμένη τιμή της
παραμέτρου στο κυρίως πρόγραμμα.
Ακόμη και με χρήση return μπορώ να επιστρέψω μία και μόνο τιμή.
Για να γίνει επιστροφή της τιμής κάποιων μεταβλητών χρησιμοποιώ για κάθε μία
από τις μεταβλητές κλήση με αναφορά
16
17
Παράδειγμα
Να εμφανίζονται οι προηγούμενη και επόμενη τιμή μίας ακεραίας
μεταβλητής
void func2(int, int &, int &);
// Dio parametroi opou ginetai klisi me anafora
int main ()
{
int a=200, prin, meta;
cout << "The result is " << a<<"\n";
func2(a, meta, prin);
cout << "The result is " << a<<" "<<prin<<" "<<meta<<"\n";
system("PAUSE");return 0; }
18
Εμβέλεια Μεταβλητών
Εμβέλεια (scope) μίας μεταβλητής είναι ο χώρος σε ένα
πρόγραμμα όπου μία μεταβλητή έχει οριστεί και επομένως
μπορεί να χρησιμοποιηθεί.
Μία μεταβλητή έχει εμβέλεια μόνο μέσα στο μπλοκ των
εντολών που έχει οριστεί. Μπλοκ εντολών είναι μία ομάδα
εντολών που περιέχεται σε αγκύλες { }. Μία τέτοια
μεταβλητή θεωρείται τοπική (local) μεταβλητή.
Αντίθετα μία καθολική (global) μεταβλητή είναι ορατή από
οποιοδήποτε μέρος ενός προγράμματος. Μία καθολική
μεταβλητή ορίζεται εκτός της συνάρτησης ή του main
προγράμματος
19
Παράδειγμα
20
21
Παραδείγματα (εμβέλεια)
22
Να γραφεί πρόγραμμα
που να βρίσκει τον
μεγαλύτερο από 2
ακέραιους. Η εισαγωγή
των αριθμών καθώς και η
εύρεση του μεγαλύτερου
αριθμού να γίνονται με
συναρτήσεις
23
Λυμένα Παραδείγματα Χρήσης
Συναρτήσεων (2)
Λυμένο Παράδειγμα 2
Να γραφεί πρόγραμμα
που να καλεί συνάρτηση
που μετατρέπει τα
δευτερόλεπτα σε
ισοδύναμο χρόνο που
εκφράζεται σε λεπτά και
δευτερόλεπτα. Να
εισάγεται ο αριθμός που
αντιπροσωπεύει
δευτερόλεπτα στο κύριο
πρόγραμμα (πχ 65 sec = 1
min & 5 sec).
24
6
Συναρτήσεις και Πίνακες (2)
Πχ
int main(void)
{
int a[10]; //orizetai pinakas
………
sinart(a); //kaleitai mia sinartisi. To a exei thesi deikti
…
}
Η συνάρτηση funct συνεπώς πρέπει να οριστεί ως
int sinart (int * pa).
8
Ισοδύναμοι τρόποι δήλωσης (2)
Όλοι οι ανωτέρω τρόποι δήλωσης έχουν το ίδιο αποτέλεσμα και δηλώνουν ότι
στην κλήση της συνάρτησης ένας πίνακας θα χρησιμοποιηθεί. Στην
πραγματικότητα μόνο μία διεύθυνση θα μεταβιβαστεί προς την συνάρτηση.
Η διάσταση του πίνακα που δηλώνεται στις τυπικές παραμέτρους δεν παίζει
κανένα ρόλο δηλαδή στο παραπάνω παράδειγμα ο πίνακας μπορεί να δηλωθεί
και σαν int pa[30]. Η C++ δεν κάνει έλεγχο για τα όρια των διαστάσεων σε ένα
πίνακα.
Επειδή στην ουσία με την κλήση της συνάρτησης που έχει πίνακα σε μία από τις
παραμέτρους δεν μεταβιβάζεται πληροφορία για το πλήθος των στοιχείων του
πίνακα αυτό γίνεται με χρήση μίας άλλης παραμέτρου που μεταβιβάζει το
πλήθος όταν αυτό χρειάζεται. Συμπερασματικά για να χρησιμοποιήσω ένα πίνακα
σε μία συνάρτηση σαν παράμετρο πρέπει να περιλαμβάνεται και το μέγεθος του
πίνακα
Παράδειγμα
Διπλασιασμός κάθε στοιχείου πίνακα με συνάρτηση
cout<<endl;
system("PAUSE"); return EXIT_SUCCESS;
}
Παρατηρήσεις: Ο ορισμός της συνάρτησης θα μπορούσε να είναι
void diplas(double * v, int n)
void diplas(double v[100], int n)
10
Παράδειγμα
11
12
Λυμένο Παράδειγμα-Εκφώνηση
13
Λύση (1)
14
Λύση (2)
15
Λύση (3)
16
Ασκήσεις με Συναρτήσεις και Πίνακες
Να γραφούν οι παρακάτω συναρτήσεις
1. Συνάρτηση που να βρίσκει τον μέσο όρο των στοιχείων
ενός πίνακα
2. Συνάρτηση που να βρίσκει τον μικρότερο και μεγαλύτερο
στοιχείο ενός πίνακα
3. Συνάρτηση που να βρίσκει τον πλήθος των στοιχείων που
είναι μεγαλύτερο του μέσου όρου του πίνακα
Οι συναρτήσεις να χρησιμοποιηθούν για δύο πίνακες
πραγματικών αριθμών. Τα αποτελέσματα να εμφανίζονται με
χρήση καταλλήλων μηνυμάτων
17
Λύσεις (1)
18
Λύσεις (2)
19
Λύσεις (3)
20
Παλαιότερα Θέματα_1
21
Άσκηση 1
Άσκηση: Τι εμφανίζει το παρακάτω πρόγραμμα στην οθόνη;
22
Άσκηση 2
Άσκηση: Τι εμφανίζει το παρακάτω πρόγραμμα στην οθόνη;
23
Παλαιότερα Θέματα_2
24
Λυμένο Θέμα_1
Εκφώνηση Λύση
25
Λυμένο Θέμα_2
Εκφώνηση Λύση
Μία συνάρτηση συνήθως υπολογίζει και επιστρέφει τιμές
(αποτελέσματα) βάσει κάποιων δεδομένων. Να γραφεί
πρόγραμμα που να περιέχει τις κατάλληλες συναρτήσεις (μία
ή περισσότερες) Στο main να εισάγονται τα δεδομένα αφού
γίνει εμφάνιση καταλλήλου μηνύματος. Κατόπιν με χρήση
(κλήση) της συνάρτησης/εων να υπολογίζονται τα
αποτελέσματα/μα. Τα αποτελέσματα θα επιστρέφονται στο
main και θα εμφανίζονται στο main με την χρήση καταλλήλου
μηνύματος. Προσοχή: Να γίνει χρήση μίας συνάρτησης μόνο.
Τα αποτελέσματα θα επιστρέφονται στο main με χρήση
καταλλήλων παραμέτρων και όχι με την εντολή return.
Περιεχόμενα
• Ορισμός δομής
• Εκχώρηση και σύγκριση δομών
• Ορισμός πίνακα από δομή
• Δομές μέσα σε δομές
• Δομές και Συναρτήσεις
• Συναρτήσεις που επιστρέφουν δομές
• Παραδείγματα
5
Ορισμός Δομής (1)
Μία δομή είναι ένας σύνθετος τύπος δεδομένων που ορίζεται από τον
προγραμματιστή. Μία δομή μπορεί να περιέχει διαφορετικούς τύπους
δεδομένων όπως int, chat, double ακόμη και arrays. O ορισμός μίας δομής γίνεται
με την δεσμευμένη λέξη struct. Μία δομή που πχ αναφέρεται σε ένα υπάλληλο
είναι η εξής:
struct ypallilos
{
char eponimo[40];
int age;
double salary;
} yp1;
struct ypallilos
{
char eponimo[40];
int age;
double salary;
};
7
Παράδειγμα 1
• To παρακάτω παράδειγμα ορίζει και εκχωρεί τιμές σε δομές
#include <iostream>
using namespace std;
int main()
{
struct ypallilos
{
char* eponimo;
int age;
double salary;
} yp1;
yp1.eponimo= "Papadopoulos";
yp1.age = 28;
yp1.salary = 1200;
cout << "Stoixeia ypallilou \n" << yp1.eponimo << " "
<< yp1.age << " " << yp1.salary << endl;
system("PAUSE"); return 0;
}
8
Παράδειγμα 2
• Είναι επίσης δυνατόν να οριστεί ο τύπος της δομής και μετά να δηλωθούν και
δημιουργηθούν μεταβλητές του συγκεκριμένου τύπου δομής. Επίσης είναι δυνατό να
δοθούν τιμές στα πεδία μίας δομής ακλουθώντας τον τρόπο που δίδονται τιμές στα
στοιχεία ενός πίνακα.
#include <iostream>
using namespace std;
int main()
{ struct ypallilos
{
char* eponimo;
int age;
double salary;
};
ypallilos yp1 ={ "Papadopoulos", 28,1200};
ypallilos yp2 ={ "Pappas", 40,1300};
cout << "Stoixeia ypallilou \n" << yp1.eponimo << " "
<< yp1.age << " " << yp1.salary << endl;
cout << "Stoixeia ypallilou \n" << yp2.eponimo << " "
<< yp2.age << " " << yp2.salary << endl;
system("PAUSE"); return 0;}
9
Παρατηρήσεις
• Στο παραπάνω πρόγραμμα ορίζονται δύο μεταβλητές με
τύπο την δομή ypallilos.
• Ο ορισμός τους είναι με παρόμοιο τρόπο που ορίζονται δύο
μεταβλητές οποιοδήποτε τύπου πχ με δύο ακεραίους int a, b;
• Τα μέλη μπορεί να είναι οποιοσδήποτε τύπος δεδομένων
ακόμη και πίνακες ή και δομές όπως θα δούμε αργότερα. Το
παρακάτω παράδειγμα κάνη χρήση δομής με μέλος ένα
πίνακα
10
Παράδειγμα 3
#include <iostream>
using namespace std;
int main()
{
struct spoudastis
{ char spoud_Name[40];
float spoud_vathmos[2]; };
struct spoudastis sp1;
cout<<" Dose ta stoixia tou spoudasti"<<endl;
cout<<" Eponimo ";
cin.getline(sp1.spoud_Name,40);
cout<<" Vathmo ";
cin>>sp1.spoud_vathmos[0]>>sp1.spoud_vathmos[1];
cout<<endl<< " Stoixeia spoudasti"<<endl;
cout<<sp1.spoud_Name<<" "<<sp1.spoud_vathmos[0]
<<" "<<sp1.spoud_vathmos[1]<<endl;
system("PAUSE"); return 0;
}
11
Εκχώρηση και σύγκριση δομών
Επιτρέπεται η εκχώρηση από μία μεταβλητή δομής
σε μία άλλη εφόσον είναι του ιδίου τύπου δομής.
Αντίθετα όπως είναι γνωστό δεν επιτρέπεται
εκχώρηση από ένα πίνακα σε ένα άλλο γιατί ο
πινάκας θεωρείται ότι είναι δείκτης προς σταθερά
(constant pointer)
12
Παράδειγμα Εκχώρησης
//DS03b
#include <iostream>
using namespace std;
int main()
{
struct ypallilos
{ char* eponimo;
int age;
double salary; };
ypallilos yp1 ={ "Papadopoulos", 28,1200};
ypallilos yp2 =yp1;
cout << "Stoixeia 1ou ypallilou \n" << yp1.eponimo << " "
<< yp1.age << " " << yp1.salary << endl;
cout << "Stoixeia 2u ypallilou \n" << yp2.eponimo << " "
<< yp2.age << " " << yp2.salary << endl;
system("PAUSE"); return 0;
}
13
Εκχωρήσεις - Συγκρίσεις
Αντί για εκχώρηση μίας δομής σε άλλη το ίδιο αποτέλεσμα επιτυγχάνεται και με εκχωρήσεις
των μελών της μίας μεταβλητής στην άλλη δηλαδή στο παραπάνω παράδειγμα η εκχώρηση
yp2=yp1;
ισοδυναμεί με τις εκχωρήσεις
Yp2.eponimo=yp1.eponymo;
Yp2.age=yp1.age;
Yp2.salary=yp1.salary;
Ενώ επιτρέπεται εκχώρηση μεταξύ δύο μεταβλητών του ιδίου τύπου δομής για να γίνει
σύγκριση δύο δομών θα πρέπει να εξεταστούν τα πεδία των δύο δομών χωριστά. Το γεγονός
αυτό συνεπάγεται ότι είναι λάθος προτάσεις του τύπου
if (yp2==yp1)
Η σύγκριση δύο δομών γίνεται με μία πιο σύνθετη λογική πρόταση που εξετάζει όλα τα μέλη
της κάθε μεταβλητής χωριστά
if (yp2.eponimo==yp1.eponimo && yp2.age==yp2.age && yp2.salary==yp1.salary
14
Παράδειγμα ds05
int main()
{ struct ypallilos
{
char* eponimo; int age; double salary;
};
15
Ορισμός πίνακα από δομή (2)
Ο τρόπος αυτός της οργάνωσης είναι καλύτερος από τον ορισμό πολλών πινάκων για
την αποθήκευση των δεδομένων.
Στο παραπάνω παράδειγμα θα έπρεπε να δημιουργηθούν 3 πίνακες για να
αποθηκεύσουν τα δεδομένα: ένας για τα eponimo ένας για τα age ένας για τα salary
O ορισμός πίνακα δομών μπορεί να γίνει ταυτόχρονα με τον ορισμό της δομής
struct ypallilos
{
char* eponimo;
int age;
double salary;
} epix[2] ;
16
18
Παράδειγμα
struct dstudent
{ // ds06
char lastName[40];
int testScore; int programmingScore;
double mesos;
};
void inStoixeia(dstudent& fstud)
{ int score;
cout<<"Dose eponymo"; cin >> fstud.lastName;
cout<<"dose tous dio vathmous";
cin >> fstud.testScore >> fstud.programmingScore;
fstud.mesos = (fstud.testScore + fstud.programmingScore) / 2.0; }
void printStoixeia(dstudent fstud)
{
cout<< fstud.lastName<< " " << fstud.testScore
<< " " << fstud.programmingScore << " " << fstud.mesos << endl;
}
int main()
{ dstudent stud1,stud2;
inStoixeia(stud1); inStoixeia(stud2);
printStoixeia(stud1); printStoixeia(stud2);
system("PAUSE"); return 0; }
19
Συναρτήσεις που επιστρέφουν δομές
Μία συνάρτηση μπορεί να έχει σαν επιστρεφόμενο τύπο μία
δομή. Στην περίπτωση αυτή η συνάρτηση δηλώνεται ότι
επιστρέφει δομή. Το αμέσως προηγούμενο παράδειγμα
μπορεί, αντί της συνάρτησης inStoixeia που είναι τύπου void
να κάνει χρήση μίας συνάρτησης που επιστρέφει στο κυρίως
πρόγραμμα μία δομή. H συνάρτηση ReadStoixeia που
επιστρέφει μία δομή δεν δέχεται καμία παράμετρο και όταν
καλείται στο κυρίως πρόγραμμα η τιμή που επιστρέφει
εκχωρείται σε μεταβλητή τύπου δομής.
Η συνάρτηση κάνει χρήση μίας τοπικής μεταβλητής τύπου
δομής για να αποθηκεύσει το στοιχεία και η εντολή return
επιστρέφει τα στοιχεία στο κυρίως πρόγραμμα.
20
21
Ενότητα # 9: Εισαγωγή στον Αντικειμενοστραφή
Προγραμματισμό
Περιεχόμενα
• Αντικειμενοστραφείς γλώσσες
• Κλάση και Αντικείμενα
• Χρήση αντικειμένων
• Δημόσια και ιδιωτικά μέλη
• Ενθυλάκωση
• Παραδείγματα
5
Αντικειμενοστραφείς γλώσσες
Ενώ ο διαδικαστικός προγραμματισμός δίνει έμφαση στις
διαδικασίες ο αντικειμενοστραφείς δίνει έμφασή στα
αντικείμενα.
Το μοντέλο στο οποίο βασίζεται μία αντικειμενοστραφής
γλώσσα είναι ο φυσικός και τεχνητός κόσμος που αποτελείται
από αντικείμενα (άνθρωπος, ζώο, σπίτι, αυτοκίνητο κλπ).
Ένα αυτοκίνητο έχει κάποια βασικά χαρακτηριστικά (ρόδες,
τιμόνι, φρένο). Σε ένα αυτοκίνητο μπορούν να εφαρμοστούν
και ορισμένες διαδικασίες: φρενάρισμα, στρίψιμο, αύξηση
ταχύτητας.
Ο τρόπος με τον οποίο εφαρμόζονται οι διαδικασίες είναι
κρυμμένος από τον οδηγό (δηλαδή πως φρενάρει ή πως
δουλεύει η μηχανή)
6
Κλάση
Μια κλάση είναι ένας γενικός ορισμός αντικειμένου που καθορίζει
χαρακτηριστικά και ενέργειες.
Η κλάση είναι το πρότυπο που δημιουργεί αντικείμενα. Το
αντικείμενο είναι ένα στιγμιότυπο μίας κλάσης.
Ένα αντικείμενο είναι μία οντότητα που η συμπεριφορά του
καθορίζεται από τις ενέργειες που μπορεί να εκτελέσει το
συγκεκριμένο αντικείμενο.
Η κλάση autokinito ορίζει μια γενική περιγραφή που θα μπορούσε
να περιλαμβάνει:
Τα χαρακτηριστικά: μάρκα, χρώμα, θέσεις, τροχοί.
Τις ενέργειες: pato_gkazi, frenaro, strivo
To αντικείμενο oxima_ix4054 είναι ένα συγκεκριμένο φυσικό
αντικείμενο που έχει μία και μοναδική ταυτότητα διαθέτει όλα τα
χαρακτηριστικά και τις ενέργειες της κλάσης που ανήκει
7
Κλάση και Αντικείμενα
Μια κλάση (ή τάξη) είναι μια διευρυμένη έννοια μίας δομής δεδομένων
όπως οι πίνακες ή οι δομές. Όμως μία κλάση αντί να έχει μόνο
δεδομένα, μπορεί να έχει και συναρτήσεις
Ένα αντικείμενο (object) είναι η υλοποίηση (instantiation- στιγμιότυπο)
μιας κλάσης. Αν δούμε τις κλάσεις σαν μεταβλητές τότε μία κλάση ορίζει
τον τύπο της μεταβλητής ενώ το αντικείμενο είναι μία μεταβλητή που
έχει σαν τύπο την κλάση. Από την άποψη των μεταβλητών, μία τάξη θα
είναι το είδος, και ένα αντικείμενο θα είναι η μεταβλητή.
Μία τέτοια κλάση θα μπορούσε να είναι η κλάση σπουδαστής ενώ
αντικείμενα οι σπουδαστές ενός τμήματος.
9
Άλλα Χαρακτηριστικά
Ο αντικειμενοστραφής προγραμματισμός διαθέτει και τα παρακάτω
χαρακτηριστικά που βέβαια αντιστοιχούν και το προηγούμενο
παράδειγμα του αυτοκινήτου
• Encapsulation (ενθυλάκωση): Οι διαδικασίες και τα δεδομένα
μπορούν να κρύβονται από το χρήστη
• Polymorphism (πολυμορφισμός): Αντικείμενα που ανήκουν σε
παρόμοιες κλάσεις μπορούν να έχουν κοινά χαρακτηριστικά αλλα και
τρόπο προσπέλασης. Με τον τρόπο αυτό ο χρήστης να μπορεί να τα
χειριστεί χωρίς να χρειάζεται να εφαρμόζει νέες διαδικασίες.
• Inheritance (κληρονομικότητα): Μπορούν να δημιουργηθούν νέα
αντικείμενα με βάση ένα άλλο ήδη υπάρχον και τα νέα αντικείμενα
να κληρονομούν τα χαρακτηριστικά του παλιού αλλά και να
διαθέτουν δικά τους χαρακτηριστικά και ενέργειες.
10
11
Public Προσδιοριστικό
H λέξη public είναι ένα προσδιοριστικό πρόσβασης (access specifier) που
καθορίζει τον τρόπο πρόσβασης που έχουν τα μέλη τους. Η public
καθορίζει ότι οι δύο συναρτήσεις μέλη TimesPlevron Emvado είναι
προσβάσιμα από οποιοδήποτε σημείο, όπου το αντικείμενο έχει οριστεί
και είναι ορατό.
Οι δυο μεταβλητές x και y είναι private επειδή κάθε μέλος μίας κλάσης
που δεν ορίζεται άμεσα με τον τρόπο πρόσβασης (private, public,
protected) είναι private. Οι τρόποι πρόσβασης θα εξηγηθούν πιο
παρακάτω
Οι συναρτήσεις μέλη που ανήκουν σε μία κλάση λέγονται και μέθοδοι.
Συνηθίζεται τα ονόματα των κλάσεων να αρχίζουν με κεφαλαίο γράμμα.
Προσοχή: Μετά τον ορισμό της κλάσης ακολουθεί ερωτηματικό
τερματισμού. Αν παραλειφθεί ο compiler εμφανίζει λάθη τα οποία
παραξενεύουν τον προγραμματιστή και τα οποία δεν σχετίζονται με την
συγκεκριμένη παράλειψη.
12
Χρήση αντικειμένων
Ενώ έχει οριστεί μία κλάση δεν έχουμε δημιουργήσει ακόμη αντικείμενα.
Τα αντικείμενα έχουν το τύπο της κλάσης και αποτελούν στιγμιότυπα
(instantiations) της κλάσης. Τα αντικείμενα δημιουργούνται με την
δήλωση τους όπως δηλώνονται όλες οι μεταβλητές σε ένα πρόγραμμα,
δηλ.
Korthogonio sxima;
13
Πρόσβαση στα μέλη
Η πρόσβαση στις συναρτήσεις μέλη της κλάσης Παρατηρήστε τη διαφορά μεταξύ του ονόματος της
γίνεται με χρήση του τελεστή (.) της τελείας. κλάσης και το ονόματος του αντικειμένου. Στο
προηγούμενο παράδειγμα στην δήλωση
sxima.TimesPlevron (10,20); Korthogonio sxima;
cout << "To emvado = " << sxima.Emvado()<<endl;
Korthogonio ήταν το όνομα της κλάσης (δηλαδή, το
Στην περίπτωση αυτή εφαρμόζουμε την μέθοδο είδος), ενώ sxima ήταν ένα αντικείμενο του τύπου
ΤimesPlevron και την μέθοδο Emvado στο Korthogonio. Είναι η ίδια σχέση που έχουν στην
αντικείμενο sxima. Το πλήρες main είναι: ακόλουθη δήλωση:
int a;
Program 5.1.1 ο τύπος int και η μεταβλητή a. Tο int είναι το όνομα του
int main () { τύπου και το a είναι το όνομα της μεταβλητής.
Korthogonio sxima;
sxima.TimesPlevron (10,20); //xrisi tis Όπως αναφέρθηκε και προηγουμένως οι συναρτήσεις
TimesPlevron sto sxima μέλη που ανήκουν σε μία κλάση λέγονται και μέθοδοι
cout << "To emvado = " << sxima.Emvado()<<endl; και καλούνται πάντα σε συνδυασμό με κάποιο
αντικείμενο δηλαδή εφαρμόζεται η μέθοδος στο
system("PAUSE"); αντικείμενο.
return EXIT_SUCCESS;
}
14
15
Επεξήγηση προγράμματος (1)
Η πρόσβαση στα μέλη x και y έχει καθοριστεί να είναι private. Η δήλωση
private αρνείται την πρόσβαση σε αυτές τις μεταβλητές από οποιοδήποτε
μέρος έξω από την κλάση.
Τα x y που είναι ιδιωτικά είναι προσπελάσιμα από την μέθοδο
TimesPlevron γιατί η μέθοδος είναι μέλος της κλάσης. Ο μόνος τρόπος
πρόσβασής και απόδοσης τιμών στα x y είναι μέσα από την συνάρτηση-
μέλος TimesPlevron που μπορεί να καθορίσει τιμές για τα μέλη μέσα
στην κλάση αντικειμένου. Ως εκ τούτου, το υπόλοιπο μέρος του
προγράμματος δεν χρειάζεται να έχει άμεση πρόσβαση σε αυτές τις δύο
μεταβλητές.
16
17
Ενθυλάκωση
Σε μεγαλύτερα προγράμματα είναι πολύ σημαντικό το
γεγονός ότι κάποιο μέλος του αντικειμένου δεν μπορεί
να τροποποιηθεί παρά μόνο με μεθόδους που έχουν
οριστεί για το σκοπό αυτό. Θα προσπαθήσουμε να
δούμε τα οφέλη της ενθυλάκωσης με ένα πολύ απλό
παράδειγμα
Στο παρακάτω πρόγραμμα οι μεταβλητές x και y δεν
προστατεύονται, αλλά δηλώνονται public δηλαδή
κάποιος μπορεί να αλλάξει τις τιμές μέσα από το main.
Επομένως η μέθοδος ΤimesPlevron δεν χρειάζεται αφού
με την εντολή sxima.x=10 μπορώ να αλλάξω την πλευρά
ενός αντικειμένου της κλάσης.
18
Παράδειγμα ενθυλάκωσης
using namespace std; Στην περίπτωση που γίνει κάποια αλλαγή στην κλάση Korthogonio θα
class Korthogonio { πρέπει ο προγραμματιστής να φροντίσει οι αλλαγές να γίνουν και στο
public: κυρίως πρόγραμμα.
Αν δηλαδή τα χ y να μετονομαστούν σε p1 και p2 τότε για να τρέξει
int x, y; σωστά το πρόγραμμα θα πρέπει οι εντολές
int Emvado (){ sxima.x=10; sxima.y=20; να γίνουν
return (x*y);} sxima.p1=10; sxima.p2=20;
}; Αντίθετα με την ενθυλάκωση και την χρήση μεθόδων πού έχουν
αποκλειστική πρόσβαση σε μεταβλητές οποιαδήποτε αλλαγή του
int main () { κώδικα στην κλάση δεν απαιτεί αλλαγές στο main όπως φαίνεται στο
Korthogonio sxima; παρακάτω παράδειγμα που είναι το γνωστό παράδειγμα που έχουμε
δεί μέχρι τώρα και που εφαρμόζεται η ενθυλάκωση.
sxima.x=10; public:
sxima.y=20; void TimesPlevron(int a, int b){
cout << "To emvado = " << x = a; y = b;}
sxima.Emvado()<<endl; int Emvado (){
return (x*y);} };
system("PAUSE"); int main () {
return EXIT_SUCCESS; Korthogonio sxima;
sxima.TimesPlevron (10,20); //xrisi tis TimesPlevron sto sxima
} cout << "To emvado = " << sxima.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS; }
19
Παρατηρήσεις (1)
Οι συναρτήσεις (μέθοδοι) μίας κλάσης μπορούν να οριστούν και
εκτός της κλάσης με τον παρακάτω τρόπο
using namespace std;
//5.1.2
class Korthogonio {
int x, y;
public:
void TimesPlevron(int,int);
int Emvado () ;
};
void Korthogonio::TimesPlevron (int a, int b) {
x = a;
y = b;
}
int Korthogonio::Emvado() {
return (x*y);
}
20
Παρατηρήσεις (2)
Ο ορισμός του αντικειμένου μπορεί να γίνει και με τον παρακάτω τρόπο.
Οι συναρτήσεις πρώτα δηλώνονται μέσα στην κλάση και μετά ορίζονται
εκτός της κλάσης με την χρήση του scope operator (::) που είναι δύο
άνω κάτω τελείες). Ο scope operator (::) (τελεστής διάκρισης εμβέλειας,
τελεστής επίλυσης εμβέλειας) προσδιορίζει την κλάση στην οποία η
συνάρτηση ανήκει, και η συνάρτηση έχει ακριβώς τις ίδιες ιδιότητες που
έχει το πρωτότυπο της σαν η συνάρτηση συμπεριλήφθηκε μέσα στον
ορισμό της κλάσης.
Mε τον τρόπο αυτό, ορίζονται τα μέλη μίας κλάσης εκτός του χώρου της
κλάσης, δηλαδή διευκρινίζεται ότι ορίζεται μια συνάρτηση που είναι
μέλος της κλάσης Korthogonio και όχι μία συνηθισμένη συνάρτηση.
Ο τρόπος αυτός θυμίζει τον τρόπο που συναρτήσεις δηλώνονται πρίν το
main, κάνοντας χρήση των πρωτοτύπων των συναρτήσεων, και ορίζονται
μετά το main.
21
Παρατηρήσεις (3)
Χάριν ευκολίας και για να γίνει σύγκριση παρατίθενται οι δύο τρόποι ο
ένας δίπλα στον άλλο:
Η μόνη διαφορά ανάμεσα σε συνάρτηση με τον πλήρη ορισμό μέσα στην
κλάση του και σε μία συνάρτηση που έχει μόνο το πρωτότυπο στη κλάση
και αργότερα τον ορισμό της, είναι ότι στην πρώτη περίπτωση, η
συνάρτηση θεωρείται αυτομάτως ένα ενσωματωμένο μέλος συνάρτηση
από το μεταγλωττιστή, ενώ στη δεύτερη θα είναι μια inline συνάρτηση
μέλος της τάξης, η οποία στην πραγματικότητα δεν έχει καμία
διαφορετική συμπεριφορά.
Εξυπακούεται ότι ένα αντικείμενο μπορεί να έχει μερικές από τις
συναρτήσεις να ορίζονται μέσα και κάποιες άλλες έξω από το σώμα του
αντικειμένου αρκεί να χρησιμοποιείται όπου χρειάζεται ο τελεστής (::)
(τελεστής διάκρισης εμβέλειας).
22
Παρατηρήσεις (4)
//Program 5.1.1 //Program 5.1.2
using namespace std; using namespace std;
class Korthogonio { class Korthogonio {
int x, y; int x, y;
public: public:
void TimesPlevron (int a, int b){ void TimesPlevron(int,int);
x = a; int Emvado () ;
y = b; };
} void Korthogonio::TimesPlevron (int a, int b) {
int Emvado (){ x = a;
return (x*y); y = b;
} }
}; int Korthogonio::Emvado() {
return (x*y);
}
23
Χρήση μιας κλάσης (1)
Ένα από τα μεγαλύτερα πλεονεκτήματα της κλάσης είναι ότι, όπως και κάθε άλλο είδος,
μπορούμε να δηλώσουμε διάφορα αντικείμενα της.
Για παράδειγμα, μετά με το προηγούμενο παράδειγμα της τάξης Korthogonio, θα
μπορούσαμε να έχουμε δηλώσει και ένα άλλο αντικείμενο ή όσα άλλα αντικείμενα θέλουμε:
//Program 5.2.1
using namespace std;
class Korthogonio {
int x, y;
public:
void TimesPlevron(int a, int b){ x = a; y = b;}
int Emvado (){return (x*y);}
};
int main () {
Korthogonio sxima1, sxima2;
sxima1.TimesPlevron (10,20);
sxima2.TimesPlevron (40,50);
cout << "To emvado = " << sxima1.Emvado()<<endl;
cout << "To emvado = " << sxima2.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
24
26
6
Constructors (1)
Είναι αναγκαίο τα αντικείμενα να αρχικοποιούν τις
μεταβλητές ή να τους αποδίδεται δυναμική μνήμη κατά τη
διάρκεια της διαδικασίας της δημιουργίας τους για να
λειτουργούν σωστά και να αποφεύγεται η εμφάνιση
απροσδόκητων τιμών κατά τη διάρκεια της εκτέλεσής τους.
Για παράδειγμα, τι θα συνέβαινε αν στο προηγούμενο
πρόγραμμα γινόταν κλήση στην συνάρτηση μέλος Emvado ()
προτού κληθεί η συνάρτηση TimesPlevron (); Μάλλον θα
είχαμε πάρει ένα απροσδιόριστο αποτέλεσμα δεδομένου ότι
στα μέλη x και y ποτέ δεν έχει ανατεθεί μια τιμή. Ένα τέτοιο
γεγονός φαίνεται όταν τρέξουμε το προηγούμενο
πρόγραμμα καλώντας την συνάρτηση Emvado() πριν δοθούν
τιμές στα αντικείμενα.
7
Constructors (2)
Προκειμένου να αποφευχθεί αυτό, μια κλάση
μπορεί να περιλαμβάνει μια ειδική συνάρτηση που
ονομάζεται constructor, η οποία καλείται αυτόματα
κάθε φορά που ένα νέο αντικείμενο της κλάσης
αυτής έχει δημιουργηθεί. Αυτή η συνάρτηση
constructor ακολουθεί τους παρακάτω κανόνες
πρέπει να έχει το ίδιο όνομα με την κλάση, και
δεν μπορεί να επιστρέφει τιμή (ούτε καν και την τιμή
void), δηλαδή μία συνάρτηση constructor δεν έχει τύπο.
8
Παράδειγμα
Program 5.3.1
class Korthogonio {
int x, y;
public:
void TimesPlevron(int a, int b){ x = a; y = b;}
int Emvado (){return (x*y);}
};
int main () {
Korthogonio sxima1, sxima2;
// Xrisi Emvado() xoris na exoun apodothei times
cout << "To emvado = " << sxima1.Emvado()<<endl;
cout << "To emvado = " << sxima2.Emvado()<<endl;
sxima1.TimesPlevron (10,23);
sxima2.TimesPlevron (40,50);
cout << "To emvado = " << sxima1.Emvado()<<endl;
cout << "To emvado = " << sxima2.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Χρήση Constructors
Οι constructors χρησιμοποιούνται για να αποδώσουν τιμές στις μεταβλητές που είναι μέλη
μίας κλάσης. Οι τιμές αυτές μπορεί να είναι οποιεσδήποτε θέλει ο προγραμματιστής ή
κάποιες εξ ορισμού τιμές. H κλάση Korthogonio συμπεριλαμβανομένου μίας constructor
μεθόδου παρουσιάζεται παρακάτω:
Program
using namespace std;//5.4.1
class Korthogonio {
int x, y;
public:
Korthogonio(int a, int b){x = a; y = b;};
int Emvado (){return (x*y);};
};
int main () {
Korthogonio sxima1 (10,20); //Dilosi kai arxikopoihsi antikeimenou
cout << "To emvado = " << sxima1.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
10
Παρατηρήσεις
Όπως μπορείτε να διαπιστώσετε, τα αποτελέσματα του
προγράμματος αυτού είναι το ίδιο με την προηγούμενο
παράδειγμα που διέθετε την συνάρτηση TimesPlevron.
Αλλά τώρα, έχουμε αφαιρέσει την συνάρτηση TimesPlevron (), και
έχουμε συμπεριλάβει ένα constructor (κατασκευαστή) που εκτελεί
μια παρόμοια λειτουργία δηλαδή αποδίδει τιμές ( αρχικοποιεί)
στις μεταβλητές x y κάνοντας χρήση των παραμέτρων που
υπάρχουν στην συνάρτηση constructor.
Υπενθυμίζεται ότι χωρίς τον ορισμό ενός constructor πρώτα πρέπει
να οριστούν τα αντικείμενα και μετά να γίνει αρχικοποίηση όπως
φαίνεται και στο παρακάτω πρόγραμμα που έχουμε δεί και
χρησιμοποιείται για την κατανόηση των εννοιών κλάσεων και
αντικειμένων από την αρχή του κεφαλαίου αυτού.
11
Παράδειγμα Constructor
class Korthogonio { //5.1.1 Ο constructor Korthogonio μπορεί να
int x, y; οριστεί και εκτός της κλάσης
public:
void TimesPlevron(int a, int b){ x = a; y = b;} using namespace std; //5.5.1
class Korthogonio {
int Emvado (){return (x*y);} int x, y;
}; public:
Korthogonio(int , int );
int Emvado ();
int main () { };
Korthogonio sxima1;
sxima1.TimesPlevron (10,20); Korthogonio::Korthogonio(int a, int b){
x = a; y = b;}
cout << "To emvado = " <<
sxima1.Emvado()<<endl; int Korthogonio::Emvado (){
return (x*y);}
system("PAUSE"); int main () {
return EXIT_SUCCESS; Korthogonio sxima1 (10,20);
} cout << "To emvado = " << sxima1.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
12
Πολλαπλοί Constructors (1)
Μία κλάση μπορεί να έχει παραπάνω από ένα constructors με διαφορετικό όμως τύπο και
πλήθος παραμέτρων. Όλοι οι constructors σε μία κλάση πρέπει να έχουν το ίδιο όνομα και
αυτό που διαφοροποιεί τον ένα από τον άλλο είναι οι παράμετροι. (Γίνεται υπερφόρτιση-
overloading).
system("PAUSE");
return EXIT_SUCCESS;
}
13
14
Πολλαπλοί Constructors (3)
Οποιοσδήποτε constructor που δεν έχει παραμέτρους καλείται εξορισμού constructor
(default constructor). Μία κλάση διαθέτει τον εξορισμό constructor με δύο τρόπος:
• είτε ο προγραμματιστής ορίζει ένα τέτοιο constructor
• είτε ο compiler αυτόματα δημιουργεί ένα τέτοιο constructor στην περίπτωση που
στη κλάση δεν συμπεριλαμβάνεται κανένας constructor από τον προγραμματιστή. Στην
δεύτερη αυτή περίπτωση όμως δεν αρχικοποιείται κανένα αντικείμενο.
Αν ο προγραμματιστής ορίσει κάποιο constructor ο compiler δεν δημιουργεί αυτόματα τον
εξ’ ορισμού constructor.
Σε όλες τις συναρτήσεις ο προγραμματιστής μπορεί να εκχωρήσει κάποιες εξορισμού τιμές
στις παραμέτρους. Το ίδιο μπορεί να γίνει και στις συναρτήσεις μέλη μίας κλάσης καθώς
και στους constructors που και αυτοί είναι συναρτήσεις. Οι αρχικές τιμές εκχωρούνται στην
περίπτωση που κληθεί o constructor χωρίς παραμέτρους. Το παρακάτω πρόγραμμα
περιέχει μόνο ένα constructor με τον οποίο υπάρχει δυνατότητα απόδοσης αρχικών τιμών.
15
Παράδειγμα
using namespace std;//5.6.2
class Korthogonio {
int x, y;
public:
Korthogonio(int a=0, int b=0){ x = a; y = b;}
int Emvado (){return (x*y);}
};
int main () {
// kaleitai o constuctors me tis default times 0,0
Korthogonio sxima3;
cout << "To emvado = " << sxima3.Emvado()<<endl;
system("PAUSE");
return EXIT_SUCCESS; }
Προσοχή: Συνήθως όλες τις φορές είναι απαραίτητο να αρχικοποιείται ένα αντικείμενο γι’ αυτό
καλό είναι πάντα να περιλαμβάνεται ένας constructor στο ορισμό μίας κλάσης.
16
Destructors
Μια συνάρτηση destructor εκπληρώνει το αντίθετο από ένα constructor.
Καλείται αυτόματα όταν ένα αντικείμενο καταστρέφεται, είτε επειδή το
πρόγραμμα έχει φτάσει σε σημείο εκτός του πεδίου εμβέλειας του
αντικειμένου (για παράδειγμα, σε περίπτωση που ορίστηκε ως ένα
τοπικό αντικείμενο μέσα σε συνάρτηση και η συνάρτηση τελειώνει) ή
επειδή είναι ένα αντικείμενο που έχει δημιουργηθεί με δυναμική
κατανομή μνήμης και απελευθερώνεται η μνήμη που καταλαμβάνει
χρησιμοποιώντας τον τελεστή delete.
Οι destructors πρέπει να έχουν το ίδιο όνομα με την κλάση, αλλά
προηγείται το σύμβολο (~) και δεν θα πρέπει να επιστρέφει καμία τιμή.
Εάν δεν ορίζεται από τον προγραμματιστή δημιουργείται αυτόματα από
το πρόγραμμα. Κάθε κλάση έχει ακριβώς ένα destructor δηλαδή
απαγορεύεται να γίνει υπερφόρτωση σε ένα destructor (ενώ μπορεί να
έχει παραπάνω από ένα constructor). O destructor αυτός είναι είτε ο εξ
ορισμού που δημιουργεί αυτόματα το σύστημα είτε ένας που ορίζει ο
προγραμματιστής
17
Χρήση Destructors
• Η χρήση των destructors είναι ιδιαίτερα κατάλληλη,
όταν σε ένα αντικείμενο εκχωρείται δυναμική μνήμη
κατά τη διάρκεια της ζωής του και κατά τη στιγμή της
καταστροφής θέλουμε να απελευθερωθεί η μνήμη
που καταλαμβάνει το αντικείμενο.
• To επόμενο παράδειγμα εμφανίζει τον τρόπο που
δημιουργείται και καταστρέφεται ένα αντικείμενο. Ο
τρόπος αυτό για να είναι κατανοητός περιλαμβάνει
εντολές εμφάνισης μηνυμάτων (cout) μέσα στους
ορισμούς των constructor και destructor.
18
Παραδείγματα χρήσης Destructors
Παράδειγμα 1 Παράδειγμα 2
using namespace std; int main () {
{Korthogonio sxima1 (100,23);
class Korthogonio { {Korthogonio sxima2 (400,50);
int x, y; cout << "To emvado = " <<
public: sxima2.Emvado()<<endl;
~Korthogonio(); }
Korthogonio(int , int ); cout << "To emvado = " <<
int Emvado (){return (x*y);} sxima1.Emvado()<<endl;
}; }
system("PAUSE");
Korthogonio::Korthogonio(int a, int b){ return EXIT_SUCCESS;
x = a; y = b; cout<<"Dimiourgia antikeimeno"<<endl;
}
}
Korthogonio::~Korthogonio() {
cout<<"Katastrofi antikeimeno"<<endl;
}
19
Παράδειγμα 1
using namespace std;
class Korthogonio {
int x, y;
public:
~Korthogonio();
Korthogonio(int , int );
int Emvado (){return (x*y);}
};
Korthogonio::~Korthogonio() {
cout<<"Katastrofi antikeimeno"<<endl;
}
20
Παράδειγμα 2
int main () {
{Korthogonio sxima1 (100,23);
{Korthogonio sxima2 (400,50);
cout << "To emvado = " << sxima2.Emvado()<<endl;
}
cout << "To emvado = " << sxima1.Emvado()<<endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
21
Εργαστήριο 1
Εισαγωγή στο περιβάλλον Dev C++ και στην γλώσσα C++
Άσκηση 1.1
Εύρεση του μεγαλύτερου από 3 ακέραιους που εισάγονται από το πληκτρολόγιο
#include <cstdlib>
#include <iostream>
system("PAUSE");
return EXIT_SUCCESS;
}
#include <cstdlib>
#include <iostream>
using namespace std;
system("PAUSE");
return EXIT_SUCCESS;
}
#include <cstdlib>
#include <iostream>
#include <cmath>
riza=sqrt(a);
cout<<"h tetrafoniki riza tou arithou";
cout<<a<<" einai = "<<riza;
system("PAUSE");
return EXIT_SUCCESS;
}
Να γίνει εκτέλεση του προγράμματος και να ελεγχθεί ότι το πρόγραμμα είναι σωστό για τις
παρακάτω τριάδες αριθμών που αντιπροσωπεύουν τις δύο πλευρές ορθογωνίου τριγώνου και την
υποτείνουσα
Άσκηση 2.1
Εύρεση του μεγαλύτερου από 3 ακέραιους που εισάγονται από το πληκτρολόγιο
#include <cstdlib>
#include <iostream>
using namespace std;
system("PAUSE");
return EXIT_SUCCESS;
}
#include <cstdlib>
#include <iostream>
using namespace std;
Παρατηρήσεις:
Το if… else θεωρείται μία εντολή και δεν χρειάζεται να περικλείεται σε αγκύλες { }
Το ίδιο πρόγραμμα με διαφορετική στοίχιση γράφεται με τέτοιο τρόπο που διευκολύνει το διαχωρισμό
των περιπτώσεων
cout<<"\n\n\n";
system("PAUSE");
return EXIT_SUCCESS;
}
Άσκηση 3.1
Εύρεση αθροίσματος ακεραίων με χρήση της εντολής for
#include <cstdlib>
#include <iostream>
using namespace std;
system("PAUSE");
return EXIT_SUCCESS;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Παρατηρήσεις:
Το setw καθορίζει το εύρος εκτύπωσης και χρειάζεται την βιβλιοθήκη iomanip
#include <cstdlib>
#include <iostream>
using namespace std;
int main(void)
{
int num,intnum;
int plithos=0;
cout<<"Give me a number ";
cin>>num;
// using do statement
intnum=num;
do
{
plithos++;
intnum=intnum/10.;
}
while (intnum !=0);
cout << "The number "<<num<< " has "<< plithos <<" digits"<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
int main ()
{
int zari1,zari2;
srand ( time(NULL) ); // initialize random seed
for (int i=0;i<36;i++){
zari1 = rand() % 6 + 1; //tixaios apo 1 eow 6: */
zari2 = rand() % 6 + 1;
cout<<zari1<<" "<<zari2<<" ";
if (zari1==4 && zari2==4) cout<<" dortia";
if (zari1==6 && zari2==6) cout<<" exares";
cout<<endl;
}
system("PAUSE");
return 0;
}
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;
int main ()
{
int mystikos, epilogi;
do {
cout << "Vres ton arithmo apo to 1 eos 10: ";
cin>>epilogi;
if (mystikos<epilogi) cout<<"Mantepse pio hamila\n";
else if (mystikos>epilogi) cout<<"Mantepse pio psila\n";
} while (mystikos!=epilogi);
cout<<"Mpravo ton vrikes"<<endl;
system("PAUSE");
return 0;
}
Άσκηση για τον σπουδαστή:
Να προστεθούν οι κατάλληλες εντολές ώστε να εμφανίζεται και πόσες προσπάθειες έχει κάνει
συνολικά ο παίκτης μέχρι να μαντέψει σωστά τον αριθμό.
#include <cstdlib>
#include <iostream>
Άσκηση 4.1
Να εισάγονται σε πίνακα 6 αριθμοί. Μετά την εμφάνιση του πίνακα να εμφανίζεται το μεγαλύτερο
στοιχείο του πίνακα και η θέση του.
#include <cstdlib>
#include <iostream>
using namespace std;
const int LIM = 6;
int main()
{
int table[LIM];
int i, maxpos, minpos;
int max, min;
cout<<"Tha ginei eisagogi "<<LIM<<" arithmon \n\n\n";
for (i = 0; i < LIM; i++) {
cout<<"Dose ton "<<i+1<< " arithmo : ";
cin>>table[i];
}
cout<<" Ta stoixeia tou pinaka einai"<<endl;
for (i = 0; i < LIM; i++)
cout<<table[i]<<" ";
maxpos = 0;
max = table[0];
system("PAUSE");
return 0;
}
#include <cstdlib>
#include <iostream>
#include <iomanip.h>
using namespace std;
int main(int argc, char *argv[])
{
cout << showpoint << fixed << right<<setprecision(2);
float theo[15]={6,3,8,2,7,4,9,5,7,4,10,3,7,8,9};
float erga[15]={3,2,7,8,9,6,5,5,5,8,7,10,5,7,3};
float math[15];
cout<<" a/a Theoria Ergastirio Sxolio vathmos
"<<endl<<endl;
for (int i=0;i<15;i++)
{
cout<<setw(3)<<i+1<<" "<<setw(8)<<theo[i]<<" "<<setw(8)<<erga[i]<<"
";
if (theo[i]<5 && erga[i]<5)
cout<<" Apotixia "<<"------"<<endl;
else if (theo[i]<5 )
cout<<" Apot. theoria "<<"------"<<endl;
else if (erga[i]<5)
cout<<" Apot. ergastirio "<<"------"<<endl;
else {
math[i]=(theo[i]+erga[i])/2;
cout<<" Epitixos ";
cout<<math[i]<<endl; }
}
cout<<endl<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Άσκηση 5.1-5.4
Υπολογίστε με το χέρι τα αποτελέσματα στα παρακάτω προγράμματα και γράψτε τα
αποτελέσματα στο αντίστοιχα πλαίσια, όπου αυτά υπάρχουν. Κατόπιν συγκρίνεται τα
αποτελέσματα με αυτό που θα εμφανιστούν όταν το πρόγραμμα εκτελεστεί στον Η/Υ.
#include <cstdlib>
#include <iostream>
#include <iostream.h>
#include <stdlib.h>
int main()
{
{//Askisi 61
cout<<"Askisi 71"<<endl;
int k=77;
int* d;
cout<<sizeof(int)<<" "<<sizeof(char)<<" ";
cout<<sizeof(double)<<" "<<sizeof(float)<<endl;
d=&k;
cout<<"k= "<<k<<" *d= "<<*d<<endl;
cout<<"&k= "<<&k<<" d= "<<d<<endl; Askisi 51
system("PAUSE");
}
{//Askisi 62
cout<<endl<<endl;
cout<<"Askisi 72"<<endl;
int k=77, n=3;
int* d1,*d2;
d1=&k;d2=&n; cout<<k<<" "<<n<<" "<<*d1<<" "<<*d2<<endl;
*d2=*d1; cout<<k<<" "<<n<<" "<<*d1<<" "<<*d2<<endl;
k=77;n=3; d2=d1; cout<<k<<" "<<n<<" "<<*d1<<" "<<*d2<<endl;
system("PAUSE");
} Askisi 52
{//Askisi 63
cout<<endl<<endl;
cout<<"Askisi 73"<<endl;
int k=66,n=5;
int* d1,*d2;
d1=&k;
d2=&n;
*d2=*d1;
*d1=44;
cout<<k<<" "<<n<<" "<<*d1<<" "<<*d2<<endl;
system("PAUSE");
} Askisi 53
{//Askisi 64
cout<<endl<<endl;
cout<<"Askisi 74"<<endl;
int a[7];
int* d, k ;
cout<<"program 1"; cout<<endl;
for (k=0;k<7;k++)
{a[k]=2*k;cout<<a[k]<<" ";} Askisi 54
cout<<endl;
d=&a[4]; cout<<*d++<<" ";
cout<<*d<<" ";cout<<endl;
system("PAUSE");
}
}
cout<<endl<<endl;
system("PAUSE");
}
Άσκηση 6.1
Παρατηρήστε πως γίνεται εμφάνιση του πίνακα με 3 τρόπους.
Υπόδειξη: Η άσκηση αυτή δεν είναι απαραίτητο να πληκτρολογηθεί στον υπολογιστή
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{ //apodosi timon se pinaka kai emfanisi me 3 tropous
cout<<"Askisi 81"<<endl;
//1os tropos
float b[4];
for (int k=0;k<4;k++) {
b[k]=4 ;
cout<<"b["<<k<<"]="<<b[k]<<" ";}
cout<<endl;
system("PAUSE");
return 0;
}
int main()
{
int k,l;
cout<<"Dose 2 akereous"<<endl;
cin>>k>>l;
cout<<"o megalyros apo tous dio einai ="<<max2(k,l)<<endl;
system("PAUSE");
return 0;
}
int max2(int x,int y)
{
if (x>y)
return x;
else
return y;
}
Άσκηση 7.1
Το παρακάτω πρόγραμμα αθροίζει τα στοιχεία σε ένα πίνακα.
#include <cstdlib>
#include <iostream>
Άσκηση 8.3
Υπολογίστε με το χέρι τα αποτελέσματα στα παρακάτω προγράμματα και γράψτε τα
αποτελέσματα στο αντίστοιχα πλαίσια, όπου αυτά υπάρχουν. Κατόπιν συγκρίνεται τα
αποτελέσματα με αυτό που θα εμφανιστούν όταν το πρόγραμμα εκτελεστεί στον Η/Υ.
#include <cstdlib>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
cout<<"Askisi 10.3"<<endl;
int a[]={200,300,400},i;
}
//=============================================
void euro(int x, int & penta, int & eka,int & eiko, int & mono)
//definition of function
{
Pe
}//=============================================
int main( )
{
int arxiko,k,l,m,n;
arxiko=dose1();
Άσκηση 9.1
Να εκτελεστεί το παρακάτω πρόγραμμα
#include <iostream>
using namespace std;
int main()
{
struct ypallilos
{
char* eponimo;
int age;
double salary;
} yp1;
yp1.eponimo= "Papadopoulos";
yp1.age = 28;
yp1.salary = 1200;
cout << "Stoixeia ypallilou \n" << yp1.eponimo << " "
<< yp1.age << " " << yp1.salary << endl;
system("PAUSE"); return 0;
}
cout << "Stoixeia 1ou ypallilou \n" << yp1.eponimo << " "
<< yp1.age << " " << yp1.salary << endl;
cout << "Stoixeia 2ou ypallilou \n" << yp2.eponimo << " "
<< yp2.age << " " << yp2.salary << endl;
ypallilos yp3;
yp3.eponimo=yp1.eponimo;
yp3.age=yp1.age;
yp3.salary=yp1. salary;
cout << "Stoixeia 3ou ypallilou \n" << yp3.eponimo << " "
<< yp3.age << " " << yp3.salary << endl;
system("PAUSE"); return 0;
}
int main()
{
struct spoudastis
{
char spoud_Name[40];
float spoud_vathmos[2];
};
system("PAUSE"); return 0;
}
#include <iostream>
using namespace std;
int main()
{
struct ypallilos
{
char* eponimo;
int age;
double salary;
} ;
cout << "Stoixeia ypallilou \n" << epix[0].eponimo << " "
<< epix[0].age << " " << epix[0].salary << endl;
cout << "Stoixeia ypallilou \n" << epix[1].eponimo << " "
<< epix[1].age << " " << epix[1].salary << endl;
system("PAUSE"); return 0;
}
int main()
{
struct rectangle rect1;
rect1.panoAris.x=-2; rect1.panoAris.y=3;
rect1.katoDexia.x=8; rect1.katoDexia.y=-1;
system("PAUSE"); return 0;
}
#include <iostream>
using namespace std;
struct dstudent
{
char lastName[40];
int testScore;
int programmingScore;
double mesos;
};
//sinartisi pou epistrefei domi
dstudent ReadStoixeia ( )
{
dstudent fstud;
cout<<"Dose eponymo"; cin >> fstud.lastName;
cout<<"dose tous dio vathmous";
cin >> fstud.testScore >> fstud.programmingScore;
fstud.mesos = (fstud.testScore + fstud.programmingScore) / 2.0;
return fstud;
}
void printStoixeia(dstudent fstud)
{
cout << fstud.lastName << " " << fstud.testScore
<< " " << fstud.programmingScore << " " << fstud.mesos << endl;
}
int main()
{
dstudent stud1,stud2;
stud1= ReadStoixeia ( ); stud2= ReadStoixeia ( );
printStoixeia(stud1); printStoixeia(stud2);
system("PAUSE"); return 0;
}
Άσκηση 10.1
Να οριστεί μία κλάση που αφορά ορθογώνια και περιλαμβάνει συναρτήσεις μέλη TimesPlevron με
την οποία εισάγονται δύο τιμές που αφορούν τις δυο πλευρές ενός ορθογωνίου και την συνάρτηση
Emvado με την οποία υπολογίζεται το εμβαδό του ορθογωνίου
#include <cstdlib>
#include <iostream>
// classes example
using namespace std;
class KOrthogonio {
int x, y;
public:
void TimesPlevron(int,int);
int Emvado () ;
};
int main () {
KOrthogonio rect;
rect.TimesPlevron (10,20);
cout << "To emvado = " << rect .Emvado()<<endl ;
system("PAUSE");
return EXIT_SUCCESS;
}
#include <cstdlib>
#include <iostream>
class TV
{
int m_Kanali;
public:
void SetKanali(int Kanali) {
m_Kanali=Kanali;
};
int GetKanali(){
cout<<m_Kanali<<endl;
};
};
TV myTV;
myTV.SetKanali(10);
myTV.GetKanali();
system("PAUSE");
return EXIT_SUCCESS;
}
Οι συναρτήσεις να εφαρμοστούν σε ένα αντικείμενο που ορίζεται στο main και που ανήκει στην
κλάση.
#include <cstdlib>
#include <iostream>
class Spoudastis {
int m_kod;
float m_the,m_erga;
public:
void SetData(int kod, float theo, float erga){
m_kod = kod; m_the = theo;m_erga=erga;}
float Mesos(){
float m=(m_the+m_erga)/2;
return (m);}
int Kodikos(){
return (m_kod);}
void Vathmoi(){
cout<<" "<<m_the<<" "<<m_erga<<" "<<endl; }
};
system("PAUSE");
return EXIT_SUCCESS;
}
Άσκηση για τον σπουδαστή
Στην ανωτέρω άσκηση να οριστεί και συνάρτηση μέλος της κλάσης που να εμφανίζει το κατάλληλο
μήνυμα εάν ο σπουδαστής
πέρασε θεωρία
πέρασε εργαστήριο
πέρασε το μάθημα
κόπηκε και στα δύο
ανάλογα με τους βαθμούς που πήρε
#include <cstdlib>
#include <iostream>
system("PAUSE");
return EXIT_SUCCESS;
}
#include <cstdlib>
#include <iostream>
class KOrthogonio {
int x, y;
public:
KOrthogonio(int a, int b){ x = a; y = b;}
int Emvado (){return (x*y);}
};
#include <cstdlib>
#include <iostream>
using namespace std;
cout << endl << "Ogos tou dom1 = " << dom1.Ogos();
cout << endl << "Ogos tou dom2 = " << dom2.Ogos();
cout <<"\nTo antikeimeno dom2 katalamvanei " << sizeof(dom2) << "
bytes.";
cout << endl;
system("PAUSE");
return EXIT_SUCCESS;
}