Πανεπιστήµιο Κρήτης, Τµήµα Επιστήµης Υπολογιστών 4 Νοεµβρίου 2011 ΗΥ240: οµές εδοµένων Χειµερινό Εξάµηνο Ακαδηµαϊκό Έτος 2011-12 ιδάσκουσα: Παναγιώτα Φατούρου Προγραµµατιστική Εργασία 1 ο Μέρος Ηµεροµηνία Παράδοσης: ευτέρα, 21 Νοεµβρίου 2011, ώρα 23:59. Τρόπος Παράδοσης: Χρησιµοποιώντας το πρόγραµµα submit. Πληροφορίες για το πώς λειτουργεί το submit παρέχονται στην ιστοσελίδα του µαθήµατος. Γενική Περιγραφή Στην εργασία αυτή σας ζητείται να υλοποιήσετε ένα πρόγραµµα διαχείρισης των δεδοµένων ενός βιβλιοπωλείου. Το βιβλιοπωλείο κατηγοριοποιεί τα βιβλία που διαθέτει στις ακόλουθες κατηγορίες: 1. Ελληνική Πεζογραφία, 2. Ξένη Πεζογραφία, 3. Ελληνική Ποίηση, 4. Ξένη Ποίηση, 5. Αρχαίοι Έλληνες Συγγραφείς, 6. Επιστήµη, 7. Εκλαϊκευµένη Επιστήµη, 8. Ιστορία, 9. Φιλοσοφία, 10. Ψυχολογία, 11. Παιδικό, κλπ. Κάθε βιβλίο κατηγοριοποιείται σε µία µόνο από αυτές τις κατηγορίες. Νέες κατηγορίες µπορεί να απαιτείται να προστεθούν προκειµένου να κατηγοριοποιηθούν κατάλληλα, νέα βιβλία που εκδίδονται. Τέλος το πρόγραµµα θα πρέπει να διατηρεί πληροφορίες για τους πελάτες του. Πιο συγκεκριµένα, κάθε πελάτης µπορεί να δηλώσει ή όχι πως επιθυµεί να ενηµερώνεται για νέα βιβλία που εκδίδονται, σε οποιεσδήποτε από τις παραπάνω κατηγορίες τον ενδιαφέρουν. Σε αυτή την περίπτωση, το βιβλιοπωλείο πρέπει περιοδικά να ενηµερώνει τους πελάτες του για τις νέες κυκλοφορίες βιβλίων στις κατηγορίες αυτές. Αναλυτική Περιγραφή Ζητούµενης Υλοποίησης Στην εργασία αυτή ζητείται να υλοποιηθεί ένα πρόγραµµα διαχείρισης αρχείων ενός βιβλιοπωλείου. Πιο συγκεκριµένα, το πρόγραµµα θα πρέπει να υλοποιεί τις ακόλουθες δοµές δεδοµένων. οµές εδοµένων που αφορούν κατηγορίες βιβλίων και βιβλία Όπως προαναφέρθηκε, τα βιβλία κατηγοριοποιούνται σε κατηγορίες. Πληροφορίες για κάθε κατηγορία αποθηκεύονται στα στοιχεία ενός πίνακα Categories[MC], όπως φαίνεται στο Σχήµα 1, όπου MC (Maximum Categories) είναι το µέγιστο πλήθος κατηγοριών που µπορούν να υπάρχουν στο σύστηµα. Ο πίνακας αυτός ονοµάζεται πίνακας κατηγοριών βιβλίων. Παρατηρήστε πως στον πίνακα µπορούν µόνο να προστίθενται νέες κατηγορίες και πως έχει γίνει η υπόθεση πως το συνολικό πλήθος κατηγοριών δεν θα ξεπεράσει τις MC. Categories[0] Categories[1] Categories[2] Categories[MC-1] Σχήµα 1 Πληροφορίες για κάθε κατηγορία αποθηκεύονται σε µια εγγραφή (struct) τύπου category που αποτελείται από τα πεδία που παρουσιάζονται στη συνέχεια. o Έναν ακέραιο cιd που εκφράζει το αναγνωριστικό της κατηγορίας. Τα αναγνωριστικά διαφορετικών κατηγοριών πρέπει να είναι διαφορετικά. Θεωρήστε πως ισχύει 0 cid MC-1. 1
o Έναν δείκτη, BL, ο οποίος δείχνει στο πρώτο στοιχείο µιας απλά συνδεδεµένης ταξινοµηµένης λίστας, η οποία ονοµάζεται λίστα βιβλίων. Η λίστα περιέχει τα βιβλία που ανήκουν στην κατηγορία αυτή, ταξινοµηµένα ως προς το αναγνωριστικό τους (). Η µορφή κάθε στοιχείου του πίνακα κατηγοριών βιβλίων παρουσιάζεται στο Σχήµα 2. cid BL Σχήµα 2 Κάθε ένα βιβλίο περιγράφεται από ένα struct που αποτελείται από τα ακόλουθα πεδία: Έναν ακέραιο που αποτελεί το αναγνωριστικό του βιβλίου. Το αναγνωριστικό είναι µοναδικό για κάθε βιβλίο. Έναν ακέραιο Author που αποτελεί το αναγνωριστικό του συγγραφέα του βιβλίου Έναν ακέραιο Publisher που αποτελεί το αναγνωριστικό του εκδοτικού οίκου. Έναν ακέραιο Year που αποθηκεύει το έτος έκδοσης του βιβλίου (π.χ., 2004, 1993, κλπ.) Έναν πραγµατικό αριθµό Price που αποθηκεύει την τιµή του βιβλίου Έναν ακέραιο Stock που αποθηκεύει το πλήθος των αντιτύπων του βιβλίου που είναι διαθέσιµα στο βιβλιοπωλείο την τρέχουσα χρονική στιγµή. Αν η τιµή του πεδίου αυτού γίνει 0, τότε το βιβλίο δεν είναι πια διαθέσιµο και η εγγραφή του θα πρέπει να διαγράφεται από τη λίστα βιβλίων της κατηγορίας στην οποία ανήκει. Η µορφή των δοµών δεδοµένων που περιγράφονται παραπάνω περιγράφονται στο Σχήµα 5. οµές εδοµένων που αφορούν τους πελάτες Επιπρόσθετα των παραπάνω δοµών, θα πρέπει να υλοποιηθεί και µια λίστα πελατών, κάθε στοιχείο της οποίας είναι ένα struct τύπου customer που περιέχει τις εξής πληροφορίες: Έναν ακέραιο custid που αποτελεί το µοναδικό αναγνωριστικό για τον πελάτη Έναν δείκτη SL στο πρώτο στοιχείο µιας λίστας που λέγεται λίστα αγορών του πελάτη, τα στοιχεία της οποίας περιγράφονται στη συνέχεια. Έναν πραγµατικό αριθµό TAmount που αποτελεί το συνολικό ποσό που ο πελάτης έχει πληρώσει για όλες τις αγορές του. Έναν πίνακα IC[MC] των MC στοιχείων που περιγράφει τις κατηγορίες βιβλίων που ενδεχόµενα ενδιαφέρουν τον πελάτη αυτόν. Αν ισχύει IC[i] == 1, 0 i MC-1, τότε ο πελάτης ενδιαφέρεται για την κατηγορία βιβλίων i. Αντίθετα, αν IC[i] == 0, τότε ο πελάτης δεν ενδιαφέρεται για την κατηγορία βιβλίων i. Έναν δείκτη που δείχνει στο επόµενο στοιχείο της λίστας πελατών. Η λίστα πελατών είναι µη-ταξινοµηµένη, ενώ η λίστα αγορών κάθε πελάτη είναι ταξινοµηµένη ως προς το <> πεδίο των εγγραφών της. Κάθε στοιχείο της λίστας αγορών ενός πελάτη είναι ένα struct τύπου sale που περιέχει τα ακόλουθα πεδία: Έναν ακέραιο που περιέχει το αναγνωριστικό ενός βιβλίου που έχει αγοραστεί από τον πελάτη. Έναν ακέραιο <Copies> που αποθηκεύει πόσα αντίγραφα του βιβλίου έχει αγοράσει ο πελάτης. Έναν δείκτη που δείχνει στο επόµενο στοιχείο της λίστας. 2
Η εγγραφή τύπου customer παρουσιάζεται στο Σχήµα 3. cid TAmount SL IC[0]... IC[MC-1] struct customer Σχήµα 3 Η µορφή των δοµών δεδοµένων που αφορούν του πελάτες παρουσιάζονται στο Σχήµα 6. Τρόπος Λειτουργίας Προγράµµατος Το πρόγραµµα που θα δηµιουργηθεί, θα πρέπει να ορίζει µε στατικό τρόπο (µε τη χρήση του #define) το µέγιστο πλήθος κατηγοριών (MC) στο σύστηµα και θα πρέπει να εκτελείται καλώντας την ακόλουθη εντολή: run <input-file> όπου run είναι το όνοµα του εκτελέσιµου αρχείου του προγράµµατος και <input-file> είναι το όνοµα ενός αρχείου εισόδου που περιέχει γεγονότα των ακόλουθων µορφών: o B <> <Category> <Author> <Publisher> <Year> <Price> <Stock>: Γεγονός τύπου Book το οποίο σηµατοδοτεί την άφιξη <Stock> αντιτύπων ενός βιβλίου µε αναγνωριστικό <> στο βιβλιοπωλείο. Το βιβλίο έχει εκδοθεί το έτος <Year> από τον εκδοτικό οίκο <Publisher>, έχει γραφτεί από το συγγραφέα µε αναγνωριστικό <Author>, η τιµή του είναι <Price> και ανήκει στην κατηγορία µε αναγνωριστικό <Category>. Εποµένως, τα <Category>, <Author>, <Publisher>, <Year>, <Price> και <Stock> είναι ακέραιοι αριθµοί. H λίστα βιβλίων της κατηγορίας <Category> θα πρέπει να ενηµερωθεί ώστε να περιέχει και το νέο βιβλίο (δηλαδή θα πρέπει να εισαχθεί σε αυτή µια εγγραφή που να αναφέρεται στο βιβλίο). H εγγραφή αυτή θα πρέπει να εισαχθεί στην κατάλληλη θέση της λίστας ώστε αυτή να παραµείνει ταξινοµηµένη ως προς το πεδίο των βιβλίων που περιέχει. Αν η λίστα περιέχει ήδη το βιβλίο, το πεδίο Stock της αντίστοιχης εγγραφής θα πρέπει να ενηµερωθεί ώστε να αποθηκεύει το σωστό πλήθος αντιτύπων του βιβλίου που είναι διαθέσιµα στο βιβλιοπωλείο (δηλαδή θα πρέπει να προστεθούν και τα νέα αντίτυπα που µόλις έφθασαν). Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος, το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη B <> <Category> <Author> <Publisher> <Year> <Price> <Stock> DONE CategoryID = <cid 1 >, BookLIST = < 1 1, stock 1 1 >, < 2 1, stock 2 1 >,, < r1 1, stock r1 1 > GategoryID = <cid 2 >, BookLIST = < 1 2, stock 1 2 >, < 2 2, stock 2 2 >,, < r2 2, stock r2 2 > GategoryID = <cid k >, BookLIST = < 1 k, stock 1 k >, < 2 k, stock 2 k >,, < rk k, stock rk k > 3
όπου 1 i, 2 i,, ri i, όπου 1 i k, είναι τα των βιβλίων που είναι αποθηκευµένα στη λίστα βιβλίων της κατηγορίας µε αναγνωριστικό <cid i > (όπου έχουµε υποθέσει πως αυτά είναι r i στο πλήθος) και stock j i, 1 j r i, είναι το πλήθος των διαθέσιµων αντιτύπων του βιβλίου µε αναγνωριστικό j i. o S <custid> <> <Category> <Copies>. Γεγονός τύπου Sales το οποίο σηµατοδοτεί την αγορά <Copies> αντιγράφων του βιβλίου µε αναγνωριστικό <> από τον πελάτη µε αναγνωριστικό <custid>. Το βιβλίο µε αναγνωριστικό <> πρέπει να αναζητηθεί στη λίστα βιβλίων της κατηγορίας <Category>. Όταν η εγγραφή e που αντιστοιχεί σε αυτό το βιβλίο βρεθεί, θα πρέπει να αφαιρεθούν από το πεδίο <Stock> αυτής της εγγραφής το πλήθος <Copies> των αντιγράφων που αγοράστηκαν από τον πελάτη. Αν το πεδίο <Stock> της εγγραφής e γίνει ίσο µε µηδέν µετά την αφαίρεση αυτή, η e θα πρέπει να διαγράφεται από τη λίστα. Αν δεν υπάρχει εγγραφή για το βιβλίο <> ή αν το πεδίο <Stock> της εγγραφής αυτής είναι µικρότερο από το <Copies> θα πρέπει να τυπώνεται κατάλληλο µήνυµα. Για την ολοκλήρωση της εκτέλεσης του γεγονότος αυτού θα πρέπει να αναζητηθεί η εγγραφή που αντιστοιχεί στον πελάτη µε αναγνωριστικό <custid> στην λίστα πελατών και να προστεθεί στο πεδίο <TAmount> της εγγραφής αυτής το ποσό που αντιστοιχεί στην τιµή του βιβλίου <> (η τιµή είναι αποθηκευµένη στο πεδίο <Price> της εγγραφής e). Η λίστα αγορών του πελάτη αυτού θα πρέπει επίσης να ενηµερωθεί. Αν δεν υπάρχει εγγραφή που να αντιστοιχεί στο εν λόγω <> στη λίστα αυτή, θα πρέπει να προστεθεί µια τέτοια εγγραφή, διαφορετικά η εγγραφή αυτή θα πρέπει να ενηµερωθεί ώστε να υποδηλώνει ότι ο πελάτης έχει αγοράσει <Copies> επιπρόσθετα αντίτυπα αυτού του βιβλίου. Τέλος, σηµειώνεται πως αν δεν υπάρχει εγγραφή για τον πελάτη στη λίστα πελατών, θα πρέπει να προστεθεί πρώτα µια τέτοια εγγραφή και στη συνέχεια να γίνουν οι ενέργειες που περιγράφτηκαν παραπάνω. Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη S <custid> <> <Copies> DONE BOOKLIST of CATEGORY <Category> = < 1, Copies 1 >, < r, Copies r > CustomerLIST = CustID1 = <custid1>, SalesLIST = < 1 1, 1 1 >, < 2 1, 2 1 >,, <n 1 1, n1 1 > CustID2 = <custid2>, SalesLIST = < 1 2, 1 2 >, < 2 2, 2 2 >,, < n2 2, n2 2 > CustIDm = <custidm>, SalesLIST = < 1 m, >, < 2 m, 2 m >,, < nm m, nm m > όπου <custid> είναι το αναγνωριστικό του πελάτη που έκανε την αγορά, <> είναι το αναγνωριστικό του βιβλίου που αγοράστηκε και <Copies> είναι το πλήθος των αντιγράφων του που αγοράστηκαν από το εν λόγω βιβλίο. Επιπρόσθετα, r είναι το πλήθος των εγγραφών στη λίστα βιβλίων της κατηγορίας <Category>, i και Copies i είναι το και η τιµή του πεδίου Copies, αν ίστοιχα, της i-οστής εγγραφής στη λίστα αυτή, όπου 1 i r. Τέλος, m είναι το πλήθος των εγγραφών της λίστας πελατών, <custidj>, 1 j m, είναι το αναγνωριστικό του πελάτη που αντιστοιχεί στην j-οστή εγγραφή της λίστας αυτής, n j είναι το πλήθος των στοιχείων που υπάρχουν στη λίστα αγορών του πελάτη αυτού, j l, 1 l n j, είναι το του βιβλίου που j αντιστοιχεί στην l-οστή εγγραφή της λίστας αυτής και l είναι το πλήθος των αντιτύπων του βιβλίου j l που έχει αγοράσει ο πελάτης µε αναγνωριστικό <custid j >. o R <custid> <cid1> <cid2> <cidk> -1: Γεγονός τύπου Preferences που παρέχει τις κατηγορίες βιβλίων για τις οποίες ενδιαφέρεται ο πελάτης µε αναγνωριστικό <custid>. Οι κατηγορίες αυτές είναι εκείνες µε αναγνωριστικά <cid1> <cid2> <cidk>, όπου k MC. Παρατηρήστε ότι η ακολουθία αναγνωριστικών κατηγοριών <cid1> <cid2> <cidk> για τις οποίες ενδιαφέρεται ο πελάτης τερµατίζει µε το αναγνωριστικό -1 που δεν είναι έγκυρο αναγνωριστικό κάποιας κατηγορίας στο σύστηµα. Η πίνακας IC της εγγραφής της λίστας πελατών που αναφέρεται στον πελάτη µε αναγνωριστικό <custid> θα πρέπει να ενηµερωθεί ώστε να αποθηκεύει τις προτιµήσεις του πελάτη σε κατηγορίες. Αν ο πελάτης µε 4
αναγνωριστικό <custid> δεν υπάρχει στη λίστα πελατών, θα πρέπει να προστεθεί µια εγγραφή για τον πελάτη αυτόν στη λίστα, όπου το πεδίο TAmount της νέας εγγραφής θα πρέπει να έχει τιµή 0 και το πεδίο BL να είναι NULL. Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη R <custid> <cid1> <cid2> <cidk> DONE CustomerLIST = CustID = <custid1>, IC = <cid 1 1, cid 2 1,, cid l1 1 > CustID = <custid2>, IC = <cid 1 2, cid 2 2,, cid l2 2 > CustID = <custidm>, IC = <cid 1 m, cid 2 m,, cid lm m > όπου τα <custid>, <cid1>, <cid2>,,<cidk>, σηµειοδοτούν ό,τι περιγράφτηκε παραπάνω, m είναι το πλήθος των στοιχείων στη λίστα πελατών, <custid1>,, <custidm> είναι τα αναγνωριστικά των m πελατών που περιέχονται στη λίστα και <cid 1 i, cid 2 i,, cid li i >, 1 i MC, είναι τα αναγνωριστικά των κατηγοριών για τις οποίες ο πελάτης µε αναγνωριστικό <custid i > ενδιαφέρεται (όπου έχουµε υποθέσει πως αυτές είναι l i < CM στο πλήθος). o F 1 <>: Γεγονός τύπου Find 1 που σηµατοδοτεί την ανεύρεση πληροφορίας. Πιο συγκεκριµένα, το αποτέλεσµα του γεγονότος αυτού πρέπει να είναι η τύπωση των αναγνωριστικών όλων των πελατών που έχουν αγοράσει το βιβλίο µε αναγνωριστικό <>. Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη F 1 <> DONE CustomerIDs = <CustId1>, <CustId2>,, <CustIdm>, NO_Customers = m όπου m είναι το πλήθος των πελατών που έχουν αγοράσει το βιβλίο µε αναγνωριστικό <>, <custidi>, 1 i m, είναι το αναγνωριστικό του m-οστού τέτοιου πελάτη από τη λίστα πελατών. o F 2 <Publisher>: Γεγονός τύπου Find 2 που σηµατοδοτεί την ανεύρεση πληροφορίας. Πιο συγκεκριµένα, το αποτέλεσµα του γεγονότος αυτού πρέπει να είναι η τύπωση των αναγνωριστικών όλων των βιβλίων που ανήκουν στον εκδοτικό οίκο <Publisher>. Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη F 2 <Publisher> DONE s = <1>, <2>,, <r>, NO_BOOKS = r όπου r είναι το πλήθος των βιβλίων που ανήκουν στον εκδοτικό οίκο <Publisher> και <1>, <2>,, <r> είναι τα αναγνωριστικά των βιβλίων αυτών. o F 3 <Publisher>: Γεγονός τύπου Find 3 που σηµατοδοτεί την ανεύρεση πληροφορίας. Πιο συγκεκριµένα, το αποτέλεσµα του γεγονότος αυτού πρέπει να είναι η τύπωση των αναγνωριστικών όλων των πελατών που έχουν αγοράσει βιβλία του εκδοτικού οίκου <Publisher>. F 3 <Publisher> DONE CustomerIDs = <CustId1>, <CustId2>,, <CustIdm>, NO_Customers = m όπου m είναι το πλήθος των πελατών που έχουν αγοράσει τουλάχιστον ένα βιβλίο του εκδοτικού οίκου µε αναγνωριστικό <Publisher> και <CustId1>, <CustId2>,, <CustIdm> είναι τα αναγνωριστικά των πελατών αυτών. o P: Γεγονός τύπου Print που σηµατοδοτεί την εκτύπωση των δοµών δεδοµένων του συστήµατος. Συγκεκριµένα, για κάθε µία από τις κατηγορίες, θα πρέπει να εκτυπώνεται η λίστα βιβλίων της κατηγορίας αυτής. Επίσης, θα 5
πρέπει να εκτυπώνεται η λίστα πελατών και για κάθε έναν από αυτούς να εκτυπώνονται τόσο οι πληροφορίες της εγγραφής που του αντιστοιχεί όσο και όλα τα βιβλία που έχει αγοράσει., δηλαδή εκείνα τα στοιχεία του πίνακα sgp που περιγράφουν τις οµάδες για τις οποίες ενδιαφέρεται ο συνδροµητής. Μετά το πέρας της εκτέλεσης ενός τέτοιου γεγονότος το πρόγραµµα θα πρέπει να τυπώνει την ακόλουθη P DONE CategoryID = <cid 1 >, BookLIST = < 1 1, 2 1,, r1 1 > CategoryID = <cid 2 >, BookLIST = < 1 2, 2 2,, r2 2 > CategoryID = <cid MC >, BookLIST= < 1 MC, 2 MC,, rmc MC > CUSTOMERLIST = CUSTOMERID = <custid1>, SalesLIST = < 1 1,, n1 1 > CUSTOMERID = <custid2>, SalesLIST = < 1 2,, n2 2 > CUSTOMERID = <custidm>, SalesLIST = < 1 m,, nm m > NO_CATEGORIES = <number of categories>, NO_Customers = <number of customers> όπου <cidi>, 1 i MC, είναι το αναγνωριστικό της κατηγορίας Categories[<cIdi>], r i είναι το πλήθος των στοιχείων στη λίστα βιβλίων της κατηγορίας <cid i >, < 1 i, 2 i,, ri i > είναι η ακολουθία των των βιβλίων που περιέχονται στη λίστα βιβλίων της κατηγορίας <cid i >. Επιπρόσθετα, <custid j > είναι το αναγνωριστικό του πελάτη που αντιστοιχεί στο j-οστό στοιχείο της λίστας πελατών, n j είναι το πλήθος βιβλίων στη λίστα αγορών του πελάτη µε αναγνωριστικό <custid j > και <c 1 j,, c nj j > είναι τα αναγνωριστικά των βιβλίων τα οποία έχει αγοράσει ο πελάτης αυτός. Τέλος, <number of categories> είναι το συνολικό πλήθος των κατηγοριών που δεν είναι κενές βιβλίων και <number of customers> είναι το συνολικό πλήθος των πελατών στο σύστηµα. Το πρόγραµµα που θα δηµιουργηθεί πρέπει να διαβάζει το αρχείο εισόδου και να εκτελεί µε τη σειρά όλα τα γεγονότα που περιγράφονται σε αυτό. Οδηγίες και Συµβουλές για την Οµαλή ιεκπεραίωση της Εργασίας Η εργασία θα πρέπει να πραγµατοποιηθεί σε βήµατα. Ο κάθε φοιτητής είναι υπεύθυνος να αποφασίσει ποια βήµατα ταιριάζουν στον τρόπο εργασίας του. Στη συνέχεια, παρατίθεται µια δυνητική ακολουθία βηµάτων που θα µπορούσε να ακολουθηθεί για την οµαλή διεκπεραίωση της εργασίας. Βήµα 1: Ξεκινήστε υλοποιώντας ένα µέρος του γεγονότος B (Book). Για την υλοποίηση του γεγονότος αυτού πρέπει αρχικά να υλοποιήσετε τη λίστα βιβλίων. Η λίστα αυτή είναι µια απλά συνδεδεµένη λίστα, που όµως πρέπει να διατηρεί τις εγγραφές ταξινοµηµένες ως προς το πεδίο. Φτιάξτε διαδικασίες BLInsert, BLDelete και BLLookUp για µια ταξινοµηµένη συνδεδεµένη λίστα, προκειµένου να πραγµατοποιείτε εισαγωγές, διαγραφές και αναζητήσεις, αντίστοιχα, στη λίστα αυτή. ηµιουργήστε µια διαδικασία BLPrint() για την εκτύπωση των στοιχείων της λίστας η οποία θα σας βοηθήσει να ελέγξετε την ορθότητα των διαδικασιών που περιγράφονται παραπάνω. ηµιουργήστε τον κώδικα σας σε ένα δικό σας αρχείο και φτιάξτε µια δική σας main() για να ελέγξετε ότι ο κώδικας που υλοποιεί τις λειτουργίες µιας απλά συνδεδεµένης ταξινοµηµένης λίστας λειτουργεί σωστά. Όταν είστε σίγουροι για αυτό συνεχίστε στο επόµενο βήµα. 6
Βήµα 2: Τελειώστε την υλοποίηση του γεγονότος B, δηµιουργώντας τον πίνακα Categories, κάθε στοιχείο του οποίου δεικτοδοτεί µια λίστα βιβλίων. ηµιουργήστε ένα αντίγραφο του βασικού αρχείου (εκείνου που περιέχει τη συνάρτηση main() που σας παρείχαν οι βοηθοί) και βάλτε σε σχόλια τον κώδικα που αναφέρεται σε γεγονότα άλλα από το B. Στο βήµα αυτό θα δουλέψετε µόνο µε γεγονότα τύπου Β. Αποµονώστε στα test_files που σας παρείχαν οι βοηθοί τα γεγονότα τύπου B και δείτε ότι το πρόγραµµά που παρήγατε σε αυτό το βήµα εκτελείται σωστά για τέτοια γεγονότα. Βήµα 3: Υλοποιήστε το γεγονός τύπου F 2. Αυτό απαιτεί την προσθήκη µιας ρουτίνας F2() που, για κάθε κατηγορία, θα διασχίζει τη λίστα βιβλίων της κατηγορίας αυτής και θα τυπώνει εκείνα τα βιβλία σε αυτήν που έχουν εκδοθεί από τον εκδότη <Publisher>. Και πάλι, τροποποιήστε κατάλληλα τα test_files που σας παρείχαν οι βοηθοί και ελέγξτε πως το γεγονός αυτό εκτελείται σωστά. Βήµα 4: Σε ένα νέο αρχείο, υλοποιήστε την λίστα πελατών. Πιο συγκεκριµένα, πρέπει να υλοποιήσετε τις συναρτήσεις/ρουτίνες CustInsert() που εισάγει ένα στοιχείο τύπου Customer στη λίστα πελατών, CustFind() που αναζητά έναν πελάτη µε αναγνωριστικό <custid> στη λίστα αυτή και CustPrint() που τυπώνει ολόκληρη τη λίστα. Η λίστα αυτή δεν είναι ταξινοµηµένη και έτσι θα πρέπει ο κώδικας σας να µην είναι ίδιος µε εκείνον που γράψατε για τις λίστες βιβλίων στο Βήµα 1). Το πεδίο SL κάθε στοιχείου της λίστας αυτής θα πρέπει να είναι στο παρόν βήµα ίσο µε NULL (αφού δεν ζητείται να υλοποιήσετε και τη λίστα αγορών στο βήµα αυτό). ηµιουργήστε µια δική σας main() (παρόµοια µε εκείνη το βήµατος 1) για να ελέγξετε ότι ο κώδικας που υλοποιεί τις λειτουργίες µιας απλά συνδεδεµένης µη-ταξινοµηµένης λίστας λειτουργεί σωστά. Όταν είστε σίγουροι για αυτό συνεχίστε στο επόµενο βήµα. Βήµα 5: Υλοποιήστε το γεγονός τύπου R. Αυτό απαιτεί την κατάλληλη ενηµέρωση του πίνακα IC των εγγραφών της λίστας πελατών. Βεβαιωθείτε πως και αυτό το γεγονός εκτελείται σωστά. Βήµα 6: Αντιγράψτε τον κώδικα που δηµιουργήσατε στο Βήµα 1 σε ένα νέο αρχείο και κάντε κατάλληλες τροποποιήσεις για να πάρετε τον κώδικα για µια λίστα αγορών. Εφόσον τα στοιχεία της λίστας αυτής είναι ταξινοµηµένα ως προς το πεδίο <>, ο κώδικας που θα προκύψει θα είναι παρόµοιος µε εκείνον του Βήµατος 1 (ωστόσο δεν χρειάζεστε την Delete εδώ). Στο βήµα αυτό δεν χρειάζεται να χειριστείτε τον πίνακα IC που αποθηκεύεται σε κάθε στοιχείο Customer. Βήµα 7: Στο βήµα αυτό θα συνδυάσετε τους κώδικες που δηµιουργήσατε στα Βήµατα 4, 5 και 6 για να τελειώσετε την υλοποίηση της λίστας πελατών που είναι ουσιαστικά µια λίστα από λίστες. Χρησιµοποιήστε τα γεγονότα τύπου S που παρέχονται στα test_files που παρείχαν οι βοηθοί για να ελέγξετε πως η λίστα πελατών ενηµερώνεται σωστά. Σηµειώνεται ότι το γεγονός S απαιτεί ενέργειες και στη λίστα βιβλίων για να εκτελεστεί σωστά, αλλά ενσωµατώστε αυτές τις ενέργειες µόνο όταν βεβαιωθείτε πως ο συνδυασµός του κώδικα της λίστας πελατών και των λιστών αγορών λειτουργούν σωστά. Βήµα 8: Υλοποιήστε το γεγονός τύπου P (Print). Συνδυάστε και τροποποιήστε κατάλληλα τις διαδικασίες ΒLPrint, CustPrint και SLPrint (αρχεία βηµάτων 1, 2 και 4) για να δηµιουργήσετε τη διαδικασία Print η οποία θα υλοποιεί το γεγονός τύπου P. Βήµα 9: Υλοποιήστε το γεγονός τύπου F 1. Αυτό απαιτεί την προσθήκη µιας ρουτίνας F1() που θα διασχίζει τη λίστα των πελατών και για κάθε πελάτη, θα καλεί την SLFind() για να βρει αν το βιβλίο µε αναγνωριστικό <> υπάρχει στη λίστα αυτή. Αν ναι, το αναγνωριστικό του πελάτη θα τυπώνεται. Βήµα 10: Υλοποιήστε το γεγονός τύπου F 2. Βήµα 11: Ελέγξετε την ορθότητα του κώδικα που δηµιουργήσατε εκτελώντας τον κώδικά σας σε όλα τα αρχεία εκτέλεσης που θα σας παρέχουν οι βοηθοί του µαθήµατος. Επιπρόσθετα, δηµιουργήστε τα δικά σας αρχεία γεγονότων για να ελέγξετε µε περισσότερη ακρίβεια την ορθότητα του κώδικά σας. οµές εδοµένων Στο Σχήµα 4 παρουσιάζονται οι δοµές σε C που πρέπει να χρησιµοποιηθούν για την υλοποίηση της παρούσας εργασίας. Επειδή το πλήθος των κατηγοριών, δηλαδή το MC, είναι γνωστό εκ των προτέρων δεσµεύσουµε µε στατικό τρόπο τον απαραίτητο χώρο µνήµης για την αποθήκευση των πινάκων IC που χρησιµοποιούν το MC. #define MC 100 struct book{ int ; 7
} int Author; int Publisher; int Year; float Price; int Stock; struct book *; stuct category { int cid; struct book *BL; } struct category Categories[MC]; struct sale { int ; int ; struct sale *; } sturct customer { int custid; struct sale *SL; float TAmmount; int IC[MC]; struct customer *; } struct customer *Customers; Σχήµα 4 8
Πανεπιστήµιο Κρήτης, Τµήµα Επιστήµης Υπολογιστών 4 Νοεµβρίου 2011 Categories[0] Categories[1] Categories[2] Categories[MC-1] c I D B L cid BL cid BL cid BL Σχήµα 5 9
Πανεπιστήµιο Κρήτης, Τµήµα Επιστήµης Υπολογιστών 4 Νοεµβρίου 2011 cid SL TAmount IC[0] IC[MC-1] cid SL TAmount IC[0] IC[MC-1] cid SL TAmount IC[0] IC[MC-1] Σχήµα 6 10