ΑΣΚΗΣΗ 1 Structural Programming Στην άσκηση αυτή θα υλοποιήσετε σε C ένα απλό πρόγραµµα Βάσης εδοµένων το οποίο θα µπορούσε να χρησιµοποιηθεί από την γραµµατεία ενός πανεπιστηµίου για την αποθήκευση και διαχείριση πληροφορίας σχετική µε τηνβαθµολογία των φοιτητών στα µαθήµατα που εγγράφονται. Τα δεδοµένα που θα εισάγονται στο σύστηµα από το χρήστη θα πρέπει να αποθηκεύονται σε ένα αρχείο. Το αρχείο αυτό θα το διαβάζει το πρόγραµµα κατά την εκκίνηση του. Το πρόγραµµα θαπρέπειναυποστηρίζειτις βασικές λειτουργίες εισαγωγής, αλλαγής και εύρεσης στοιχείων όπως περιγράφονται στην συνέχεια. Η βασική εγγραφή θα πρέπει να έχει τα παρακάτω στοιχεία : Κωδικός φοιτητή (Ακέραιος αριθµός µοναδικός για κάθε φοιτητή) Ονοµατεπώνυµο φοιτητή Κωδικός µαθήµατος (Ακέραιος αριθµός µοναδικός για κάθε µάθηµα) Βαθµός 1
Οι λειτουργίες που πρέπει να υποστηρίζονται από το πρόγραµµα θα εµφανίζονται µέσω ενός βασικού µενού στην οθόνη του χρήστη και θα είναι οι εξής: Εισαγωγή νέας εγγραφής: Ο χρήστης εισάγει ένα-έναταστοιχείατηςεγγραφής µε την παραπάνω σειρά (κωδικός φοιτητή, όνοµα φοιτητή, κωδικός µαθήµατος, βαθµός). Αλλαγή στοιχείων: Σε αυτή την επιλογή ζητούνται από τον χρήστη τα εξής στοιχεία: => Κωδικός Μαθητή (StudenID) => Κωδικός µαθήµατος (LessonID) Με τα στοιχεία αυτά το πρόγραµµα θα εντοπίσει τη σχετική εγγραφή (αν υπάρχει), θα την τυπώσει στη οθόνη και στη συνέχεια θα ρωτήσει το χρήστη αν θέλει να προχωρήσει ή όχι στην αλλαγή του πεδίου ΒΑΘΜΟΣ. Σε περίπτωση που ο χρήστης επιθυµεί να αλλάξει το βαθµό τοσύστηµα θα του ζητήσει τη νέα τιµή του βαθµού και θα αντικαταστήσει την παλιά. Εύρεση βαθµολογίας µαθήµατος φοιτητή: O χρήστης εισάγει τον κωδικό του φοιτητή και τον κωδικό µαθήµατος και στην οθόνη εµφανίζεται το όνοµα του φοιτητή, ο κωδικός του, ο κωδικός του µαθήµατος και ο βαθµός που έχει πάρει ο φοιτητής στο συγκεκριµένο µάθηµα. Στατιστικά στοιχεία φοιτητή: Με αυτή την επιλογή ο χρήστης εισάγει τον κωδικό του φοιτητή και το σύστηµα του εµφανίζει: µια λίστα µε τους κωδικούς όλων των µαθηµάτων στα οποία έχει εγγραφεί ο φοιτητής µαζί µε την αντίστοιχη βαθµολογία σε κάθε µάθηµα µια λίστα µόνο µε τα µαθήµατα (και την αντίστοιχη βαθµολογία) που έχει περάσει ο φοιτητής (βαθµός>=5) µια λίστα µόνο µε ταµαθήµατα (και την αντίστοιχη βαθµολογία) που έχει αποτύχει ο φοιτητής (βαθµός < 5) το µέσος όρος βαθµολογίας του φοιτητή σε όλα τα µαθήµατα. Εύρεση φοιτητών µε συγκεκριµένο όριο βαθµολογίας σε συγκεκριµένο µάθηµα: Εισάγεται ο κωδικός του µαθήµατος και ένας βαθµός Χ και το πρόγραµµα εµφανίζει τους κωδικούς και τα ονόµατα των φοιτητών που έχουν βαθµολογία στο συγκεκριµένο µάθηµα µεγαλύτερηήίσητουχ(βαθµός >= Χ). Πρόσθεση εγγραφών από αρχείο: Με την επιλογή αυτή επιτρέπεται η εισαγωγή νέων εγγραφών, κατά τη διάρκεια εκτέλεσης της εφαρµογής σας, από κάποιο αρχείο, οι οποίες πρέπει να προστεθούν στις ήδη υπάρχουσες. ΣΗΜΕΙΩΣΗ:Το σύστηµα σας θα πρέπει να είναι σε θέση να απαντάει µε µηνύµατα λάθους προς τον χρήστη, όταν τα δεδοµένα που εισάγει ο τελευταίος προκειµένου να εκτελέσει µια από τις παραπάνω λειτουργίες, δεν είναι υπαρκτά (π.χ εκτέλεση λειτουργία εύρεσης βαθµολογίας µαθηµάτων, µε εισαγωγή κωδικού φοιτητή που δεν υπάρχει στη βάση δεδοµένων σας). 2
Ο ΗΓΙΕΣ Με την εκκίνηση της εφαρµογής θα δηµιουργείτε στη µνήµη µια δοµή δεδοµένων τύπου λίστας, µονά διασυνδεδεµένη, () από εγγραφές τις οποίες θα διαβάζετε από αρχείο (αν το αρχείο είναι άδειο θα ενηµερώνει το χρήστη και θα του ζητάει να εισάγει εγγραφές στο σύστηµα). Κάθε νέα εγγραφή που διαβάζεται από αρχείο ή εισάγεται από το χρήστη θα προστίθεται στο τέλος της λίστας (append). (εικόνα 1) Πέρα από την παραπάνω βασική Λίστα που θα κρατάει τις εγγραφές του συστήµατος, θα χρησιµοποιήσετε 2 ακόµα βοηθητικές λίστες δεικτοδότησης (Indexes) οι οποίες θα διευκολύνουν την αναζήτηση της πληροφορίας που είναι απαραίτητη στις λειτουργίες ανάκτησης δεδοµένων και στατιστικών στοιχείων: Η µία λίστα (Students Index) θα έχει σε κάθε κόµβο της α) τον κωδικό ενός φοιτητή (StudentID) και β) µια λίστα της οποίας οι κόµβοι θα περιέχουν τους κωδικούς των µαθηµάτων (LessonIDs) πουέχειεγγραφείοφοιτητήςκαθώςεπίσηςκαιδείκτεςπροςτουςκόµβους εκείνους της MainList πουπεριέχουντιςεγγραφέςτωνµαθηµάτων τα οποία έχει πάρει ο φοιτητής Student ID (εικόνα 2) Η δεύτερη λίστα (Lessons Index) αντίστοιχα, θα έχει σε κάθε κόµβο της α) τον κωδικό ενός µαθήµατος () και β) µια λίστα της οποίας οι κόµβοι θα περιέχουν τους κωδικούς των φοιτητών (StudentIDs) που έχουν εγγραφεί στο µάθηµα, καθώςεπίσηςκαιδείκτεςπροςτους κόµβους εκείνους της MainList που περιέχουν τους φοιτητές οι οποίοι έχουν πάρει το µάθηµα. (εικόνα 2) Το κεντρικό αρχείο όπου θα αποθηκεύονται µόνιµα οι εγγραφές της βάσης δεδοµένων θα ενηµερώνεται από το πρόγραµµα σας στις περιπτώσεις που ο χρήστης: α) εισάγει νέες εγγραφές από το πληκτρολόγιο, β) επιλέξει την εισαγωγή νέων εγγραφών από άλλο αρχείο γ) αλλάξει το βαθµό σεέναµάθηµα (LessonID) ενός φοιτητή (StudenID), στην περίπτωση αυτή θα πρέπει να φροντίσετε να βρείτε την αντίστοιχη εγγραφή πουείναι αποθηκευµένη στο αρχείο και να αλλάξετε την τιµή του πεδίου ΒΑΘΜΟΣ. Στις 2 πρώτες περιπτώσεις απλά πρέπει να εισάγετε τις εγγραφές στο τέλος του βασικού αρχείου ΚΑΙ στο τέλος της. Στην Τρίτη όµως περίπτωση αφού διορθώσετε το ΒΑΘΜΟ στη, πρέπει να ψάξετε µέσαστοαρχείογιανα εντοπίσετε που βρίσκεται η εγγραφή αυτή (LessonID, StudenID) και να της αλλάξετε το πεδίο ΒΑΘΜΟΣ. Επίσης δεν πρέπει να ξεχνάτε µετάαπόκάθενέαεγγραφήναενηµερώνεται και τις 2 βοηθητικές λίστες (Students Index, Lessons Index) Να κάνετε προσεκτικό σχεδιασµό των επιµέρους ανεξάρτητων λειτουργιών της άσκησης τις οποίες θα υλοποιήσετε µε χρήση συναρτήσεων (procedural programming). 3
Students Index Lessons Index Stud-1 Stud-2 Stud-x Less-1 Less-2 Less-z L-1 L-1 L-1 S-1 S-1 S-1 L-2 L-2 L-2 S-2 S-2 S-2 L-3 L-3 L-3 S-3 S-3 S-3 L-k L-l L-m S-n S-q S-r (Stud-2, Less-1) (Stud-2,Less-2) Εικόνα 1 Students Index Lessons Index Lessons StudID-2 Lessons StudID-X Lessons LessID-1 Students LessID-2 Students LessID-Z Students LesID-1 LesID-1 LesID-1 LesID-2 LesID-2 LesID-2 StudID -2 StudID -2 StudID -2 LesID-3 LesID-3 LesID-3 StudID -3 StudID -3 StudID -3 LesID-k LesID-l LesID-m StudID -n StudID -q StudID -r Εικόνα 2 4
ιευκρινήσεις ΟΜΗ ΒΑΣΙΚΗΣ ΕΓΓΡΑΦΗΣ-ΑΡΧΕΙΟΥ Ηδοµή της βασικής εγγραφής που θα αποθηκεύεται στο αρχείο θα είναι η ακόλουθη: struct { int stud_id; // student id char name[50]; // student's name int less_id; // lesson id float mark; // mark }record; ΕΥΡΕΣΗ ΑΡΙΘΜΟΥ ΕΓΓΡΑΦΩΝ ΠΟΥ ΥΠΑΡΧΟΥΝ ΣΤΟ ΑΡΧΕΙΟ Είναι σηµαντικό να τονίσουµε ότιστο αρχείο που θα αποθηκεύετε τις εγγραφές σας θα σώζετε ΜΟΝΟ δοµές τύπου record (προηγούµενη διευκρίνηση) και τίποτε άλλο.!!! Αν λοιπόν θέλουµε ναβρούµε τον αριθµό των εγγραφών που έχουν αποθηκευτεί σε ένα αρχείο, που ανοίγουµε για να το διαβάσουµε, µπορούµε ναεφαρµόσουµε τηνεξής λογική. FILE *db; void main() { record rec; int num_of_records, count; long file_size; db = fopen("records.dat", "rb"); if ( (fseek(db,0,seek_end))!=0 ) { printf("error in reading to the end of file"); return; } /*number of bytes in the file*/ file_size = ftell(db); num_of_records = file_end/sizeof(rec); fseek(db,0, SEEK_SET); fclose(db); } 5
Ησυνάρτησηftell(db) επιστρέφει το µέγεθος των δεδοµένων σε bytes που παρεµβάλλονται από την αρχή του αρχείου µέχρι το σηµείο που βρίσκεται ο FILE pointer (δηλ ο db). Άρα για να βρούµε τοσυνολικό µέγεθος του αρχείου απλά µετακινούµε τον db στο τέλος του αρχείου (χρησιµοποιώντας τη συνάρτηση fseek(db,0,seek_end)) και στη συνέχεια καλούµε τηνftell(db) για να µας δώσει το µέγεθος των δεδοµένων σε bytes από την αρχή έως το τέλος του αρχείου. Άρα αφού λοιπόν γνωρίζουµε τοµέγεθος του αρχείου (file_size) και το µέγεθος της κάθε εγγραφής (sizeof(rec)) οαριθµός των αρχείων προκύπτει µε µια απλή διαίρεση: num_of_records = file_end/sizeof(rec) 6