Τα πάντα για την C

...του ubuntu και έργων ΕΛ/ΛΑΚ (Έργα-Οδηγοί-Προτάσεις)

Συντονιστής: konnn

Re: Τα πάντα για την C

Δημοσίευσηαπό simosx » 02 Απρ 2012, 17:44

stamatiou έγραψε:Δηλαδή να το κάνω σειριακά;


Εννοείς «με ανάγνωση όλου του αρχείου στη μνήμη και τοποθέτηση σε πίνακα».
Πιστεύω ότι η εκφώνηση σε καθοδηγεί σε αυτό τον τρόπο, και έχοντας όλα τα δεδομένα σε ένα πίνακα μπορείς να ολοκληρώσεις εύκολα την αναζήτηση των ζευγαριών.
Όπως το βλέπω, δίχως τα δεδομένα σε πίνακα για άμεση προσπέλαση, θα πάρει αρκετή ώρα για να ολοκληρώσεις έναν πίνακα 1εκ τιμών.
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό stamatiou » 02 Απρ 2012, 17:52

simosx έγραψε:
stamatiou έγραψε:Δηλαδή να το κάνω σειριακά;


Εννοείς «με ανάγνωση όλου του αρχείου στη μνήμη και τοποθέτηση σε πίνακα».
Πιστεύω ότι η εκφώνηση σε καθοδηγεί σε αυτό τον τρόπο, και έχοντας όλα τα δεδομένα σε ένα πίνακα μπορείς να ολοκληρώσεις εύκολα την αναζήτηση των ζευγαριών.
Όπως το βλέπω, δίχως τα δεδομένα σε πίνακα για άμεση προσπέλαση, θα πάρει αρκετή ώρα για να ολοκληρώσεις έναν πίνακα 1εκ τιμών.

Ναι αλλά πιο γρήγορα δεν θα γίνει η δουλειά αν δε διαβάσω ολόκληρο το αρχείο;
1Γνώσεις→Linux: Αρχάριος┃Προγραμματισμός:Αρχάριος┃Αγγλικά:Μέτριος
2Λειτουργικό→Arch Linxu 32bit
3Προδιαγραφές→2x AMD AthlonX2 DualCore QL-66 ‖ RAM 1751 MiB ‖ Hewlett-Packard 308C - Hewlett-Packard Compaq 615
4Κάρτες γραφικών:ATI RS780M/RS780MN [Radeon HD 3200 Graphics][1002:9612]
5Δίκτυα:eth0:Marvell 88E8042 PCI-E Fast Ethernet Controller [11ab:4357] (rev 10)⋮eth1: Broadcom BCM4312 802.11b/g LP-PHY [14e4:4315](rev 01)
Πρωσοπική Ιστοσελίδα: http://giwrg98.co.cc
Άβαταρ μέλους
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό simosx » 02 Απρ 2012, 19:31

stamatiou έγραψε:
simosx έγραψε:
stamatiou έγραψε:Δηλαδή να το κάνω σειριακά;


Εννοείς «με ανάγνωση όλου του αρχείου στη μνήμη και τοποθέτηση σε πίνακα».
Πιστεύω ότι η εκφώνηση σε καθοδηγεί σε αυτό τον τρόπο, και έχοντας όλα τα δεδομένα σε ένα πίνακα μπορείς να ολοκληρώσεις εύκολα την αναζήτηση των ζευγαριών.
Όπως το βλέπω, δίχως τα δεδομένα σε πίνακα για άμεση προσπέλαση, θα πάρει αρκετή ώρα για να ολοκληρώσεις έναν πίνακα 1εκ τιμών.

Ναι αλλά πιο γρήγορα δεν θα γίνει η δουλειά αν δε διαβάσω ολόκληρο το αρχείο;


Για τη δουλειά που θέλεις να κάνεις, θα χρειαστεί να πηγαίνεις πίσω-εμπρός στα δεδομένα του αρχείου, ιδίως όταν τα ζευγάρια δεν είναι συνεχόμενα.
Δες για παραδειγμα,
Κώδικας: Επιλογή όλων
-10 -8 -7 -2 0 2 10

ή
Κώδικας: Επιλογή όλων
-10 -2 0 2 7 8 10


