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

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

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

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

Δημοσίευσηαπό migf1 » 06 Απρ 2012, 22:31

Γεια σου, Ηλία!

Παίζει να είναι στο top-3 των πιο χρήσιμων κεφαλαίων αυτό με τα struct/union/enums :) Είναι η βάση για HL programming με C.

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

Μορφοποιημένος Κώδικας: Επιλογή όλων
/*********************************************************************
* days_of_month: Returns the number of days in a month. *
*********************************************************************/
int days_of_month(int month, int year) {
if (month == FEBRUARY && is_leap(year))
return 29;
if (month == FEBRUARY)
return 28;
return month % 2 ? 31 : 30;
}

πρέπει να βγάζει σφάλμα στον Ιούλιο (γιατί παρότι μονός έχει 31 ημέρες ;) )

Άσχετα με το παραπάνω, σε προγράμματα με μήνες συνηθίζονται υλοποιήσεις με έναν πίνακα για τις ημέρες όλων των μηνών (συνδυασμένο με έναν enumerator για να τον κάνεις απευθείας indexing, αλλά για τη συγκεκριμένη συνάρτηση αρκεί απλά ένα: #define FEB 1)...

Μορφοποιημένος Κώδικας: Επιλογή όλων
enum { JAN=0, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Οπότε αμέσως-αμέσως...
Μορφοποιημένος Κώδικας: Επιλογή όλων
int days_in_month( int m, int y, int mdays[] )
{
return FEB == (--m) && Y_ISLEAP(y) ? 29 : mdays[ m ];
}

* το --m είναι επειδή σε αυτά τα προγράμματα ο χρήστης δίνει τους μήνες ως 1-indexed νούμερα, ενώ εσωτερικά τους μετατρέπουμε σε 0-indexed, για να κάνουμε indexing τον πίνακα (μπορείς την μετατροπή να την κάνεις έξω από τη συνάρτηση, οπότε δεν θα το χρειάζεσαι μέσα της).

Στην συγκεκριμένη εκφώνηση, για να μείνεις πιστός στο πρότυπο της συνάρτησης, ο mdays[] μπορεί να οριστεί καθολικά (αλλά γενικώς είναι καλό να τις αποφεύγουμε τις καθολικές μεταβλητές).
Τελευταία επεξεργασία από migf1 και 07 Απρ 2012, 09:27, έχει επεξεργασθεί 1 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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

Ευχαριστώ πολύ για τα tips.
Θα κάνω διάφορες διορθώσεις στον κώδικα και θα τον ξανά ποστάρω.

Σχετικά με την days_of_month() έχεις δίκιο, ξέχασα τελείως ότι μετά από κάποια στιγμή αλλάζει το πράγμα. :lol:
Το επαλήθευσα με τον "κανόνα" του αριστερού χεριού! :P :lol:
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

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

Ilias95 έγραψε:Ευχαριστώ πολύ για τα tips.
Θα κάνω διάφορες διορθώσεις στον κώδικα και θα τον ξανά ποστάρω.

Don't mention it :)

Ένα άλλο πολύ (πολύ) χρήσιμο tip για πράξεις σε ημερομηνίες, είναι η μετατροπή τους σε Julian Day Numbers: http://www.hermetic.ch/cal_stud/jdn.htm

Δεν χρειάζεται να πήξεις διαβάζοντας όλο αυτό το μαρκινάρι, κράτα μονάχα τους 2 αλγόριθμους μετατροπής στο τέλος: http://www.hermetic.ch/cal_stud/jdn.htm#comp

Ο ένας μετατρέπει μια (Γρηγοριανή) ημερομηνία σε julian-day-number και ο άλλος μετατρέπει ένα julian-day-number σε (Γρηγοριανή) ημερομηνία... Γρηγοριανές είναι οι ημερομηνίες που χρησιμοποιούμε.

Ούτε αυτούς χρειάζεται να καταλάβεις πως και γιατί δουλεύουν, απλά χρησιμοποίησέ τους (έχουν κάποιο εύρος έγκυρων αποτελεσμάτων, από το 1461 και μετά νομίζω, αν και για πιο σίγουρα από το 1582 και μετά.

Το ρεζουμέ είναι πως αντί να φτιάχνεις loops από τον τάδε μήνα έως τον δείνα, με if isleap() κλπ, κλπ, απλά μετατρέπεις τις 2 ημερομηνίες σου σε jdn και τα αφαιρείς :)

ΥΓ. Αν σε ενδιαφέρει το θέμα, μπορείς να δεις και τον κώδικα του "dates" που έχω στο site μου, με πλήρη σχόλια καθώς και online τεκμηρίωση (στα Αγγλικά). Υπάρχουν τέτοιοι "μαγικοί" αλγόριθμοι και για άλλες δουλειές, π.χ. για να βρίσκεις την ημέρα της εβδομάδας (weekday) μιας οποιαδήποτε ημερομηνίας, αν και συνήθως αρκεί να μετατρέψεις την ημερομηνία σε jdn, και μετά να κάνεις ένα jdn % 7.
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

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

Btw, για μια σύντομη περίληψη περί Γρηγοριανών Ημερομηνιών, δες εδώ: http://x-karagiannis.gr/prog/libs/conte ... html#Intro
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό Ilias95 » 07 Απρ 2012, 13:22

Ανανέωσα τον κώδικα κάνοντας χρήση του πίνακα με τις ημέρες ανά μήνα, και χρησιμοποιώντας την μετατροπή σε Julian Day Numbers: https://github.com/Ilias95/C-Exercises/ ... 16/ex_05.c
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

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

Είσαι δυνατός παίκτης! :)

Να σου πω κι άλλο ένα τρικάκι, για το compare... επειδή συνήθως δεν μας ενδιαφέρει να είναι ακριβώς -1 ή 1 το αποτέλεσμα, αλλά μας αρκεί να είναι αρνητικό όταν ο 1ος αριθμός είναι μικρότερος του 2ου, θετικό αν είναι ανάποδα ή 0 αν είναι ίσα, τότε επειδή τα jdn είναι πάντα θετικοί αριθμοί, η compare γίνεται μια απλή αφαίρεση...

Μορφοποιημένος Κώδικας: Επιλογή όλων
compare_dates( struct date d1, struct date d2 )
{
return to_julian(d1) - to_julian(d2);
}
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

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

Δημοσίευσηαπό pc_magas » 07 Απρ 2012, 14:12

Άν είναι μια απλή αφαίρεση τότε μπορεί αντί για συνάρτηση να μπεί macro ;)
My blog|Κυπριακή Κοινότητα Ελευθέρου Λογισμικού Λογισμικού ανοικτού Κώδικα
Γνώσεις Linux:Ποτέ αρκετές|Προγραμματισμός: Php, javascript, nodejs, python, bash |Aγγλικά:Καλά
Οι υπολογιστές μου:
Spoiler: show
Ubuntu 16.04 64 bit σεIntel(R) Pentium(R) CPU G4400 @ 3.30GHz, 16Gib Ram, 500Gib Hard Disk, και κάρτα γραφικών Nvidia Geforce GT610
Lubuntu 14.04 σε Dell Inspiron mini 10(1010) intel Atom Z500 1Gb ram και gma500 (εδώθη σε άλλον)
Kubuntu 16.04 Lenovo G70 Intel i5 Nvidia Grapgics Card, Intel Graphics card (έχει 2) με Nouveau, 16Gb RAM, 126GB SSD Σκληρό Δίσκο
Άβαταρ μέλους
pc_magas
powerTUX
powerTUX
 
