ZAKKWYLDE Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Σωστα.. Με τις διορθωσεις που προτεινες δουλεψε.. Απλα εγω μπερδευομαι και μεταφραζω μεσα μου το while=Μεχρις_οτου απο την ΓΛΩΣΣΑ και εξου και οι λαθος συνθηκες.. Τωρα οσο αναφορα την εκτυπωση που λες.. Θα το προσπαθησω να βαζει την τομη σε εναν πινακα Δ ετσι ωστε να μην υπαρχουν επαναληψεις.. Ευχαριστω ΠΟΛΥ... Το προβλημα ομως που προκυπτει ειναι το μεγεθος του πινακα Δ.. Νωριτερα στο προγραμμα ο χρηστης καθοριζει το μεγεθος των τριων πινακων.. Δεν ξερεις ποσα ειναι τα κοινα στοιχεια ετσι ωστε να φτιαξεις αναλογο πινακα.. Μπορει να ειναι 3 μπορει ομως να ειναι και 200 Με βάση αυτά που πιστεύω ότι έχετε διδαχθεί μέχρι τώρα, ο εντελώς "μπακαλίστικος" τρόπος είναι να κάνεις τον πίνακα Δ όσο το μέγεθος του μεγαλύτερου πίνακα. Τα κοινά στοιχεία θα είναι <= αυτού του πίνακα όταν μιλάμε για τομές. Τώρα στην εκτύπωση μπορεί να έχεις έναν πίνακα μισογεμάτο και εσύ θέλεις να εκτυπώνεις μέχρι εκεί που έχεις νούμερα. Απλά το LOOP για την εκτύπωση θα το τρέξεις μέχρι να βρείς κελί NULL(αφού τα έχεις αρχικοποιήσει σε NULL απο την αρχή). Αυτό φυσικά προϋποθέτει ότι όταν βρείς κοινά στοιχεία τα προσθέτεις στον πίνακα Δ στο πρώτο "κενό" κελί. Η υλοποίηση αυτή φυσικά δεν είναι η ενδεδειγμένη σε πραγματικές συνθήκες, αλλά νομίζω επιτυγχάνει το σκοπό της άσκησης. Όταν μπείς σε Δομές Δεδομένων θα δεις ότι υπάρχουν πολύ καλύτεροι τρόποι να το κάνεις
migf1 Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Με βάση αυτά που πιστεύω ότι έχετε διδαχθεί μέχρι τώρα, ο εντελώς "μπακαλίστικος" τρόπος είναι να κάνεις τον πίνακα Δ όσο το μέγεθος του μεγαλύτερου πίνακα. Τα κοινά στοιχεία θα είναι <= αυτού του πίνακα όταν μιλάμε για τομές. Σωστό! Η δική μου πρόταση σε προηγούμενο ποστ για το άθροισμα των πινάκων είναι προφανώς εσφαλμένη (ή ακριβέστερα, αχρείαστα μνημοβόρα... θα το διορθώσω). Τώρα στην εκτύπωση μπορεί να έχεις έναν πίνακα μισογεμάτο και εσύ θέλεις να εκτυπώνεις μέχρι εκεί που έχεις νούμερα. Απλά το LOOP για την εκτύπωση θα το τρέξεις μέχρι να βρείς κελί NULL(αφού τα έχεις αρχικοποιήσει σε NULL απο την αρχή).Αυτό φυσικά προϋποθέτει ότι όταν βρείς κοινά στοιχεία τα προσθέτεις στον πίνακα Δ στο πρώτο "κενό" κελί. Κι αυτό σωστό (όπως είπε και ο imitheos), με την προϋπόθεση πως ο Δ θα είναι πίνακας δεικτών. Κι αν είναι πίνακας δεικτών, τότε σε κάθε κοινό στοιχείο θα πρέπει να κάνει malloc() τον αντίστοιχο δείκτη του Δ και στο τέλος να τους κάνει όλους free(). Μια άλλη ιδέα, κι εφόσον μιλάμε για int στοιχεία, είναι να αρχικοποιήσει τον Δ σε INT_MIN ή σε ΙΝΤ_ΜΑΧ. Χάνει ως valid τιμή όποιο από τα 2 αυτά επιλέξει, αλλά είναι αποδεκτό κόστος εις όφελος του σημαντικά πιο απλού κώδικα αλλά και της σημαντικά καλύτερης ταχύτητας.
ZAKKWYLDE Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Κι αυτό σωστό (όπως είπε και ο imitheos), με την προϋπόθεση πως ο Δ θα είναι πίνακας δεικτών. Κι αν είναι πίνακας δεικτών, τότε σε κάθε κοινό στοιχείο θα πρέπει να κάνει malloc() τον αντίστοιχο δείκτη του Δ. Έχω την εντύπωση ότι δεν είναι απαραίτητο αυτό. Μπορεί να έχει int array[sizeA], και να κάνει ένα loop αμέσως μετά και να αρχικοποιήσει array = NULL. Στην εκτύπωση θα κάνει ένα loop while array != NULL. Δεν είμαι απόλυτα σίγουρος βέβαια . Βέβαια νομίζω ότι το INT_MIN/INT_MAX μου αρέσει περισσότερο τώρα που το βλέπω.
imitheos Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Εφόσον ο OP δουλεύει με βάση τα στοιχεία του A, το πιο εύκολο είναι όπως είπες να το κάνει με το μέγεθος του A αντί να ψάχνει ποιος πίνακας έχει τι διάσταση. Ακαδημαϊκά όμως, χρειάζεται ο Δ να έχει μέγεθος όσο αυτό του μεγαλύτερου πίνακα ? Αν ο Α έχει 3 στοιχεία και ο Β έχει 352 στοιχεία, τα κοινά στοιχεία μπορούν να είναι περισσότερα των τριών ?
ZAKKWYLDE Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Όχι ότι έχει διαφορά για τα δεδομένα των μεγεθών που μιλάμε αλλά χρειάζεται ο Δ να έχει μέγεθος όσο αυτό του μεγαλύτερου πίνακα ? Αν ο Α έχει 3 στοιχεία και ο Β έχει 352 στοιχεία, τα κοινά στοιχεία μπορούν να είναι περισσότερα των τριών ? Ναι έχεις δίκιο . Τελικά και εγώ έφαγα περισσότερη μνήμη απ'ότι έπρεπε
migf1 Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Έχω την εντύπωση ότι δεν είναι απαραίτητο αυτό. Μπορεί να έχει int array[sizeA], και να κάνει ένα loop αμέσως μετά και να αρχικοποιήσει array = NULL. Στην εκτύπωση θα κάνει ένα loop while array != NULL. Δεν είμαι απόλυτα σίγουρος βέβαια . Βέβαια νομίζω ότι το INT_MIN/INT_MAX μου αρέσει περισσότερο τώρα που το βλέπω. Αν βρίσκονται ακόμα πολύ αρχή, το πιο ωραίο από όλα είναι ο κώδικας που έδωσε ο imitheos, με την boolean. Σχετικά με το NULL, στην C συνήθως ορίζεται ως: (void *)0 αλλά είναι implementation dependent. Είναι ακριβώς ο ίδιος λόγος που το calloc(1, sizeof(Struct)) ή το memset(Struct, 0, sizeof(Struct)) δεν εγγυώνται πως αν η δομή Struct περιέχει δείκτες τότε θα αρχικοποιηθούν σε NULL. Τουλάχιστον αυτά ίσχυαν παλιά, ίσως έχουν αλλάξει σε μεταγενέστερα πρότυπα της γλώσσας. EDIT Άντε πάλι edit στο edit Σωστός imithee!
imitheos Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 (επεξεργασμένο) Σχετικά με το NULL, στην C συνήθως ορίζεται ως: (void *)0 αλλά είναι implementation dependent. Είναι ακριβώς ο ίδιος λόγος που το calloc(1, sizeof(Struct)) ή το memset(Struct, 0, sizeof(Struct)) δεν εγγυώνται πως αν η δομή Struct περιέχει δείκτες τότε θα αρχικοποιηθούν σε NULL. Τουλάχιστον αυτά ίσχυαν παλιά, ίσως έχουν αλλάξει σε μεταγενέστερα πρότυπα της γλώσσας. Έτσι είναι όντως (και δεν νομίζω να μπορεί να αλλάξει ο συγκεκριμένος κανόνας). Το πρόβλημα όμως δεν είναι ότι στην memset βάζεις 0 και όχι (void *)0. Το NULL είναι όντως implementation dependent όπως είπες χωρίς όμως να μπορεί να πάρει ό,τι τιμές θέλει ο implementor αλλά πρέπει να οριστεί ως "Null Pointer Constant". Ως NPC ορίζεται το (void *)0 ή οποιαδήποτε ICE (Integer Constant Exp<b></b>ression) έχει τιμή 0. Δηλαδή μπορεί να έχει τιμή (void *)0, 0, (int 0), (long) 0, κτλ αλλά οπωσδήποτε μία από αυτές. Το implementation-defined κομμάτι του NULL σημαίνει ότι μπορείς να επιλέξεις οποιαδήποτε από τις παραπάνω τιμές θέλεις. Γιατί τώρα μας δημιουργεί πρόβλημα η memset και η calloc. > int *p = 0; int k = 0; int *q = k; Ο δείκτης q ΔΕΝ είναι NULL pointer γιατί ενώ μεν του θέτουμε την τιμή 0, ΔΕΝ χρησιμοποιούμε Integer Constant Exp<b></b>ression άρα δεν έχουμε Null Pointer Constant. Είναι ευθύνη του compiler να θέτει στο δείκτη τη σωστή διεύθυνση μόνο όποτε βλέπει NPC. Αν λοιπόν έχουμε μια πλατφόρμα στην οποία η διεύθυνση ενός NULL pointer είναι το 17236, τότε ο compiler θα δώσει στον δείκτη p την σωστή τιμή 17236 ενώ ο δείκτης q θα δείχνει λανθασμένα στην διεύθυνση 0. Αυτό είναι και το πρόβλημα της memset και της calloc γιατί χρησιμοποιούν κάποια μεταβλητή και όχι απευθείας την τιμή 0. Θα μπορούσε η memset να έχει ειδική μέριμνα για την περίπτωση του μηδενός αλλά δεν βλέπω καμμία libc να το κάνει. Η calloc υλοποιείται με κάλεσμα της memset (τουλάχιστον σε Free,Net BSD) οπότε δεν εγγυάται ούτε αυτή. Το κομμάτι που είπα για ειδική μέριμνα δεν πρέπει να είναι σωστό γιατί δεν μπορεί η memset να ξέρει τι δεδομένα έχουμε περάσει για να μεριμνήσει. Απλά γράφει 0 σε κάθε "byte" (ή σε πολλαπλά ταυτόχρονα αν η libc έχει κάποια optimized έκδοση). Επεξ/σία 24 Νοεμβρίου 2012 από imitheos
ZAKKWYLDE Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Έτσι είναι όντως (και δεν νομίζω να μπορεί να αλλάξει ο συγκεκριμένος κανόνας). Το πρόβλημα όμως δεν είναι ότι στην memset βάζεις 0 και όχι (void *)0. Το NULL είναι όντως implementation dependent όπως είπες χωρίς όμως να μπορεί να πάρει ό,τι τιμές θέλει ο implementor αλλά πρέπει να οριστεί ως "Null Pointer Constant". Ως NPC ορίζεται το (void *)0 ή οποιαδήποτε ICE (Integer Constant Expression) έχει τιμή 0. Δηλαδή μπορεί να έχει τιμή (void *)0, 0, (int 0), (long) 0, κτλ αλλά οπωσδήποτε μία από αυτές. Το implementation-defined κομμάτι του NULL σημαίνει ότι μπορείς να επιλέξεις οποιαδήποτε από τις παραπάνω τιμές θέλεις. Γιατί τώρα μας δημιουργεί πρόβλημα η memset και η calloc. > int *p = 0; int k = 0; int *q = k; Ο δείκτης q ΔΕΝ είναι NULL pointer γιατί ενώ μεν του θέτουμε την τιμή 0, ΔΕΝ χρησιμοποιούμε Integer Constant Expression άρα δεν έχουμε Null Pointer Constant. Είναι ευθύνη του compiler να θέτει στο δείκτη τη σωστή διεύθυνση μόνο όποτε βλέπει NPC. Αν λοιπόν έχουμε μια πλατφόρμα στην οποία η διεύθυνση ενός NULL pointer είναι το 17236, τότε ο compiler θα δώσει στον δείκτη p την σωστή τιμή 17236 ενώ ο δείκτης q θα δείχνει λανθασμένα στην διεύθυνση 0. Αυτό είναι και το πρόβλημα της memset και της calloc γιατί χρησιμοποιούν κάποια μεταβλητή και όχι απευθείας την τιμή 0. Θα μπορούσε η memset να έχει ειδική μέριμνα για την περίπτωση του μηδενός αλλά δεν βλέπω καμμία libc να το κάνει. Η calloc υλοποιείται με κάλεσμα της memset (τουλάχιστον σε Free,Net BSD) οπότε δεν εγγυάται ούτε αυτή Άρα με βάση αυτό, όταν αρχικοποιείς όλους τους int ενός array σε NULL είναι το ίδιο με το να θέτεις τη τιμή ως 0;
migf1 Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Έτσι είναι όντως (και δεν νομίζω να μπορεί να αλλάξει ο συγκεκριμένος κανόνας). Το πρόβλημα όμως δεν είναι ότι στην memset βάζεις 0 και όχι (void *)0. Το NULL είναι όντως implementation dependent όπως είπες χωρίς όμως να μπορεί να πάρει ό,τι τιμές θέλει ο implementor αλλά πρέπει να οριστεί ως "Null Pointer Constant". Ως NPC ορίζεται το (void *)0 ή οποιαδήποτε ICE (Integer Constant Exp<b></b>ression) έχει τιμή 0. Δηλαδή μπορεί να έχει τιμή (void *)0, 0, (int 0), (long) 0, κτλ αλλά οπωσδήποτε μία από αυτές. Το implementation-defined κομμάτι του NULL σημαίνει ότι μπορείς να επιλέξεις οποιαδήποτε από τις παραπάνω τιμές θέλεις. Γιατί τώρα μας δημιουργεί πρόβλημα η memset και η calloc. > int *p = 0; int k = 0; int *q = k; Ο δείκτης q ΔΕΝ είναι NULL pointer γιατί ενώ μεν του θέτουμε την τιμή 0, ΔΕΝ χρησιμοποιούμε Integer Constant Exp<b></b>ression άρα δεν έχουμε Null Pointer Constant. Είναι ευθύνη του compiler να θέτει στο δείκτη τη σωστή διεύθυνση μόνο όποτε βλέπει NPC. Αν λοιπόν έχουμε μια πλατφόρμα στην οποία η διεύθυνση ενός NULL pointer είναι το 17236, τότε ο compiler θα δώσει στον δείκτη p την σωστή τιμή 17236 ενώ ο δείκτης q θα δείχνει λανθασμένα στην διεύθυνση 0. Αυτό είναι και το πρόβλημα της memset και της calloc γιατί χρησιμοποιούν κάποια μεταβλητή και όχι απευθείας την τιμή 0. Θα μπορούσε η memset να έχει ειδική μέριμνα για την περίπτωση του μηδενός αλλά δεν βλέπω καμμία libc να το κάνει. Η calloc υλοποιείται με κάλεσμα της memset (τουλάχιστον σε Free,Net BSD) οπότε δεν εγγυάται ούτε αυτή Δεν είναι απαραίτητο να ορίζεται ως 0-bits το NULL, δες cfaq-5.17. Ίσως όμως να έχει αλλάξει αυτό σε μεταγενέστερα πρότυπα, δεν το έχω παρακολουθήσει. Άρα με βάση αυτό, όταν αρχικοποιείς όλους τους int ενός array σε NULL είναι το ίδιο με το να θέτεις τη τιμή ως 0; Θεωρητικά όχι. Στην πράξη όμως ναι (μιας και πρέπει να είναι πολύ εξωτική η πλατφόρμα για να μην είναι ορισμένο σε 0-bits το NULL). EDIT: Α, και σε C θα σου βγάλει warning ο compiler, either way. Στην C++ ορίζεται ως σκέτο 0 το NULL (νομίζω).
imitheos Δημοσ. 24 Νοεμβρίου 2012 Δημοσ. 24 Νοεμβρίου 2012 Άρα με βάση αυτό, όταν αρχικοποιείς όλους τους int ενός array σε NULL είναι το ίδιο με το να θέτεις τη τιμή ως 0; Το NULL υπάρχει για pointer contexts και όχι για να θέτεις μηδέν σε ένα απλό int. Όπως είπε ο migf1, στην C++ που είναι ορισμένο σαν 0 μπορείς να το κάνεις ενώ στην C θα σου βαρέσει error λόγω του ορισμού του ως (void *). Ανεξάρτητα όμως από τον ορισμό του, δεν έχει νόημα να βάζουμε NULL σε μη-δείκτες. Δεν είναι απαραίτητο να ορίζεται ως 0-bits το NULL, δες cfaq-5.17. Ίσως όμως να έχει αλλάξει αυτό σε μεταγενέστερα πρότυπα, δεν το έχω παρακολουθήσει. Φυσικά και δεν είναι απαραίτητο. Αυτό δεν περιέγραψα και εγώ ? Το 0 που θέτουμε σε ένα δείκτη δεν σημαίνει τον αριθμό με όλα τα bits 0 αλλά είναι ένδειξη στον compiler ότι πρέπει να τοποθετήσει την τιμή που πρέπει ώστε ο δείκτης να είναι NULL. Για αυτό ανέφερα το παράδειγμα με την πλατφόρμα όπου έχουμε 17236 για διεύθυνση NULL. Για αυτό πρέπει να έχουμε το 0 σε constant μορφή. Στη 2η περίπτωση με τον δείκτη q γίνεται αυτό που λες και ο q παίρνει ως τιμή όλα τα bits 0 επειδή δεν έχουμε constant expression. Edit: Γνωρίζω και σέβομαι τον κόπο και την προσπάθεια που κάνουν τα παιδιά που διατηρούν το φόρουμ και επίσης κατανοώ ότι χρησιμοποιούμε δωρεάν το φόρουμ οπότε δεν έχω δικαίωμα να έχω "απαιτήσεις" αλλά ρε παιδιά κάνετε κάτι για τον editor.
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα