#include<stdio.h>
#include<math.h>
#include<stdlib.h>
double sum(double x, double y);
int main (void)
{
double x,y,temp;
printf("\n Dose thn timh tou x");
scanf("%lf" ,&x);
printf("Dose thn timh tou y");
scanf("%lf", &y);
temp=sum(x,y);
printf("\n To athroisama ton x kai y ypologismena apo synarthsh tou programmatos einai to sum=%lf", temp);
system("pause");
}
double sum(double x, double y)
{
double a;
a=x+y;
return a;
}
ΑΣ ΔΟΥΜΕ ΤΩΡΑ ΕΝΑ ΕΝΔΙΑΦΕΡΟΝ ΠΡΟΓΡΑΜΜΑ ΜΕ ΣΥΝΑΡΤΗΣΕΙΣ ΚΑΙ ΤΗΝ ΕΝΤΟΛΗ switch-case
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
double athroisma(double a,double b);
double ginomeno (double a,double b);
double piliko (double a,double b);
double mo (double a,double b);
int main (void)
{
double x,y;
int k,i,l;
printf("\n Give i");
scanf("%d", &l);
for (i=1;i<=l;i++)
{
printf("\n Give first number");
scanf("%lf", &x);
printf("\n Give second number");
scanf("%lf", &y);
printf("\n Give the number");
scanf("%d", &k);
switch (k)
{
case 1:
printf("\n To athroisma einai sum=%lf", athroisma(x,y));
break;
case 2:
printf("\n To ginomeno einai p=%lf", ginomeno(x,y));
break;
case 3:
if (y==0)
printf("\n Adinath diairesh");
else
printf("\n To ginomeno einai piliko=%lf", piliko(x,y));
break;
default:
printf("\n O mesos oros einai mo=%lf", mo(x,y));
break;
}
}
system("pause");
}
double athroisma(double a,double b)
{
double sum;
sum=a+b;
return sum;
}
double ginomeno (double a,double b)
{
double p;
p=a*b;
return p;
}
double piliko (double a,double b)
{
double piliko;
piliko=a/b;
return piliko;
}
double mo (double a,double b)
{
double mo;
mo=(a+b)/2;
return mo;
}
ΑΣ ΔΟΥΜΕ ΤΩΡΑ ΤΟΝ ΟΔΗΓΟ ΤΩΝ ΕΡΓΑΣΤΗΡΙΩΝ ΥΠΟΛΟΓΙΣΤΩΝ ΟΠΩΣ ΠΑΡΟΥΣΙΑΣΤΗΚΕ ΑΠΟ ΤΟ ΕΘΝΙΚΟ ΚΑΙ ΚΑΠΟΔΙΣΤΡΙΑΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΤΟΥ ΤΜΗΜΑΤΟΣ ΦΥΣΙΚΗΣ.
Εργαστήριο Υπολογιστών
Ασκήσεις
Διδάσκοντες:
Ε. Ανασοντζής (Επίκ. Καθηγητής)
Α. Μουστάκας (Επίκ. Καθηγητής)
Ε. Νισταζάκης (Επίκ. Καθηγητής)
Ε. Τσίλης (Επίκ. Καθηγητής)
Πανεπιστήμιο Αθηνών
Τμήμα Φυσικής
Αθήνα 2011
Εργαστήρια Υπολογιστών στην C
Τμήμα Φυσικής
1. Άσκηση (Εισαγωγή)
1.1 Γνωριμία με τον υπολογιστή.
Μπροστά σας έχετε υπολογιστές με τους
οποίους θα μάθετε να επικοινωνείτε και να
προγραμματίζετε. Οι υπολογιστές έχουν είσοδο είτε από κάποια
δισκέτα είτε από το πληκτρολόγιο
ενώ έξοδος είναι η οθόνη. Το λειτουργικό σύστημα
είναι το Linux-Ubuntu, βασικά αρχεία του οποίου
φορτώνονται στη μνήμη του υπολογιστή κατά τη
διάρκεια της εκκίνησής του. Το λειτουργικό σύστημα
εφοδιάζει τον χρήστη με ένα σύνολο βασικών εντολών
με τη βοήθεια των οποίων ο χρήστης
επικοινωνεί με τον υπολογιστή.
1.2 Βασικές πληροφορίες για το Linux
1.2.1 Εκκίνηση του υπολογιστή
Αρχικά ανοίγετε τον υπολογιστή και περιμένετε
να φορτώσει το Operating System στη μνήμη του
(δηλαδή να «ξεκινήσει»). Ανάλογα με το τερματικό
που χρησιμοποιείτε, μπορεί να σας ζητηθεί να
εισάγετε ως username τη λέξη
student, ή να κάνετε κλικ μεταξύ άλλων επιλογών. Κατόπιν, θα σας
ζητηθεί να εισάγετε ως password τη λέξη
physics.
1.2.2 Εντολές του Linux
Όταν ολοκληρωθεί η εκκίνηση του υπολογιστή,
η οθόνη μοιάζει με την αντίστοιχη οθόνη που πιθανώς
να έχετε συνηθίσει στα Microsoft Windows, δηλαδή
ένα παράθυρο με μικρά εικονίδια (shortcuts). Ο
λόγος είναι ότι το σύστημα Linux έχει σχεδιαστεί
έτσι ώστε να είναι βολικό και αύκολο για χρήστες
Windows, αλλά ταυτόχρονα είναι πολύ πιο γρήγορο
και «ανθεκτικό».
Για να συνεχίσουμε, πρέπει πρώτα να ανοίξουμε
μία κονσόλα, από την οποία θα μπορέσουμε να
πληκτρολογήσουμε τις απαραίτητες εντολές. Έτσι
κάνουμε κλικ στο εικονίδιο με το όνομα Terminal
στην οθόνη του υπολογιστή. Όταν ανοίξει το παράθυρο
της κονσόλας εμφανίζεται το σήμα :\>, το
οποίο ονομάζεται prompt, και μας πληροφορεί
ότι το λειτουργικό σύστημα είναι έτοιμο να δεχθεί
εντολή από τον χρήστη. Ο χρήστης εισάγει κάθε
φορά μια εντολή από το πληκτρολόγιο
ακολουθούμενη από το πλήκτρο Enter.
1. Πληκτρολογούμε την εντολή
cd Documents
που μας πηγαίνει στο directory Documents.
(cd σημαίνει «change directory»).
2. Πληκτρολογούμε την εντολή
mkdir 201100xxx
όπου xxx είναι οι αριθμοί του ΑΜ μας. Αυτή η
εντολή δημιουργεί ένα directory με όνομα 200700xxx,
το οποίο είναι το προσωπικό μας directory μέσα
στο οποίο θα δημιουργήσουμε τα προγράμματα που
θα γράψουμε.
3. Πληκτρολογούμε την εντολή
cd 201100xxx
που μας πηγαίνει στο παραπάνω directory.
4. Κατόπιν, ανάλογα με το τερματικό το οποίο
χρησιμοποιούμε, πληκτρολογούμε την εντολή
kwrite &
που ανοίγει τον editor kwrite ή την εντολή
gedit &
που ανοίγει τον editor gedit. Αντίστοιχα, μπορούμε
να ανοίξουμε τον editor, κάνοντας κλικ στο
αντίστοιχο εικονίδιο στην οθόνη του υπολογιστή.
Το σύμβολο & το γράφουμε για να μας επιτρέψει
να γράψουμε άλλες εντολές αφού ανοίξει ο editor.
(Αν δεν το είχαμε γράψει, δε θα μπορούσαμε να
εισάγουμε άλλες εντολές σε αυτήν την κονσόλα, όσο
το πρόγραμμα kwrite/gedit είναι ανοικτό.) Βλέπουμε
τώρα ένα νέο παράθυρο να ανοίγει, αυτό του
editor. Σε αυτό το παράθυρο θα γράψουμε το πρόγραμμα
μας. Είναι καλό να ονομάσουμε άμεσα το
πρόγραμμα με την εντολή πηγαίνοντας με το ποντίκι
στο κουμπί File και πατώντας Save As και
κατόπιν εισάγοντας το όνομα του προγράμματος,
συμπληρώνοντάς το με το .c π.χ. onoma.c. Στη
συνέχεια, και όσο γράφουμε το πρόγραμμα, όταν
θέλουμε να το σώσουμε, πατούμε το κουμπί που
μοιάζει με δισκέττα. Όταν σώσουμε το πρόγραμμα
θα παρατηρήσουμε ότι στον editor οι διαφορετικού
τύπου λέξεις έχουν άλλο χρώμα. Π.χ. τα σχόλια
είναι σε italics, το κείμενο μέσα στην εντολή printf
είναι κόκκινα, ενώ οι μεταβλητές είναι μαύρες.
Αυτό συμβαίνει επειδή ο editor έχει αναγνωρίσει το
είδος του προγράμματος που γράφουμε και επιχειρεί
να μας βοηθήσει να το διαβάζουμε πιο εύκολα.
5. Αφού γράψουμε το πρόγραμμα και αφού το σώσουμε,
είμαστε έτοιμοι να το μεταγλωττίσουμε
χρησιμοποιώντας τον Compiler. Πληκτρολογούμε
στην κονσόλα με την εντολή:
gcc –o onoma onoma.c
όπου το gcc είναι το όνομα του compiler για
την C και onoma το όνομα του προγράμματός μας. To
κομμάτι της εντολής: “-o onoma”, κάνει τον
compiler να ονομάσει το πρόγραμμα που θα «τρέξουμε»
ως “onoma”. Κατόπιν βλέπουμε στο τερματικό τα
σχόλια του compiler, συγκεκριμένα τα λάθη τα
οποία έχει βρει. Πάμε πίσω στον editor και τα
διορθώνουμε, σώζουμε το αρχείο (με την εντολή Save,
όπως παραπάνω) και μετά ξανατρέχουμε τον
compiler.
6. Όταν ο compiler δε μας δώσει άλλα λάθη, είμαστε
έτοιμοι να «τρέξουμε» το πρόγραμμά μας
πληκτρολογώντας την εντολή:
./onoma
Τώρα αρχίζουμε να εισάγουμε ό,τι τιμές μας ζητάει
το πρόγραμμα κλπ.
7. Όταν τελειώσουμε με το πρόγραμμα μας, κλείνουμε
το παράθυρο του kwrite και της κονσόλας.
Χρήσιμες Εντολές στην Κονσόλα
Α. Όταν είμαστε στο prompt της κονσόλας, τα
βελάκια↑ και ↓ μας επιτρέπουν να ξαναφέρουμε
προηγούμενες και επόμενες εντολές που έχουμε
πληκτρολογήσει.
Β. Το κουμπί Tab μας επιτρέπει να γραφουμε
την αρχη μιας εντολής ή ονόματος αρχείου και κατόπιν,
πατώντας Tab, να συμπληρώνεται μόνο του. Π.χ.
άν στην εντολή 1 παραπάνω γράψουμε cd Docum και
μετά πατήσουμε Tab η λέξη Documents θα συμπληρωθεί
μόνη της.
Γ. Η εντολή cp (copy) αντιγράφει ένα
ήδη υπάρχον αρχείο σε ένα άλλο με το όνομα που θα
υποδείξουμε εμείς. Π.χ.
cp onoma.c onoma2.c
Δ. Η εντολή ls (list) μας δίνει στην
κονσόλα όλα τα προγράμματα μέσα στο directory που
βρισκόμαστε.
1.3 Υπολογισμός αθροίσματος
Παρακάτω δίνεται το πρώτο σας πρόγραμμα, το
οποίο τυπώνει μηνύματα στην οθόνη και εκτελεί μία
πρόσθεση με προσθετέους που εσείς εισάγετε.
Επίσης τυπώνει και το αποτέλεσμα της πρόσθεσης.
#include <stdio.h> //{Ενσωμάτωση Βασικών Αρχείων}
int main(void) //{Βασικό μέρος προγράμματος}
{
//
Define variables
double
a,b,c; //{Δήλωση μεταβλητών}
printf(“\n Hello!”);
//{Τύπωση μηνύματος στην οθόνη}
printf(“\n
Give me a = “);
scanf(“%lf”,
&a);
printf(“\n
Give me b = “); //{Δέχεται προσθετέους}
scanf(“%lf”,
&b);
c = a+b;
printf(“\n
The sum is c = %lf”,c);
printf(“\n
The sum with 7 total digits and 3 decimal digits is c = %7.3lf”, c);
printf(“\n
The sum written scientifically is c = %e\n”, c); {Εμφάνιση του αποτελέσματος}
return 0;
} //{Τέλος προγράμματος}
1.4 Άσκηση: Υπολογισμός μέσης τιμής
Με βάση τις γνώσεις που προσκομίσατε από την
παραπάνω άσκηση, μπορείτε τώρα να γράψετε ένα
πρόγραμμα από την αρχή, το οποίο υπολογίζει
τη μέση τιμή τεσσάρων αριθμών. Η ιδέα είναι η ίδια με
την παραπάνω, μόνο που, αντί να εισάγετε δύο
αριθμούς, a, b, πρέπει τώρα να εισάγετε τέσσερεις
αριθμούς, a, b, c, d και να διαιρέσετε το άθροισμα
με το τέσσερα. Προσοχή, οι αριθμοί πρέπει να είναι
πραγματικοί (και όχι ακέραιοι), και έτσι για
να μην μπερδέψετε τον compiler, πρέπει να διαρέσετε με
το 4.0, αντί απλά το 4! Έπίσης, αρκεί να τυπώνεται
ο τελικός αριθμός (η μέση τιμή δηλαδή) με έναν
από τους τρεις τρόπους που χρησιμοποιήθηκαν
στο παραπάνω πρόγραμμα.
Όταν τελειώσετε το πρόγραμμα, πρέπει να το σώσετε,
κατόπιν να το κάνετε compile, και κατόπιν να
βεβαιωθείτε ότι «τρέχει» ακολουθώντας τις παραπάνω
οδηγίες. Στη συνέχεια πρέπει οπωσδήποτε να το
δείξετε σε κάποιον από τους επιβλέποντες ο οποίος
θα επιβεβαιώσει τη σωστή λειτουργία του.
2. Άσκηση (Tριώνυμο)
2.1 Επίλυση Τριωνύμου.
Όπως είναι γνωστό ένα τριώνυμο δευτέρου βαθμού
ρ(x) ορίζεται μονοσήμαντα από τους συντελεστές
του α,β,γ. Δοθέντων των συντελεστών μπορούμε
να αποφανθούμε κατά πόσο το τριώνυμο έχει μία,
δύο πραγματικές ή δύο μιγαδικές ρίζες. Το πρόγραμμα
κάνει αυτή ακριβώς τη δουλειά: ζητάει τους
συντελεστές και βγάζει αποτελέσματα. Ιδιαίτερη
προσοχή χρειάζεται όταν εισάγεται τιμή για τον α :
δεν πρέπει να δοθεί τιμή μηδέν σε αυτό το συντελεστή.
2.3 Εφαρμογή
Παρακάτω δίνεται το πρόγραμμα, το οποίο δίνει
τις ρίζες τριωνύμου που εσείς εισάγετε, δίνοντας τους
συντελεστές του.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
//
Define variables
double
a, b, c, d, x1;
printf(“\nGive
value a (non-zero)”);
scanf(“%lf”,
&a);
printf(“\nGive
value b”);
scanf(“%lf”,
b);
printf(“\n
Give value of c”);
scanf(“%lf”, c); //{εισαγωγή στοιχείων}
d=b*b-4*a*c;
//{υπολογισμός διακρίνουσας}
if
(d==0.0)
{
x1 =
-0.5*b/a;
printf(“\nThe
double root is x= %f”, x1);
}
else
{
if
(d<0)
printf(“\nNo
real roots”);
else
{
x1=0.5(-b+sqrt(d))/a;
x2=0.5*(-b-sqrt(d))/a;
print(“\nThe
two roots are x1= %f and x2=%f”, x1, x2);
}
}
return 0;
}
Το πρόγραμμα ζητάει τους a, b, c και υπολογίζει
τη διακρίνουσα. Έπειτα χρησιμοποιεί τη δομή : If-else
αναλόγως τυπώνει στην οθόνη τα αποτελέσματα.
Η δομή If-else έχει την εξής σύνταξη
:
If (condition)
command
list
else command
list
Σε μια command list μπορεί να εμπεριέχεται
μια δομή If -else. Τότε έχουμε φωλιασμένο (nested) if,
όπως και στο πρόγραμμα μας.
ΣΗΜΑΝΤΙΚΟ:
Όταν κάνουμε compile το παραπάνω πρόγραμμα,
καθώς και κάθε πρόγραμμα στο οποίο
συμπεριλαμβάνουμε το “#include
<math.h>”, χρησιμοποιούμε την εντολή:
2.4. Άσκηση: Υπολογισμός των μιγαδικών ριζών
Στο παραπάνω πρόγραμμα υπολογισμού των ριζών
του τριωνύμου, προσθέσετε τις κατάλληλες
γραμμές κώδικα ώστε να εμφανίζει στην οθόνη
τις μιγαδικές ρίζες της εξίσωσης όταν η διακρίνουσα
είναι μικρότερη του μηδενός. Για τον υπολογισμό
αυτό, δε χρειάζεται να χρησιμοποιήσετε μιγαδικούς
αριθμούς στη C αλλά μόνο να χειριστείτε έξυπνα
την εντολή printf και τις σχέσεις που φαίνονται στη
σημείωση που ακολουθεί.
3. Άσκηση (Αριθμητική Ολοκλήρωση)
3.1 Εισαγωγή
Σε αυτήν την άσκηση θα ασχοληθούμε με μία πολύ
χρήσιμη εφαρμογή των υπολογιστών στη Φυσική,
την αριθμητική ολοκλήρωση συναρτήσεων. Υπάρχουν
πάμπολλες μέθοδοι με ευρύ φάσμα σε
πολυπλοκότητα. Εμείς εδώ θα αναπτύξουμε την
μέθοδο ολοκλήρωσης με τον κανόνα του τραπεζίου.
Σύμφωνα με αυτήν την μέθοδο, όταν τα σημεία
x1, x2 είναι πολύ κοντά
μεταξύ τους (δηλαδή το x2-
x1=h→0), τότε το ολοκλήρωμα
3.2 Εφαρμογή
Στην παρακάτω εφαρμογή θα υπολογίσουμε το ολοκλήρωμα
της συνάρτησης cos(x) από a έως b και θα
το συγκρίνουμε με το σωστό αποτέλεσμα
b και του αριθμού των βημάτων Ν.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
int main(void)
{
double
a, b, n, h, sum;
int i;
printf("To
programma ayto tha oloklirosei to cos(x) apo to a os to b se N
vimata.\n");
printf("Dose
tin arxiki timi olokliromatos, a\n");
scanf("%lf",
&a);
printf("Dose
tin teliki timi olokliromatos, b\n");
scanf("%lf",
b);
printf("Dose
ton synoliko arithmo vimaton N\n");
scanf("%lf",
n);
h =
(b-a)/n;
sum =
0.0;
for
(i=0; i<n+1, ++i)
sum +=
cos(a+h*i)*h;
sum -=
0.5*h*(cosa+cos(b));
printf("arithmitiko
apotelesma = %lf \n", sum);
exact_res
= sin(b)-sin(a);
printf("akrives
apotelesma = %lf \n", exact_res);
diff =
fabs(sum - exact_res);
printf("diafora
= %e \n", &diff );
return 0;
}
3.3 Άσκηση: Υπολογισμός με τον κανόνα του παραλληλογράμμου
Ένας άλλος τρόπος αριθμητικού υπολογισμού του
ολοκληρώματος είναι η μέθοδος του
παραλληλογράμμου. Η μεθοδολογία αυτή είναι λιγότερο
ακριβής από αυτή του τραπεζίου που
αναλύθηκε παραπάνω, αλλά απαιτεί μικρότερο αριθμό
πράξεων και πολλές είναι πιο χρήσιμη.
Σύμφωνα με τη μέθοδο αυτή, όπως φαίνεται στο
παραπάνω σχήμα, χωρίζουμε το διάστημα που
θέλουμε να ολοκληρώσουμε σε μικρά κομμάτια που
απέχουν μεταξύ τους h. Θεωρούμε ότι, όταν τα
σημεία π.χ. x1, x2, είναι πολύ κοντά μεταξύ τους, τότε το μπορεί
να προσομοιωθεί με ένα
παραλληλόγραμμο με τη μία πλευρά του να είναι
μήκους x1 και την άλλη h. Οπότε το στοιχειώδες
εμβαδό από την πρώτη διαμέριση θα είναι
hf(x1), ενώ από κάθε επόμενη θα είναι hf(xi),
με i=1…N.
Αρα, το συνολικό εμβαδό-ολοκλήρωμα θα δίνεται
από τη σχέση:
f ( x)dx ≈ h( f1 + f 2
+ f 3 + ...
+ f N )
= h( f1
+ f 2 + f 3
+ ... + f N
+1 )
− hf N +1
Με βάση την παραπάνω ανάλυση της μεθόδου και
την εξίσωση που προέκυψε να αλλάξετε το
παραπάνω πρόγραμμα, ώστε να υπολογίζει το ολοκλήρωμα
με τη μέθοδο του παραλληλογράμμου και
όχι με αυτή του τραπεζίου.
Η συνάρτηση f(x) θα σας δοθεί στο εργαστήριο
από τους διδάσκοντες.
4. Άσκηση (Αριθμητική Ολοκλήρωση Συνήθους
Διαφορικής
Εξίσωσης)
4.1 Εισαγωγή
Αυτή η άσκηση γενικεύει τη μέθοδο της προηγουμένης
στην περίπτωση που η συνάρτηση προς
ολοκλήρωση είναι η παράγωγος μιας διαφορικής
εξίσωσης, η οποία εξαρτάται από την συνάρτηση y(x)
και τη μεταβλητή x, δηλαδή
y '( x) = f ( y( x), x)
Ολοκληρώνοντάς την έχουμε
b
a
Ένα πολύ απλό παράδειγμα είναι η
για την οποία η λύση είναι γνωστή
y= y(a)e−( x−a ) + e− x ( x − a)
Ο τρόπος τον οποίον θα χρησιμοποιήσουμε για
να τη λύσουμε αριθμητικά λέγεται μέθοδος του Euler
και είναι ο απλούστερος από μια σειρά πολλών
μεθόδων που χρησιμοποιούνται σε αριθμητικά πακέτα.
Η βασική ιδέα είναι ότι η παράγωγος στην αριστερή
πλευρά της πρώτης εξίσωσης αυτής της
παραγράφου, μπορεί να προσεγγιστεί με τον ορισμό
της για h→0, ως εξής:
yn+1 =xn+1 ) ≈ y( xn ) + f ( y( xn ),
xn )h = +
f ( yn ,
xn )h
Έτσι σε κάθε βήμα υπολογίζουμε την τιμή του
y(x) στο επόμενο σημείο προσθέτοντας στο y(x) του
προηγούμενου την τιμή της παραγώγου f(y,x) υπολογισμένη
στο προγούμενο σημείο. Όπως και στην
προηγούμενη άσκηση χρειάζόμαστε την αρχική τιμή
της y(a), τις τιμές των αρχικών και τελικών
σημείων a, b, και τον αριθμό βημάτων, Ν. Τότε
το βήμα h δίνεται από
4.2 Εφαρμογή
Στην παρακάτω εφαρμογή θα υπολογίσουμε αριθμητικά
τη λύση της παραπάνω διαφορικής εξίσωσης
και θα το συγκρίνουμε με το σωστό αποτέλεσμα
για διάφορες τιμές των a, b και του αριθμού των
βημάτων Ν.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
double
a, b, n, h, x_n, y_n, f_n, y0;
double
exact_res, diff;
int i;
printf("To
programma ayto tha lisei th diaforiki exisosi y'=- y+exp(-x) apo to a os to b
se N
vimata.\n");
printf("Dose
tin arxiki timi a\n");
scanf("%lf",
a);
printf("Dose
tin teliki timi b\n");
scanf("lf",
&b);
printf("Dose
tin arxiki timi tis synartisis y(a)\n");
scanf("%lf",
y0);
printf("Dose
ton synoliko arithmo vimaton N\n");
scanf("%lf",
&n);
h =
(b-a)/n;
y_n =
y0;
x_n = a;
for
(i=0; i<n+1; ++i)
{
f_n =
-y_n+exp(-x_n);
x_n +=
-h;
y_n +=
f_n*h;
}
printf("arithmitiko
apotelesma = %lf \n", y_n);
exact_res
= y0*exp(-b+a)+exp(-b)*(b-a);
printf("akrives
apotelesma = %lf \n", exact_res);
diff =
fabs(y_n - exact_res);
printf("diafora
= %e \n", diff );
return 0;
}
4.3 Άσκηση: Επίλυση διαφορικής και επιβεβαίωση
λύσης
Με βάση την παραπάνω μεθοδολογία και το πρόγραμμα
που υλοποιήθηκε στην παράγραφο 4.2, να
δημιουργείστε το αντίστοιχο πρόγραμμα για την
επίλυση της διαφορικής εξίσωσης:
y '( x) = f ( y( x), x)
Η συνάρτηση f(y, x) και η αντίστοιχη ακριβής
λύση θα σας δοθεί στο εργαστήριο από
τους διδάσκοντες.
5. Άσκηση (Αποθήκευση και ανάκτηση δεδομένων
από το δίσκο)
5.1 Ποια είναι η λογική της αποθήκευσης
Πολύ συχνά τα δεδομένα τα οποία προκύπτουν από
ένα πρόγραμμα πρέπει να επεξεργαστούν με
κάποια άλλη εφαρμογή ή τα αποτελέσματα αυτά
πρέπει να αποθηκευτούν ώστε να μπορούν, σε κάποια
άλλη στιγμή, να ανακτηθούν από το χρήστη για
να τα χρησιμοποιήσει.
Επομένως, είναι σημαντικό να έχουμε τη δυνατότητα
να αποθηκεύουμε δεδομένα στο δίσκο του
υπολογιστή μας. Στην ακόλουθη εφαρμογή, υπολογίζουμε
τις τιμές μιας συνάρτησης και τα
αποτελέσματα τα αποθηκεύουμε στον δίσκο.
5.2 Εφαρμογή
Το ακόλουθο πρόγραμμα υπολογίζει την τιμές της
συνάρτησης f(x)=3x4+2x2-5x+1, για τιμές
του x από
-100 έως 100 με βήμα 0.01. Τα αποτελέσματα αποθηκεύονται
σε ένα αρχείο της μορφής .dat και
μπορούν να χρησιμοποιηθούν για επεξεργασία από
οποιοδήποτε πρόγραμμα υποστηρίζει αυτού του
τύπου τα αρχεία.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
include <stdio.h>
include <stdlib.h>
int main()
{
FILE* fp;
double x, fx;
fp=fopen(“test1.dat”, “w”);
/*anoigei to arxeio gia egrafh */
for(x=-10; x<10;
x=x-0.1)
{
fx = 3*pow(x,4)+2*pow(x,3)-5*x+1;
fprintf(fp, “%d,%f\n”,
x, fx);
}
fclose(fp);
return 0;
}
5.3 Άσκηση
Να κάνετε τις απαραίτητες τροποποιήσεις στο
παραπάνω πρόγραμμα ώστε να ανοίγει ένα αρχείο και
για αποθήκευση αλλά και για ανάγνωση στοιχείων,
που θα το ονομάζετε test2.dat και στη συνέχεια να
αλλάξετε τη συνάρτηση που υπολογίζει και να
βάλετε την f(x)=(5x7+1)/(x2+1) για τιμές του
x από -10
έως το 50 με βήμα 0.005.
5.4 Ανάγνωση αρχείου
Όπως αναφέρθηκε και στην εισαγωγή της παρούσας
άσκησης, τα αρχεία στα οποία έχουμε
αποθηκεύσει τα διάφορα δεδομένα, μπορούν να
διαβαστούν και τα δεδομένα αυτά να
χρησιμοποιηθούν. Με βάση αυτή τη δυνατότητα,
να κατασκευάσετε ένα πρόγραμμα, το οποίο όταν θα
τρέχει, θα διαβάζει τα στοιχεία του αρχείου
test1.dat και στη συνέχεια θα εκτυπώνει στην οθόνη τη
μέση τιμή και τη διασπορά των τιμών του
fx. Σημειωτέον ότι η μέση τιμή μ και η διασπορά σ2
ορίζονται ως εξής
include <stdio.h>
include <stdlib.h>
int main()
{
FILE* fp;
double timi_f,
athroisma_x, athroisma_x2, mesos, diaspora;
int timi_x, plithos;
fp=fopen("test1.dat",
"r");
fscanf(fp,
"%d,%lf", &timi_x, &timi_f);
while(!feof(fp)){
printf("\n%d\t%lf\t",
timi_x, timi_f);
fscanf(fp,
"%d,%lf", &timi_x, &timi_f);
plithos +=1;
athroisma_x += timi_f;
athroisma_x2 +=
timi_f*timi_f;
}
mesos =
athroisma_x/plithos;
diaspora = athroisma_x2;
printf("\nN = \t %d\n",
plithos);
printf("Mesos = \t
%lf\n", mesos);
printf("Diaspora =
\t%lf \n", diaspora);
fclose(fp);
return 0;
}
6. Άσκηση (Πράξεις με Πίνακες)
6.1 Πολλαπλασιασμός Πινάκων.
Όπως είναι γνωστό δύο πίνακες ΝxΡ , ΡxΚ πολλαπλασιαζόμενοι
με αυτή τη σειρά δίνουν ένα πίνακα
ΝxΚ. Σε αυτή την άσκηση εισάγονται δύο πίνακες
και το πρόγραμμα δίνει το αποτέλεσμα τους.
Μπορείτε όμως να αλλάξετε τους Ν, Ρ, Κ, οι οποίοι
δίνονται ως σταθερές στην αρχή του
προγράμματος και να εκτελέσετε έτσι όποιο πολλαπλασιασμό
θέλετε.
6.2 Λογικά διαγράμματα
Στα πλαίσια του δομημένου προγραμματισμού χρησιμοποιούνται
λογικά διαγράμματα που παριστούν
βασικές λογικές δομές, όπως άλλωστε έχει αναφερθεί
στις ασκήσεις που έχουν προηγηθεί. Στο
πρόγραμμα χρησιμοποιούνται η σειριακή δομή
(που έχουμε γνωρίσει στη 2η άσκηση) και η δομή
επανάληψης, for (i=0; i<n; ++i) (που έχουμε γνωρίσει στην 3η άσκηση).
6.3 Εφαρμογή
Παρακάτω δίνεται το πρόγραμμα, το οποίο εκτελεί
πολλαπλασιασμό πινάκων.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
int n,
m, p;
int i,
j;
printf(“\n
In this program we will multiply a MxN matrix A with an NxP matrix B”);
printf(“\n
Give number of rows of matrix A, M= ”);
printf(“\n
Give number of columns of matrix A, N= ”);
scanf(“%d”,
n);
printf(“\n
Give number of columns of matrix B, P= ”);
scanf(“%d”,&p);
// Here we
define the matrices A, B
double
a[m][n];
double
bb[n][p];
double
c[m][p];
printf(“\nGive
elements of B\n”);
for
(i=0; i<n; ++i)
{
{
printf(“\nB[%d][%d]
= ”, i+1 ,j+1);
scanf(“%lf”,&b[i][j]);
}
}
for
(i=0; i<m; ++i)
{
for
(j=0; j<p;++j)
{
temp =
0.0;
for
(k=0; k<n; ++k)
temp +=
a[i][k]*b[k][j];
c[i][j]
= temp;
printf(“\n
C[%d][%d] = %f”, i+1, j+1, c[i][j]);
}
return 0;
}
Παρατηρήστε ότι για τον υπολογισμό του πίνακα
C=AxB χρησιμοποιούνται 3 δομές for, η μία μέσα
6.4 Άσκηση: Υπολογισμός αθροίσματος πινάκων
Είναι γνωστό ότι η πρόσθεση και η αφαίρεση πινάκων
μπορεί να πραγματοποιηθεί μόνο μεταξύ
πινάκων που έχουν την ίδια διάσταση. Αν θεωρήσουμε
δύο πίνακες Α και Β με ίδιες διαστάσεις, έστω
Ν×M, τότε η πρόσθεση ή η αφαίρεση τους θα δίνει
έναν πίνακα C, επίσης Ν× M, τα στοιχεία του
οποίου θα υπολογίζονται ως εξής:
cij = aij
± bij όπου i=1..N και
j=1…M
Με βάση τον ορισμό αυτό, να αλλάξετε το παραπάνω
πρόγραμμα ώστε να υπολογίζει το άθροισμα
C=Α+Β και να τυπώνει τα περιεχόμενα του πίνακα
C στο αρχείο test3.dat, με κάθε στήλη του
πίνακα να απέχει από την άλλη κατά ένα tab.
7. Άσκηση (Υπολογισμός Αθροίσματος - Γινομένου)
7.1 Η έννοια του μεγάλου αριθμού προσθετέων
Συχνά σε αριθμητικούς υπολογισμούς υπάρχει η
ανάγκη υπολογισμού ενός αθροίσματος, γινομένου,
κλπ με άπειρους όρους. Δεδομένου ότι στην πράξη
η πρόσθεση άπειρων αριθμών δεν είναι εφικτή,
πρέπει να γράψουμε ένα πρόγραμμα στο οποίο θα
έχουμε ορίσει μία παράμετρο η οποία να «ελέγχει»
το πόσο κοντά βρισκόμαστε σε αυτό που σε κάθε
εφαρμογή μπορούμε να θεωρήσουμε ως «άπειρο».
Ας μελετήσουμε λοιπόν το ακόλουθο πρόβλημα που
υπολογίζει το άθροισμα των όρων μίας σειράς της
μορφής:
1 1 1 1 1
Επειδή το άθροισμα αυτό αποτελείται από άπειρους
όρους, πρέπει να βάλουμε μία συνθήκη σύμφωνα
με την οποία, ο υπολογιστής θα σταματήσει να
αθροίζει. Η συνθήκη αυτή θα μπορούσε να είναι π.χ.
ότι ο Η/Υ θα σταματήσει τη διαδικασία του αθροίσματος
όταν φτάσει στον όρο εκείνο που θα είναι
μικρότερος από κάποιο συγκεκριμένη τιμή, έστω
ε = 5×10-4. Για να το πετύχουμε αυτό,
χρησιμοποιούμε είτε την εντολή while είτε την
do...while Η εντολή αυτή επαναλαμβάνει μία
διαδικασία τόσες φορές όσες χρειάζεται μέχρι
κάποια, ορισμένη, παράμετρος να πάρει μία
συγκεκριμένη τιμή.
7.2 Εφαρμογή
Παρακάτω δίνεται το πρόγραμμα, το οποίο υπολογίζει,
μέσω της εντολής while, το παραπάνω
άθροισμα.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
include <stdio.h>
int main()
{
double athroisma,
prostheteos, epsilon;
int i;
athroisma = 0.0;
prostheteos = 1.0;
epsilon = 5e-04;
i = 1;
while (prostheteos >=
epsilon)
{
prostheteos = 1/i;
athroisma = athroisma +
prostheteos;
i=i+1;
}
printf(“\n To plhthos
ton orwn einai = %d\n”, i-1);
printf(“\n To athroisma
einai = %.5f\n”, athroisma);
return 0;
}
7.3 Χρήση των εντολών do…while
Να αλλάξετε το παραπάνω πρόγραμμα, ώστε να δημιουργήσετε
ένα καινούριο, με τέτοιο τρόπο ώστε
να μην χρησιμοποιεί την εντολή while για τη
λειτουργία του αλλά τη σύνθετη εντολή do…while.
Θυμίζουμε ότι, όπως είναι γνωστό και από το
μάθημα, για να λειτουργήσει η εντολή while πρέπει να
έχει κάτι να συγκρίνει πριν την πρώτη επανάληψη
της διαδικασίας. Αντίθετα, η σύνθετη εντολή
do…while, πρώτα κάνει την πρώτη επανάληψη και
μετά ζητάει να συγκρίνει για να αποφασίσει αν θα
συνεχίσει ή όχι τις επαναλήψεις.
7.4 Άσκηση: Πολλαπλασιασμός με μεγάλο αριθμό
όρων
Να γράψετε ένα πρόγραμμα το οποίο δεν θα υπολογίζει
το άθροισμα άπειρων όρων όπως παραπάνω,
αλλά το ακόλουθο γινόμενο πολλών όρων:
Το πρόγραμμα θα πρέπει να σταματάει τον υπολογισμό
όταν κάποιος από τους όρους του γινομένου
γίνει ίσος η μικρότερος από μία τιμή ε, η οποία
θα πρέπει να ζητηθεί από τον χρήστη στην αρχή του
προγράμματος (να χρησιμοποιηθεί η εντολή
scanf). Όταν θα σταματήσει τον υπολογισμό, θα πρέπει να
εκτυπώνει στην οθόνη το συνολικό γινόμενο, την
τιμή του k στην οποία έφτασε και την τιμή του
τελευταίου παράγοντα του γινομένου, πριν να
σταματήσει η διαδικασία.
7.5 Άσκηση: Επιλογή με την εντολή switch
Με βάση τα προγράμματα που δημιουργήσατε στις
παραγράφους 6.3 και 6.5 να κατασκευάσετε ένα
νέο το οποίο θα ζητάει από τον χρήστη να εισάγει
την επιλογή του αν θέλει να κάνει πρόσθεση ή
πολλαπλασιασμό. Η επιλογή του χρήστη θα εισάγεται
μέσω της εντολής scanf ενώ ο τρόπος με τον
οποίο θα επιλέγεται ο πολλαπλασιασμός ή η πρόσθεση
θα γίνεται μέσω των εντολών
switch…case…default.
8. Άσκηση (Παραγοντικό)
8.1 Συναρτήσεις
Μερικά τμήματα ενός προγράμματος είναι σχεδόν
αυτόνομα και μπορούν να γραφούν ξεχωριστά από
το κύριο πρόγραμμα. Η C παρέχει αυτή τη δυνατότητα
με τις functions. Μια συνάρτηση έχει δομή
όμοια με αυτήν ενός προγράμματος, καλείται δε
από το κυρίως πρόγραμμα ή από άλλες συναρτήσεις.
Οι συναρτήσεις επιστρέφουν μια τιμή στο πρόγραμμα
μέσω του ονόματος τους, ή αλλάζουν την τιμή
κάποιας μεταβλητής του κυρίως ή άλλου προγράμματος..
8.2 Καθολικές και τοπικές μεταβλητές.
Κατά την εκτέλεση ενός προγράμματος δεσμεύεται
μνήμη-χώρος για τις μεταβλητές που
χρησιμοποιούνται. Οι μεταβλητές αυτές έχουν καθολική ισχύ και
ονομάζονται καθολικές (global)
μεταβλητές. Όταν κληθεί μια συνάρτηση δεσμεύεται
μνήμη για τις εσωτερικές (local) μεταβλητές τις.
Αυτές έχουν ισχύ εσωτερικά στη διαδικασία και
η μνήμη που καταλαμβάνουν αποδεσμεύεται μετά το
τέλος της διαδικασίας. Χρησιμοποιώντας τοπικές
μεταβλητές οι διαδικασίες αποκτούν αυτονομία και
μεγαλύτερη εμβέλεια χρήσης.
8.3 Παράμετροι τιμής.
H C δίνει τη δυνατότητα να περαστούν τιμές σε
μεταβλητές της διαδικασίας όταν αυτή καλείται. Έτσι
μια διαδικασία επικοινωνεί με τον έξω χώρο και
μπορεί να παραμετροποιηθεί. Με αυτό τον τρόπο
καθίσταται αυτόνομη και μπορεί να χρησιμοποιηθεί
ακόμα και από άλλα προγράμματα. Στο
πρόγραμμα μας δηλώνουμε τη συνάρτηση
factorial με τον τρόπο που φαίνεται πιο κάτω:
int
factorial(int n_int)
Η παράμετρος n_int είναι μια ακέραια
παράμετρος η οποία κληροδοτείται από το κύριο πρόγραμμα
κατά την κλήση της συνάρτησης. Έτσι στο πρόγραμμα
καλούμε την factorial με τον εξής τρόπο :
k = factorial(n);
Η τιμή της μεταβλητής n δίνεται στην
παράμετρο n_int της συνάρτησης. Σε αυτήν την περίπτωση η
συνάρτηση επιστρέφει τιμές μέσω του ονόματος
της.
8.4 Η χρήση συνάρτησης με δείκτες.
Ο δεύτερος τρόπος χρήσης συνάρτησης παραπάνω
(void calculate_factorial(int n, int *m)) είναι μία
κλασική χρήση δεικτών στη C. Αν δεν είχαμε βάλει
τον αστερίσκο στο όρισμα της συνάρτησης, η τιμή
της m δε θα άλλαζε όταν την καλούσαμε
από την main. Ουσιαστικά με αυτόν τον τρόπο, καλόντας τη
μεταβλητή με αναφορά, της δίνουμε τη δυνατότητα
να αλλάξει τιμή στο κυρίως πρόγραμμα.
8.5 Ν! (Ν παραγοντικό)
Το Ν παραγοντικό (Ν!), ως γνωστό, δίνεται
από τη σχέση Ν!=1*2*3*...*(Ν-1)*Ν αν Ν>0 ή Ν!=1 αν
Ν=0. Στο πρόγραμμα μας υπολογίζουμε με δύο τρόπους
το Ν!. Στη μία η συνάρτηση επιστρέφει την
τιμή Ν! μέσω του ονόματός της. Στην άλλη με
κλήση μιας μεταβλητής του κυρίου προγράμματος με
αναφορά (με δείκτη).
8.6 Εφαρμογή
Παρακάτω δίνεται το πρόγραμμα, το οποίο διαθέτει
δύο συναρτήσεις για υπολογισμό του Ν!. Η πρώτη
χρησιμοποιεί τη δομή for ενώ
η δεύτερη είναι μια αναδρομική συνάρτηση.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΠΡΟΓΡΑΜΜΑ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ
ΛΑΘΗ ΚΑΙ
ΠΑΡΑΛΕΙΨΕΙΣ ΠΟΥ ΠΡΕΠΕΙ ΝΑ ΕΝΤΟΠΙΣΕΤΕ ΩΣΤΕ ΝΑ
ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
//Dilosi
synartiseon:
//Edo i
exodos einai typou int
int
factorial(int n_int);
//Edo
den yparhei exodos alla mia metabliti kaleitai me anafora (i
//n_factorial
void
calculate_factorial(int m_int, int *n_factorial);
int
main(void)
{
int n,
m, k ;
printf(“\nGive
me non-negative value of N = ”);
scanf(“%d”,
&n);
//O enas
tropos:
k =
factorial(n);
printf(“\n%d!=%d”,n,k);
//O allos
tropos:
calculate_factorial(n,&m);
printf(“\n%d!=%d”,n,m);
return
0;
}
int
factorial(int n_int)
{
int i,
fact; //i, fact einai topikes metablites
if
(n_int = = 0)
return
1;
else
{
fact =
1;
for
(i=1; i<=n_int; ++i)
fact *=
i;
return
fact;
}
}
void calculate_factorial(int
m_int, int *n_factorial)
{
int i,
fact;
if
(m_int = = 0)
*n_factorial
= 1;
else
{
fact =
1;
for
(i=1; i<=m_int; ++i)
fact *=
i;
*n_factorial
= fact;
}
}
9. Άσκηση (Ανταλλαγή Θέσεως Τιμών Δύο Μεταβλητών)
Το παρακάτω πρόγραμμα είναι ένα βασικό πρόγραμμα
στη λογική του προγραμματισμού: Διαβάζει
δύο πραγματικούς αριθμούς και να τους τοποθετεί
στις μεταβλητές x, y και μετά να τους ανταλλάσει
θέσεις.
#include
<stdio.h>
int
main(void)
{
//Define
variables
double
x, y, prosorini;
/*function
body*/
printf(“\n
Give values of x and y:”);
scanf(“%lf
%lf ”, &x, &y);
printf(“\nx
= %f y = %f \n”, x, y);
prosorini
= x;
x = y;
y =
prosorini;
printf(“\n
x = %f \t y = %f”, x, y);
return 0;
}
10. Άσκηση (Ταξινόμηση φυσσαλίδας)
10.1 Ταξινόμηση.
Ταξινόμηση γενικά είναι η διαδικασία αναδιευθέτησης
ενός δεδομένου συνόλου αντικειμένων σε
μια συγκεκριμένη σειρά. Ο σκοπός της ταξινόμησης είναι να διευκολύνει
τη μετέπειτα αναζήτηση
των αντικειμένων μέσα στο ταξινομημένο σύνολο. Η ταξινόμηση είναι απαραίτητη σε τηλεφωνικούς
καταλόγους, σε πίνακες περιεχομένων, σε λεξικά,
σε βιβλιοθήκες και γενικά όπου υπάρχουν
αποθηκευμένα στοιχεία που πρέπει να ανακαλουνται.
Πρόκειται δηλαδή για μια θεμελιώδη ενέργεια
στην επεξεργασία δεδομένων.
10.2 Ταξινόμηση φυσαλλίδας.
Η ταξινόμηση φυσαλλίδας (BubbleSort)
χρησιμοποιεί διαδοχικά περάσματα από τον πίνακα και
κάθε φορά μεταφέρεται το μικρότερο στοιχείο
του υπόλοιπου συνόλου στο αριστερό άκρο του πίνακα.
Αν φανταστούμε τον πίνακα σε κατακόρυφη μορφή
και τα στοιχεία σα φυσαλλίδες σε δοχείο με νερό
με βάρη ανάλογα με τα κλειδιά τους τότε κάθε
πέρασμα του πίνακα έχει σαν αποτέλεσμα την
αναρρίχηση μιας φυσαλλίδας (bubble) στο σωστό
επίπεδο βάρους. Παράδειγμα φαίνεται στον πίνακα
(1) που ακολουθεί.
Παρατηρούμε ότι στα τρία τελευταία περάσματα
ο πίνακας ήταν ήδη ταξινομημένος. Άλλοι αλγόριθμοι
λαμβάνουν υπ’ όψην τους αν σε ένα πέρασμα έγινε
ή όχι κάποια ανταλλάγή και έτσι τελειώνουν. Εμείς
θα δούμε τον απλό αλγόριθμο ο οποίος θα ταξινομεί
10 στοιχεία.
10.3 Λογικές δομές.
Στα πλαίσια του δομημένου προγραμματισμού χρησιμοποιούνται
λογικά διαγράμματα που παριστούν
βασικές λογικές δομές. Στο πρόγραμμα χρησιμοποιούνται
η σειριακή δομή (που έχουμε γνωρίσει στη
2η άσκηση) και η δομή επανάληψης: for
(i=l; i<=n;++i) (σχήμα 1).
10.4 Εφαρμογή
Παρακάτω δίνεται το πρόγραμμα, το οποίο ταξινομεί
n αριθμούς που εσείς εισάγετε.
ΠΡΟΣΟΧΗ! ΣΤΟ ΠΑΡΑΚΑΤΩ ΥΠΑΡΧΟΥΝ ΣΥΝΤΑΚΤΙΚΑ ΛΑΘΗ
Η/ΚΑΙ ΠΑΡΑΛΕΙΨΕΙΣ.
ΠΡΕΠΕΙ ΝΑ ΤΑ ΒΡΕΙΤΕ ΩΣΤΕ ΤΟ ΤΕΛΙΚΟ ΠΡΟΓΡΑΜΜΑ
ΝΑ ΤΡΕΧΕΙ ΚΑΝΟΝΙΚΑ
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
int i,
j, list_size;
double
temp;
printf(“\n
Give list size of the list n= ”);
scanf(“%d”,&list_size);
// Here we
define the list a of size list_size
double
a[list_size];
for
(i=0; i<list_size; ++i)
{
printf(“\n
Give me element a[%d]= ”, i+1);
scanf(“%lf”,&a[i]);
}
// First
for-loop
for
(i=0; i<list_size-1; ++i)
{
//
Second for-loop
for
(j=i+1; j<list_size; ++j)
{
//
Compare
if
(a[i]>a[j])
{
temp=a[j];
a[j] =
a[i];
a[i]=temp;
}
}
}
printf(“\nOrdered
list is given below\n”);
for
(i=0; i<list_size; ++i)
printf(“a[%d]
= %7.3f\n”, i+1, a[i]);
}
return 0;
}
Το πρόγραμμα ζητάει τους n αριθμούς και τους
ταξινομεί. Χρησιμοποιεί τη δομή for δύο φορές και
τυπώνει στην οθόνη τα αποτελέσματα.
11. Άσκηση (Υπολογισμός Απόλυτης Τιμής)
11.1 Εφαρμογή
Μία απλή εφαρμογή της εντολής if είναι
να υπολογίστε την απόλυτη τιμή ενός πραγματικού αριθμού
που δίνεται από το πληκτρολόγιο (χωρίς να χρησιμοποιείσετε
την εντολή fabs(a)). Η διαδικασία είναι η
εξής: Πρώτα εισάγεται η τιμή του αριθμού από
το πληκτρολόγιο. Κατόπιν ελέγχεται το πρόσημο του
αριθμού, δηλαδή αν το a<0.0. Αν το a είναι
αρνητικό του αλλάζουμε πρόσημο με την εντολή “a= -a”.
Αν το a είναι θετικό δεν κάνουμε τίποτε. Κατόπιν
τυπώνουμε τον αριθμό a, ο οποίος τώρα έχει σίγουρα
θετικό πρόσημο. Τη διαδικασία τη βλέπουμε στο
παρακάτω διάγραμμα ροής:
#include
<stdio.h>
int
main(void)
{
//
Define variables
double
a;
printf(“\n
Give value a”);
scanf(“%lf”, &a); //{εισαγωγή στοιχείων}
// Εδώ πρέπει να συμπληρώσετε το πρόγραμμα,
στο οποίο τσεκάρετε αν το
// a είναι αρνητικός. Άν είναι, τότε του αλλάζετε
πρόσημο, δηλ. a=-a.
// Κατόπιν τυπώνετε την απόλυτη τιμή του a.
return 0;
}
12. Άσκηση (Υπολογισμός Τόκων και Κεφαλαίου)
Στο παρακάτω πρόγραμμα μας δίνεται το αρχικό
κεφάλαιο μίας κατάθεσης, καθώς και το επιτόκιο, και
ο αριθμός ετών της κατάθεσης. Ζητούμενο είναι
η αξία του κεφαλαίου σαν συνάρτηση του χρόνου.
#include
<stdio.h>
int
main(void)
{
double
epitokio, kefalaio, tokos, axia_kef;
int
etos, plithos_eton;
printf("Doste
times gia kefalaio, plithos eton, epitokio \n");
scanf("%lf
%d %lf",
&kefalaio,
&plithos_eton, &epitokio);
axia_kef
= kefalaio;
printf("Etos Tokos
Axia \n");
for
(etos = 1; etos <= plithos_eton; ++etos)
{
tokos =
axia_kef * epitokio;
axia_kef
+= tokos;
printf("%4d
%15f %15f\n", etos, tokos, axia_kef);
}
return 0;
}
13. Άσκηση (Υπολογισμός Σειράς
Fibonacci)
Το παρακάτω πρόγραμμα είναι ένα κλασικό πρόγραμμα
υπολογισμού σειράς. Συγκεκριμένα ζητείται ο
υπολογισμός των όρων της σειράς Fibonacci, η
οποία δίνεται με τη σχέση
Sn+=1
Sn + Sn−1 με αρχικές τιμέ= 1,= 1 . Η σειρά Fibonacci έμφανίζεται
συχνά
στα μαθηματικά και στη φύση. Δείτε για παράδειγμα την ιστοσελίδα
/*Ypologiste
tis akolouthias Fibonacci A(n+1)=A(n)+A(n-1)*/
#include<stdio.h>
int
main(void)
{
/*Orismos
metavliton*/
int i,
n, an, an1, an2;
printf("Doste
to n>=2: n = ");
scanf("%d",
&n);
/*
Ypologismos tou athroismatos */
an = 1;
/*arxiki timi */
an1 = 1;
/*arxiki timi */
printf("\n
a[0] =%d\n", an);
printf("\n
a[1] =%d\n", an1);
for (i =
2; i<=n; ++i)
{
an2 =
an1+ an;
an =
an1;
an1 =
an2;
printf("\n
a(%d] =%d\n", i, an2);
}
return 0;
}
14. Άσκηση (Πολλαπλασιασμός Μιγαδικών Αριθμών)
Μία απλή άσκηση που χρησιμοποιεί συναρτήσεις
στην C είναι ο υπολογισμός του γινομένου
μιγαδικών αριθμών.
/*Ypologiste
to ginomeno 2 migadiko arithmon*/
#include<stdio.h>
#include<math.h>
double
real_product(double real1, double imag1, double real2, double imag2);
double
imag_product(double real1, double imag1, double real2, double imag2);
int
main(void)
{
/*Orismos
metavliton*/
double
x1, y1, x2, y2, x3, y3;
printf("Doste
to pragmatiko meros tou protou migadikou arithmou: x1 = ");
scanf("%lf",
&x1);
printf("Doste
to fantastiko meros tou protou migadikou arithmou: y1 = ");
scanf("%lf",
&y1);
printf("Doste
to pragmatiko meros tou 2ou migadikou arithmou: x2 = ");
scanf("%lf",
&x2);
printf("Doste
to fantastiko meros tou 2ou migadikou arithmou: y2 = ");
scanf("%lf",
&y2);
x3 =
real_product(x1,y1,x2,y2);
y3 =
imag_product(x1,y1,x2,y2);
printf("\n
z3 = %f + i%f\n", x3, y3);
return
0;
}
double
real_product(double real1, double imag1, double real2, double imag2)
{
double
temp = real1*real2-imag1*imag2;
return
temp;
}
double
imag_product(double real1, double imag1, double real2, double imag2)
{
return
real1*imag2+imag1*real2;
}
15. Άσκηση (Υπολογισμός Αθροίσματος
1+2+...+n)
Μία πολύ απλή άσκηση είναι ο υπολογισμός του
αθροίσματος 1+...+n.
/*Ypologiste
to athroisma S_n = 1 + 2 + 3.... +n*/
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
/*Orismos
metavliton*/
int n,
i;
int S;
printf("\n
Dose tin timi tou n = ");
scanf("%d",
&n);
S = 0;
for
(i=1; i<=n; ++i)
S=S+i;
printf("\n
To athroisma S_n = %d \n", S);
return 0;
}
Μια παρόμοια άσκηση ακολουθεί
/*Ypologiste to athroisma 1+1/2^2+1/3^2…+1/n^2*/
#include<stdio.h>
#include<math.h>
int
main(void)
{
/*Orismos
metavliton*/
int i,
n;
double
athroisma =0.0;
printf("Doste
to n>=2: n = ");
scanf("%d",
&n);
for
(i=1;i<=n;i++)
{
athroisma
+= 1.0/(i*i);
}
printf("\n
ATHROISMA = %f\n", athroisma);
printf("\n
orio = %f\n", pow(3.14159,2)/6.0);
return 0;
}
16. Άσκηση (Υπολογισμός Εσωτερικού Γινομένου)
Μία άλλη πολύ απλή άσκηση είναι ο υπολογισμός
του εσωτερικού γινομένου 2 Ν-διάστατων
ανυσμάτων
/*Ypologiste
to synimitono ths gonias 2 n-diastaton anoismaton */
#include
<stdio.h>
#include
<math.h>
int
main(void){
double
sum_aa, sum_ab, sum_bb, cos_theta;
printf("\n
Give me the size of the vectors: n = ");
scanf("%d",&n);
double
a[n], b[n];
for
(k=0; k<n; k++){
printf("a[%d]
= ", k);
scanf("%lf",&a[k]);
}
for
(k=0; k<n; k++){
printf("b[%d]
= ", k);
scanf("%lf",&b[k]);
}
printf("k=
%d",k);
sum_ab =
0.0;
sum_bb =
0.0;
sum_aa =
0.0;
for
(k=0; k<n; k++){
sum_ab =
sum_ab+a[k]*b[k];
sum_aa =
sum_aa+a[k]*a[k];
sum_bb =
sum_bb+b[k]*b[k];
}
cos_theta
= sum_ab/sqrt(sum_aa*sum_bb);
printf("\nesot
ginomeno a.b = %lf", sum_ab);
printf("\n
metro a = %lf", sum_aa);
printf("\n
metro b = %lf", sum_bb);
printf("\n
cosine of angle btw a b = %lf\n", cos_theta);
return 0;
}
17. Άσκηση (Υπολογισμός Εμβαδού Τριγώνου)
#include
<stdio.h>
#include
<math.h>
int main(void)
{
// Edo dilonoume metavlites
double
x, h, E;
printf("\n
Typose to mikos tis pleyras tou trigonou\n");
scanf("%lf",
&x);
h =
sqrt(3)/2.0*x;
E =
0.5*x*h;
printf("\n
To ypsos tou trigonou einai: %lf", h);
printf("\n
To embadon tou trigonou einai: %lf\n", E);
return 0;
}
18. Άσκηση (Μετατροπή Βαθμών Fahrenheit
σε Celsius)
/*
Programma pou metatrepei ti thermokrasia
apo
Fahrenheit se Kelsiou */
#include
<stdio.h>
#include
<math.h>
int
main(void)
{
double
F, C;
printf("\nDose
ti thermokrasia se vathmous Fahrenheit\n");
scanf("%4lf",
&F);
printf("F=%10.4lf",
F);
C =
5.0/9.0*(F-32.0);
printf("\nI
thermokrasia se vathmous Kelsiou einai %lf C\n", C);
return 0;
}
19. Άσκηση (Συνάρτηση Εισαγωγής Δεδομένων
Πίνακα)
Μία εφαρμογή της δημιουργίας εξωτερικής συνάρτησης
στο πρόγραμμα είναι η εξής
#include
<stdio.h>
const
int n=2;
void
read_matrix(double *matrix[n][n]);
int main
(void){
int i,
j;
double
a[n][n], b[n][n];
read_matrix(&a[3][3]);
// read_matrix(&b);
for
(i=0; i<n; i++){
for
(j=0; j<n; j++){
printf("a[%d][%d]
= %lf\n",i,j, a[i][j]);
}
}
system("pause");
return
0;
}
void
read_matrix (double *matrix[n][n]){
int i,j;
for
(i=0; i<n; i++){
for
(j=0; j<n; j++){
printf("Give
me x[%d][%d] = ",i,j);
scanf("%lf",&matrix[i][j]);
}
}
}