Αυτό που μπορώ να φανταστώ είναι ότι έχεις δύο μετρητές που διατρέχουν τον πίνακα με τις τιμές.
Ξεκινούν από τη τιμή που είναι πιο κοντά στο 0 και ακολουθούν αντίθετη κατεύθυνση μεταξύ τους.
Καθώς προχωρούν σε αντίθετη κατεύθυνση, ελέγχουν αν υπάρχει ζευγάρι. Ανάλογα με τη τιμή στον πίνακα, μπορεί να πηγαίνουν στο επόμενο ή να περιμένει ο ένας μετρητής τον άλλο ώστε να έχουν παρόμοιο απόλυτη τιμή.
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό stamatiou » 02 Απρ 2012, 20:58

Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....
1Γνώσεις→Linux: Αρχάριος┃Προγραμματισμός:Αρχάριος┃Αγγλικά:Μέτριος
2Λειτουργικό→Arch Linxu 32bit
3Προδιαγραφές→2x AMD AthlonX2 DualCore QL-66 ‖ RAM 1751 MiB ‖ Hewlett-Packard 308C - Hewlett-Packard Compaq 615
4Κάρτες γραφικών:ATI RS780M/RS780MN [Radeon HD 3200 Graphics][1002:9612]
5Δίκτυα:eth0:Marvell 88E8042 PCI-E Fast Ethernet Controller [11ab:4357] (rev 10)⋮eth1: Broadcom BCM4312 802.11b/g LP-PHY [14e4:4315](rev 01)
Πρωσοπική Ιστοσελίδα: http://giwrg98.co.cc
Άβαταρ μέλους
stamatiou
daemonTUX
daemonTUX
 
Δημοσιεύσεις: 947
Εγγραφή: 25 Ιουν 2010, 20:23
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 02 Απρ 2012, 23:35

Ilias95 έγραψε:
Μπορείς να δώσεις ένα παράδειγμα για το πως θα γίνει το tokenization αλλιώς;

Εννοώ απευθείας μέτρημα των στοιχείων που θέλεις (γραμμές, λέξεις, χαρακτήρες) καθώς διαβάζεις το αρχείο, κάτι σαν κι αυτό...

Μορφοποιημένος Κώδικας: Επιλογή όλων
typedef struct Count {
uintmax_t nl; /* newlines count */
uintmax_t w; /* words count */
uintmax_t c, b; /* chars & bytes count */
uintmax_t maxlnlen; /* length of maximum line */
}Count;
...
Count count;
int c;
bool onword = false;
uintmax_t lnchars = 0;

memset( count, 0, sizeof(Count) );
onword = (c=isspace( getc(fp) )) ? false : true;
ungetc(c, fp);
while ( (c=getc(fp)) != EOF )
{
if ( isspace(c) )
{
if ( '\n' == c ) {
count->nl++;
if (count->maxlnlen < --lnchars)
count->maxlnlen = lnchars;
lnchars = 0;
if ( onword ) {
count->w++;
onword = false;
}
}
else if ( onword ) {
count->w++;
onword = false;
}
}
else
onword = true;

if ( c != '\n')
lnchars++;
count->c++;
}

count->b = count->c / sizeof(char);
...


Btw, μόλις είδα πως το mywc δουλεύει μονάχα με ένα αρχείο, ενώ το wc με όσα και να του περάσεις στη γραμμή εντολών (και τα αθροίζει στο τέλος).

ΥΓ. buffer λέμε γενικώς τα arrays που χρησιμοποιούμε για προσωρινή αποθήκευση/διαχείριση
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό Ilias95 » 02 Απρ 2012, 23:43

Θα δω αργότερα (και) αυτόν τον κώδικα γιατί και εδώ έχω άγνωστα στοιχεία (όπως structures και έναν τελεστή "->" που πήρε το μάτι μου).

Πάντως και εγώ αν προσέξεις καθώς διαβάζω το αρχείο κάνω και μέτρημα των στοιχείων πλην των word counts.
Το τελευταίο δεν μου ήρθε κάποιος τρόπος να το κάνω ενώ διάβαζα το αρχείο, έτσι χρησιμοποίησα το text buffer και ύστερα το έκανα tokenize.

migf1 έγραψε:Btw, μόλις είδα πως το mywc δουλεύει μονάχα με ένα αρχείο, ενώ το wc με όσα και να του περάσεις στη γραμμή εντολών (και τα αθροίζει στο τέλος).

Indeed, επικεντρώθηκα περισσότερο στην λειτουργία του προγράμματος. Δεν είναι κάτι δύσκολο όμως. :)
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 02 Απρ 2012, 23:51

Ναι, το είδα πως το κάνεις μόνο με για τις λέξεις ;)

Όσο για το struct και το ->, δεν είναι τίποτα... απλά αντί να τις έχω χύμα τις μεταβλητές, τις έχω βάλει μέσα σε ένα struct (οπότε αν χρειαστεί να περαστούν σε κάποια συνάρτηση να μπορεί να περαστεί μονάχα το struct ως όρισμα, αντί για όλες αυτές οι μεταβλητές)
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό simosx » 02 Απρ 2012, 23:59