Δημοσιεύσεις: 2599
Εγγραφή: 12 Απρ 2009, 18:55
Τοποθεσία: Αχαρναί Αττικής
Launchpad: pc_magas
IRC: pc_magas
Εκτύπωση

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

Δημοσίευσηαπό Ilias95 » 07 Απρ 2012, 14:19

Έξυπνο. Το συμπλήρωσα.

pc_magas έγραψε:Άν είναι μια απλή αφαίρεση τότε μπορεί αντί για συνάρτηση να μπεί macro ;)

Νομίζω ότι είναι καλύτερα να μείνει συνάρτηση, γιατί τα ορίσματα είναι structures, η return value enumeration και τα macros δεν ελέγχουν τα ορίσματα που τους περνάς.
Ilias95
saintTUX
saintTUX
 
Δημοσιεύσεις: 1548
Εγγραφή: 29 Απρ 2011, 23:26
Εκτύπωση

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

Δημοσίευσηαπό migf1 » 07 Απρ 2012, 14:29

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

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

Δημοσίευσηαπό migf1 » 07 Απρ 2012, 14:33

Ilias95 έγραψε:Έξυπνο. Το συμπλήρωσα.


:)

Κοίτα και κάτι ακόμα πιο έξυπνο, που δουλεύει ανεξαρτήτως προσήμου των 2 αριθμών...

Μορφοποιημένος Κώδικας: Επιλογή όλων
compare_int( int n1, n2 )
{
return (n1 > n2) - (n1 < n2);
}


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

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

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