stamatiou έγραψε:Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....


Υπάρχουν αρκετές επιλογές όταν έχεις όλη τη λίστα των αριθμών σε έναν πίνακα.
Τι θα επέλεγες για να επιλύσεις το πρόβλημα, έχοντας όλους τους αριθμούς σε ένα πίνακα;
προσωπικό ιστολόγιο ϗ πλανήτης Ubuntu-gr
Συμβάλετε και εσείς στο ελληνικό βιβλίο Ubuntu!
1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 13.10 saucy 3.11.0-031100rc1-generic 64bit (el_GR.UTF-8, Unity ubuntu)
3 AMD E-450 APU with Radeon HD Graphics ‖ RAM 3555 MiB ‖ Sony Corporation VAIO
4 AMD nee ATI Wrestler [Radeon HD 6320] [1002:9806] {fglrx_pci}
5 eth0: Atheros Inc. AR8151 v2.0 Gigabit Ethernet [1969:1083] (rev c0) ⋮ wlan0: Atheros Inc. AR9285 [168c:002b] (rev 01)
Φτιάξτε και εσείς τη δική σας υπογραφή (παραπάνω κείμενο) αυτόματα με κλικ εδώ!
simosx
Επίτιμο μέλος
Επίτιμο μέλος
 
Δημοσιεύσεις: 10334
Εγγραφή: 11 Μάιος 2008, 18:52
Launchpad: simosx
IRC: simosx
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 03 Απρ 2012, 01:13

Λοιπόν, έκανα και εγώ μια γρήγορη υλοποίηση, που λειτουργικά είναι νομίζω αρκετά πιστή με αυτή του αυθεντικού. Δεν την δοκίμασα εξαντλητικά, οπότε μπορεί να περιέχει bugs.

http://ideone.com/1oMC1

Τα options τα έχω σε έναν ομώνυμο πίνακα στην main(), με την κάθε γραμμή του να αντιστοιχεί σε ένα option και τον enumerator OptionId να περιέχει τα indicies του πίνακα.

Το καθένα από τα options εκτός από την short & long εντολή του (sstr & lstr), και την περιγραφή του (desc), έχει κι ένα bitflag (obit) που το χρησιμοποιώ για να δηλώσω πως είναι ενεργοποιημένο το συγκεκριμένο option.

Η μεταβλητή obitmap στην main() αποτελείται από 2 bytes (uint16_t) εκ των οποίων χρησιμοποιώ μονάχα το ένα (το άλλο είναι άδειο, αν χρειαστεί να μπουν κι άλλα options). Την ξεκινάω με μηδενική τιμή και για κάθε option που καθορίζει ο χρήστης στη γραμμή εντολών ανάβω το κατάλληλο bit μέσα σε αυτή την μεταβλητή. Αυτό το κάνει συνάρτηση parse_cmdln_args() οπότε μόλις τελειώσει, η μεταβλητή obitmap έχει αναμμένα μονάχα τα bits που αντιστοιχούν στα activated options.

Η parse_cmdln_args() ενημερώνει επίσης έναν πίνακα από δείκτες (fnames) που δείχνουν μονάχα σε όσα argv[ i ] περιέχουν ονόματα αρχείων στη γραμμή εντολών. Ενημερώνει επίσης το πλήθος αυτών των filenames που βρήκε στη γραμμή εντολών (nfiles). Στην αρχή του προγράμματος έχω βάλει όριο μέχρι 100 filenames (+1 γιατί τον τελευταίο δείκτη τον θέλω πάντα NULL).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Τα πάντα για την C

Δημοσίευσηαπό migf1 » 03 Απρ 2012, 13:20

stamatiou έγραψε:Δηλαδή να έχω έναν μετρητή i στην αρχή του πίνακα και ένα στο τέλος του πίνακακαι να μετράνε και οι 2 προς το κέντρο; Δεν πολυκαταλαβαίνω το τρόπο λύσης....

Αυτό που είπε ο Σίμος είναι και η δική μου άποψη: http://ideone.com/Oq8aL

Το δοκίμασα μονάχα με τα παραδείγματα εισόδου της εκφώνησης. Το αρχείο input που δίνει, σε εμένα σε Windows το δείχνει ως binary. Κάνε δοκιμές χρόνου, κλπ και φτιάξε το να τυπώνει το αποτέλεσμα σε αρχείο (απενεργοποίησε και την buffer_print() για να μη σου τυπώσει 1.000.000 νούμερα).
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

ΠροηγούμενηΕπόμενο

Επιστροφή στο Ανάπτυξη Λογισμικού / Αλγόριθμοι