ANSI C: Παράδειγμα Διαχείρισης Ημερομηνιών

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

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

ANSI C: Παράδειγμα Διαχείρισης Ημερομηνιών

Δημοσίευσηαπό migf1 » 14 Ιουν 2011, 04:59

Με αφορμή αυτό το νήμα πριν από μερικές ημέρες, έφτιαξα σήμερα ένα μικρό πρόγραμμα που κάνει μερικούς υπολογισμούς μεταξύ 2 ημερομηνιών του Γρηγοριανού Ημερολογίου (από τις 15 Οκτ 1752 έως τις 31 Δεκ 9999).

Sample Output #1
Sample Output #2
Sample Output #3

έγραψε:
Βελτιώσεις στη V3.65 (το πρόγραμμα έχει πλέον δική του σελίδα: http://x-karagiannis.gr/prog/libs/conte ... /dates.php)
  • διεύρυνση του κάτω ορίου στο ημερολόγιο, από 14 Σεπ 1752 σε 15 Οκτ 1582
  • δυνατότητα τυπώματος ετήσιου ημερολογίου είτε στην οθόνη είτε σε αρχείο κειμένου που καθορίζει ο χρήστης
  • αλλαγή όλων των σχολίων του κώδικα σε μορφή αναγνωρίσιμη από το Doxygen
  • δημιουργία πλήρους τεκμηρίωσης στα Αγγλικά, τόσο για τον κώδικα όσο και για το πρόγραμμα

http://forum.ubuntu-gr.org/viewtopic.ph ... 05#p226905


έγραψε:
Βελτιώσεις στη V3.6 (το πρόγραμμα έχει πλέον δική του σελίδα: http://x-karagiannis.gr/prog/libs/conte ... /dates.php)
  • αναθεώρηση της αρχιτεκτονικής του κώδικα
  • πλήρης συμβατότητα του κώδικα με το πρότυπο ANSI/C89
  • ένδειξη σημερινής ημέρας στα ημερολόγια
  • δυνατότητα εξόδου μετά την παραγωγή ετήσιου ημερολογίου στη γραμμή εντολών


έγραψε:
Βελτιώσεις στη V3.5 (κώδικας και σύνδεσμος κατεβάσματος στο τέλος της δημοσίευσης)
  • αποθήκευση ετήσιων ημερολογίων σε αρχεία κειμένου: "calΕΤΟΣ.txt", περνώντας το έτος ως command line argument.
Σημειώσεις Υλοποίησης:

Αν το εκτελέσιμο ονομάζεται "dates", τότε πληκτρολογώντας στη γραμμή εντολών:
Κώδικας: Επιλογή όλων

dates 2011
θα δημιουργηθεί το αρχείο: cal2011.txt που θα περιέχει το ετήσιο ημερολόγιο του 2011

Έτη μικρότερα του 1752 προσαρμόζονται αυτόματα στο έτος 1752, ομοίως έτη μεγαλύτερα του 9999 προσαρμόζονται αυτόματα στο έτος 9999.

Η συνάρτηση που ασχολείται με τα command line arguments είναι η...
Κώδικας: Επιλογή όλων
void do_cmlargs(char *argv[], Date calstart, Date calend, int mdays[], char *mnames[], char *dnames[] )

η οποία καλείται στη αρχή της main(). Μετατρέπει το string argv[1] σε long, το ελέγχει να μην ξεπερνάει τα όρια του ημερολογίου, χρησιμοποιώντας την συνάρτηση:
Κώδικας: Επιλογή όλων
int date_compare( Date date1, Date date2 )

Κατόπιν δημιουργεί το αρχείο κειμένου και τυπώνει μέσα του το ετήσιο ημερολόγιο, μέσω της συνάρτησης:
Κώδικας: Επιλογή όλων
void fprint_calyear( Date date, int mdays[], char *mnames[], char *dnames[], FILE *fp )


Έφτιαξα επίσης τις παρακάτω συναρτήσεις για να γίνουν νοηματικά πιο κατανοητοί κάποιοι έλεγχοι σε διάφορα σημεία του προγράμματος (δείτε τα σχόλιά τους στον κώδικα για περισσότερες λεπτομέρειες):
Κώδικας: Επιλογή όλων

bool date_dayinbounds( Date date, int mdays[] );
bool date_inbounds( Date date, Date calstart, Date calend);

Βελτιώσεις στη V3 (κώδικας και σύνδεσμος κατεβάσματος στο τέλος της δημοσίευσης)
  • εμφάνιση μηνιαίων ημερολογίων για τις 2 ημερομηνίες (ή ενός αν αναφέρονται στον ίδιο μήνα)
Σημειώσεις Υλοποίησης:

Προστέθηκε η συνάρτηση:
Κώδικας: Επιλογή όλων

void print_calmonth(Date date, int mdays[], char *mnames[], char *dnames[] );
που εμφανίζει στην οθόνη το μηνιαίο ημερολόγιο του ορίσματος date. Χρησιμοποιείται στην main() μαζί με έλεγχο ώστε να μην καλείται δυο φορές όταν οι 2 ημερομηνίες αναφέρονται στον ίδιο μήνα.

Προστέθηκε επίσης η γενική συνάρτηση διαχείρισης string:
Κώδικας: Επιλογή όλων

char *s_strip(char *s, const char *del);
η οποία αφαιρεί από το string s οποιονδήποτε χαρακτήρα βρίσκεται μέσα στο string del. Χρησιμοποιείται στη συνάρτηση date_getoperation() με κενούς χαρακτήρες στο del (space και tab) πριν γίνει η μετατροπή της εισόδου από string σε long int, ώστε ακόμα κι αν ο χρήστης γράψει π.χ. "+ 2 1 65 9" θα εκληφθεί ως: "+21659". Σημειώστε πως η s_strip() διαφέρει από την s_trim() (π.χ. η πρώτη αφαιρεί κι ενδιάμεσα κενά, ενώ η δεύτερη μόνο όσα βρίσκονται στην αρχή και στο τέλος).

Τέλος, απλώς αλλάχτηκε το όνομα της συνάρτησης print_results() σε print_diffs()

Βελτιώσεις στη V2 (κώδικας και σύνδεσμος κατεβάσματος στο τέλος της δημοσίευσης)
  • προσθαφαίρεση οποιουδήποτε αριθμού ημερών στην 1η ημερομηνία (αντί για 2η ημερομηνία, γράψτε π.χ. +200 ή -3000)
  • εμφάνιση του Ιουλιανού αριθμού (Julian Day Number) για την κάθε ημερομηνία στα αποτελέσματα
  • εμφάνιση των οδηγιών όταν ο χρήστης επιλέξει να δώσει νέες ημερομηνίες)
Σημειώσεις Υλοποίησης:

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

Εν συντομία, προστέθηκε η συνάρτηση:
Κώδικας: Επιλογή όλων

bool date_getoperation( Date *date, char *inbuf );

η οποία μετατρέπει το string εισόδου σε long int, και χρησιμοποιείται μέσα στην συνάρτηση:
Κώδικας: Επιλογή όλων
bool date_askuser( int id, char *prompt, Date *date, int max_inbuf, int mdays[], Date calstart, Date calend )
που με τη σειρά της έχει αλλαχτεί αφενός να επιστρέφει boolean κι αφετέρου να δέχεται ένα επιπλέον όρισμα, το id, ώστε να ξέρουμε αν διαβάζουμε την 1η ή την 2η ημερομηνία. Αν διαβάζουμε την 2η, τότε της "επιτρέπουμε" αντί για νορμάλ ημερομηνία να διαβάσει έναν signed long int, τον οποίον τον αποθηκεύουμε στο πεδίο: d της μεταβλητής date, προτού την επιστρέψουμε στην main(), παράλληλα με την τιμή TRUE στην επιστροφή της συνάρτησης αυτής κάθε αυτής.

H main() με τη σειρά της εξετάζει την τιμή επιστροφής της date_askuser() για την 2η ημερομηνία και αν είναι TRUE σημαίνει πως η date2 αντί για κανονική ημερομηνία περιέχει πράξη. Σε αυτή την περίπτωση ο αριθμός της πράξης είναι ήδη αποθηκευμένος στο πεδίο: date2.d οπότε καλεί την συνάρτηση: date_plusdays() για να προσθέσει τις ημέρες που βρίσκονται στο date2.d (+ ή -) στην date1 και να αποθηκεύσει το αποτέλεσμα σε μορφή κανονικής πια ημερομηνίας μέσα στη μεταβλητή date2.

Αν το αποτέλεσμα της πράξης βγαίνει εκτός ορίων του ημερολογίου, τότε στη date2 εκχωρείται το όριο (είτε το πάνω, είτε το κάτω, ανάλογα με το ποιο πήγε να... παραβιαστεί.

Υπάρχουν και σχετικά σχόλια μέσα στον κώδικα (στα Αγγλικά).


Το πρόγραμμα διαβάζει από τον χρήστη 2 ημερομηνίες και κατόπιν υπολογίζει:
  • την ημέρα της εβδομάδας για την καθεμιά τους
  • το αν κάποια από αυτές βρίσκεται σε δίσεκτο έτος
  • ποια είναι η διαφορά τους σε ημέρες
  • ποια είναι η διαφορά τους σε μορφή: μέρες, μήνες, χρόνια.
  • EDIT: V2
  • σε ποιον Ιουλιανό αριθμό αντιστοιχούν (Julian Day Number)
  • EDIT: V3
  • εμφάνιση μηνιαίων ημερολογίων για τις 2 ημερομηνίες (ή ενός αν αναφέρονται στον ίδιο μήνα)
  • EDIT: V3.5
  • δημιουργία αρχείων κειμένου με ετήσια ημερολόγια, περνώντας το έτος ως command line argument στη γραμμή εντολών
Εκτός από τον κλασικό τρόπο εισαγωγής των 2 ημερομηνιών, "καταλαβαίνει" επίσης τις εξής λέξεις (mnemonics):
  • start
  • end
  • today
  • yesterday
  • tomorrow
  • EDIT: V2
  • οποιονδήποτε αριθμό με πρόσημο
τις οποίες μετατρέπει αυτόματα σε έγκυρες ημερομηνίες, είτε διαβάζοντας το ρολόι του συστήματος για τις 3 προτελευταίες, είτε αναθέτοντας το κάτω και το πάνω όριο του ημερολογίου στις 2 πρώτες, είτε προσθαφαιρώντας μέρες στην 1η ημερομηνία.

EDIT: V3.5: πληκτρολογώντας στη γραμμή εντολών ένα έτος μετά το όνομα του προγράμματος (command line argument) δημιουργείται αρχείο κειμένου που περιέχει το ετήσιο ημερολόγιο του έτους αυτού.

Κατά την εισαγωγή της κάθε ημερομηνίας κάνει real-time ελέγχους εγκυρότητας. Σε περίπτωση σφάλματος, αφού πρώτα ενημερώσει τον χρήστη, τον προτρέπει συνεχώς για νέο input μέχρι να εισαγάγει έγκυρη ημερομηνία ή κάποιο από τα παραπάνω mnemonics.

Η συνάρτηση που κάνει όλη τη... βρώμικη δουλειά με τους ελέγχους εγκυρότητας στο διάβασμα των ημερομηνιών είναι η:
Κώδικας: Επιλογή όλων
void date_askuser( char *prompt, Date *date, int max_inbuf, int mdays[] );

η οποία μεταξύ άλλων χρησιμοποιεί την:
Κώδικας: Επιλογή όλων
bool date_getmnemonic( Date *date, char *inbuf, const Date calstart, const Date calend );
ειδικά για το διάβασμα των mnemonics.

Για τον υπολογισμό της διαφοράς των 2 ημερομηνιών εκφρασμένης σε ημέρες, όπως και για τον υπολογισμό της ημέρας της εβδομάδας για την καθεμιά τους, οι ημερομηνίες μετατρέπονται σε Ιουλιανούς αριθμούς (Julian Day Numbers) με τη συνάρτηση:
Κώδικας: Επιλογή όλων
long date_2jdn( Date date );

η οποία έχει και το... αντίστροφο ταίρι της:
Κώδικας: Επιλογή όλων
Date *jdn_2date( Date *date, long jd )

Η διαφορά εκφρασμένη σε μορφή: μέρες, μήνες, χρόνια υπολογίζεται στη συνάρτηση:
Κώδικας: Επιλογή όλων
long date_diff( Date *datediff, Date date1, Date date2, int mdays[] );
η οποία αφενός ενημερώνει το όρισμα datediff με το αποτέλεσμα του υπολογισμού, και αφετέρου επιστρέφει και η ίδια τη διαφορά εκφρασμένη ως συνολικό πλήθος ημερών.

Επίσης, υπάρχουν οι παρακάτω βοηθητικές συναρτήσεις διαχείρισης strings, οι οποίες ουσιαστικά είναι αυτόνομες και μπορούν να χρησιμοποιηθούν όπως είναι σε οποιοδήποτε πρόγραμμα χρησιμοποιεί 8-μπιτες κωδικοσελίδες χαρακτηρων ASCII...
Κώδικας: Επιλογή όλων

char *s_get(char *s, size_t len);
char *s_trim(char *s);
char *s_tolower( char *s );
int s_tokenize(char *s, char *tokens[], int maxtokens, char *delimiters);
διαβάστε τα σχόλια στον κώδικα για εξήγηση του τι κάνουν.

Ακόμα υπάρχει η συνάρτηση:
Κώδικας: Επιλογή όλων

Date *date_plusdays( Date *date, Date basedate, long ndays, Date calstart, Date calend );
που προσθέτει ημέρες σε μια ημερομηνία, επιστρέφοντας τη νέα ημερομηνία. Προς το παρόν τη χρησιμοποιώ μονάχα για τον υπολογισμό των mnemonics: yesterday και tomorrow.

Και τέλος, τα παρακάτω macros χρησιμοποιούνται για διάφορους ελέγχους εγκυρότητας...
Κώδικας: Επιλογή όλων

#define MAX_INBUF 255+1 // for our input buffer
#define INVALID -1 // just a flag for invalid d,m,y

#define validday(d) ( (d) > 0 && (d) < 32 ) // 1st validity check for days
#define validmonth(m) ( (m) > 0 && (m) < 13 ) // 1st validity check for months
#define validyear(y) ( (y) > 1751 && (y) < 10000 ) // 1st validity check for years

#define isleap(y) ( !((y) % 4) && ( (y) % 100 || !((y) % 400) ) )

Όλα τα σχόλια όπως και το πρόγραμμα τα έχω γράψει στα Αγγλικά, ελπίζω να μην υπάρχει πρόβλημα! Ο κώδικας είναι γραμμένος σε στάνταρ C οπότε λογικά γίνεται compile σε οποιαδήποτε πλατφόρμα. Να σημειώσω επίσης πως δεν χρησιμοποιώ πρότυπα συναρτήσεων, γιατί φροντίζω όλες μου οι συναρτήσεις να ορίζονται πριν χρησιμοποιηθούν (για αυτό είναι και τελευταία η main() ).

Σχόλια, απορίες, προτάσεις, επισημάνσεις, παρατηρήσεις πάντα ευπρόσδεκτα, και κυρίως bug reports :geek:

Παραθέτω τον κώδικα, αλλά επειδή το code-tag τον κάνει μαντάρα στη στοίχιση των σχολίων, μπορείτε επίσης να τον δείτε με syntax-highlighting και να τον κατεβάσετε κι από το ideone.com, στα ακόλουθα links: v3.5 ( v3, v2, v1 ).

Κώδικας: Επιλογή όλων

// -------------------------------------------------------------------------------
// DATES ver 3.5 <mig_f1@hotmail.com>
// a sample program in ANSI C performing calculations between two Gregorian dates:
// difference in days and in (d,m,y) form, weekday & leap years indicators
// jdn conversions, +/- days arithmetic, monthly calendars display
// it can also print yearly calendars in text files, naming them: "calYEAR.txt"
// by passing the year as a command line argument ( 1752-9999 )
// -------------------------------------------------------------------------------
// migf1, Athens 2011 * use at your own risk * free for whatever use * give credit
// -------------------------------------------------------------------------------
// external alogorithms:
// http://www.codeproject.com/KB/datetime/DateDurationCalculation1.aspx
// http://www.hermetic.ch/cal_stud/jdn.htm#comp

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <stdlib.h>

#define MAX_INBUF 255+1 // for our input buffer
#define INVALID -1 // just a flag for invalid d,m,y

#define validday(d) ( (d) > 0 && (d) < 32 ) // 1st validity check for days
#define validmonth(m) ( (m) > 0 && (m) < 13 ) // 1st validity check for months
#define validyear(y) ( (y) > 1751 && (y) < 10000 ) // 1st validity check for years

#define isleap(y) ( !((y) % 4) && ( (y) % 100 || !((y) % 400) ) )

#define myabs(x) ( (x) < 0 ? -(x) : (x) ) // absolute value

typedef enum bool { FALSE=0, TRUE } bool; // our custom boolean type
enum { JAN=1, FEB }; // just two month constants
enum { ID1=1, ID2 }; // to identify 1st and 2nd dates

typedef struct Date { // our date structure
long int d; // 1-31
long int m; // 1-12
long int y; // 1752-9999
} Date;

// ------------------------------------------------------------------------------------
// Read s from stdin until either len chars have been typed or ENTER has been hit,
// and null-terminate s (if ENTER was there, it is replaced).
// Return the null-terminated s
//
char *s_get(char *s, size_t len)
{
char *cp;
for (cp=s; (*cp=getc(stdin)) != '\n' && (cp-s) < len-1; cp++ )
; // for-loop with empty body
*cp = '\0'; // null-terminate last character

return s;
}

// ------------------------------------------------------------------------------------
// Trim leading & trailing blanks from string s, pad it with '\0's and return it
// (or NULL on error)
//
char *s_trim(char *s)
{
if ( !s || !*s ) // error, early exit
return NULL;

char *cp1; // for parsing the whole s
char *cp2; // for shifting & padding

// trim leading & shift left remaining
for (cp1=s; isblank((int)*cp1); cp1++ ) // skip leading blanks, via cp1
;
for (cp2=s; *cp1; cp1++, cp2++) // shift-left remaining chars, via cp2
*cp2 = *cp1;
*cp2-- = '\0'; // mark end of left trimmed s

// replace trailing blanks with '\0's
while ( cp2 > s && isblank((int)*cp2) )
*cp2-- = '\0'; // pad with '\0'

return s;
}

// ------------------------------------------------------------------------------------
// remove from string s any char contained in string del (return the modified string s)
char *s_strip(char *s, const char *del)
{
if ( !s || !*s)
return NULL;

char *cp1; // for parsing the whole s
char *cp2; // for keeping desired *cp1's

for (cp1=s, cp2=s; *cp1; cp1++ )
if ( !strchr(del, *cp1) ) // *cp1 is NOT contained in del
*cp2++ = *cp1; // copy it to start of s, via cp2
*cp2 = 0; // null terminate the trimmed s

return s;
}

// ------------------------------------------------------------------------------------
char *s_ncopy( char *dst, const char *src, int n )
{
char *ret = dst;

while ( (dst-ret) < n-1 && (*dst=*src) != '\0' )
dst++, src++;

if ( *dst )
*dst = 0;

return ret;
}

// ------------------------------------------------------------------------------------
// Convert s to lowercase and return it (or NULL on error)
//
char *s_tolower( char *s )
{
if ( !s ) // error, early exit
return NULL;

char *ret;
for ( ret=s; (*s=tolower(*s)); s++ )
;
return ret;
}

// ------------------------------------------------------------------------------------
// break a string up to maxtokens tokens and store them in *tokens[]
// (uses " " as the delimeter string)
// returns the number of tokens, or 0 on failure
// ------------------------------------------------------------------------------------

int s_tokenize(char *s, char *tokens[], int maxtokens, char *delimiters)
{
if ( !s || !*s || !tokens || !maxtokens || !delimiters || !*delimiters )
return 0;

register int i=0;

tokens[0] = strtok(s, delimiters);
if (tokens[0] == NULL)
return 0;
for (i=1; i < maxtokens && (tokens[i]=strtok(NULL, delimiters)) != NULL; i++);

return i;
}

// ------------------------------------------------------------------------------------
// Convert a Gregorian date to a Julian Day count
// IMPORTANT: accurate ONLY for dates after Oct 15, 1582 (Gregorian Calendar)
// Algorithm by Henry F. Fliegel & Thomas C. Van Flandern:
// http://www.hermetic.ch/cal_stud/jdn.htm#comp
//
long date_2jdn( Date date )
{
return
( 1461 * ( date.y + 4800 + ( date.m - 14 ) / 12 ) ) / 4 +
( 367 * ( date.m - 2 - 12 * ( ( date.m - 14 ) / 12 ) ) ) / 12 -
( 3 * ( ( date.y + 4900 + ( date.m - 14 ) / 12 ) / 100 ) ) / 4 +
date.d - 32075;

}

// ----------------------------------------------------------------------------------
// Convert a Julian Day count to a Gregorian date (d,m,y)
// IMPORTANT: accurate ONLY for dates after Oct 15, 1582 (Gregorian Calendar)
// Algorithm by Henry F. Fliegel & Thomas C. Van Flandern:
// http://www.hermetic.ch/cal_stud/jdn.htm#comp
//
Date *jdn_2date( Date *date, long jd )
{
long l = jd + 68569;
long n = ( 4 * l ) / 146097;
l = l - ( 146097 * n + 3 ) / 4;
long i = ( 4000 * ( l + 1 ) ) / 1461001;
l = l - ( 1461 * i ) / 4 + 31;
long j = ( 80 * l ) / 2447;
date->d = l - ( 2447 * j ) / 80;
l = j / 11;
date->m = j + 2 - ( 12 * l );
date->y = 100 * ( n - 49 ) + i + l;

return date;
}

// ------------------------------------------------------------------------------------
// Compare date1 against date2, chronologically.
// Return: 1 if date1 > date2, 0 if date1 == date2, -1 if date1 < date2
int date_compare( Date date1, Date date2 )
{
long int jdn1 = date_2jdn( date1 ); // convert date1 to julian day number
long int jdn2 = date_2jdn( date2 ); // convert date2 to julian day number

if (jdn1 > jdn2)
return 1;
if (jdn1 == jdn2)
return 0;

return -1;
}

// ------------------------------------------------------------------------------------
// Check if date.d exceeds the max allowed days in month date.m of year date.y
// Return TRUE if does not, FALSE otherwise
// for example: 29/2/2011, 31/4/anyyear are both FALSE
//
bool date_dayinbounds( Date date, int mdays[] )
{
if ( date.d > mdays[ date.m - 1 ] )
{
if ( date.d == 29 && date.m == FEB && isleap( date.y ) )
return TRUE;
return FALSE;
}

return TRUE;
}
// ------------------------------------------------------------------------------------
// Check if date lyes between calstart and calend (inclusive)
// Return TRUE if it does, FALSE otherwise
//
bool date_inbounds( Date date, Date calstart, Date calend)
{
return date_compare(date, calstart) >= 0 && date_compare(date, calend) <= 0;
}

// ------------------------------------------------------------------------------------
// Convert Gregorian date to weekday (valid from Sep 14, 1752 to Dec 31, 9999)
// Return 0 to 6 (Mon to Sun)
//
int date_2weekday( Date date )
{
return date_2jdn(date) % 7; // return jdn % 7
}

// ------------------------------------------------------------------------------------
// Calc the difference between date1 and date2 and RETURN it expressed as # of days.
// IMPORTANT:,
// the difference is also calc'ed as days, months, years and passed into datediff
// Algorithm by Mohammed Ali Babu
// http://www.codeproject.com/KB/datetime/DateDurationCalculation1.aspx
//
long date_diff( Date *datediff, Date date1, Date date2, int mdays[] )
{
if ( !datediff )
return -1;

long int jdn1 = date_2jdn( date1 ); // calc jd of date1
long int jdn2 = date_2jdn( date2 ); // calc jd of date2
Date *dp2 = (jdn2 > jdn1) ? &date2 : &date1; // dp2 points to latest date
Date *dp1 = (dp2 == &date1) ? &date2 : &date1; // dp1 points to earliest date

/*
* the following alogorithm is published by Mohammed Ali Babu at:
* http://www.codeproject.com/KB/datetime/DateDurationCalculation1.aspx
*/

// first calc the difference of the day part
int increment = 0;
if ( dp1->d > dp2->d )
increment = mdays[ dp1->m - 1 ];

if (increment == -1)
{
if ( isleap( dp1->y ) )
increment = 29;
else
increment = 28;
}

if (increment != 0)
{
datediff->d = (dp2->d + increment) - dp1->d;
increment = 1;
}
else
datediff->d = dp2->d - dp1->d;

// then calc the difference of the month part
if ( (dp1->m + increment) > dp2->m )
{
datediff->m = (dp2->m + 12) - (dp1->m + increment);
increment = 1;
}
else {
datediff->m = dp2->m - (dp1->m + increment);
increment = 0;
}

// and last calculate the difference of the year part
datediff->y = dp2->y - (dp1->y + increment);


return myabs( jdn2-jdn1 );
}

// ------------------------------------------------------------------------------------
// Add ndays to basedate and Return the result into date (ndays can be negative)
// (calstart and calend are used for boundary checking)
//
Date *date_plusdays( Date *date, Date basedate, long ndays, Date calstart, Date calend )
{
long jstart = date_2jdn( calstart ); // julian day of our calendar start date
long jend = date_2jdn( calend ); // julian day of our calendar end date
long jd = date_2jdn( basedate ); // julian day of basedate

if ( jd+ndays > jend ) // fix overflow (calend)
return jdn_2date( date, jend );

if ( jd+ndays < jstart ) // fix underflow (calstart)
return jdn_2date( date, jstart );

return jdn_2date( date, jd+ndays );
}

// ------------------------------------------------------------------------------------
// Convert string inbuf into a valid signed long int, store it in date->d
// Return FALSE on failure
//
bool date_getoperation( Date *date, char *inbuf )
{
if ( !inbuf || !*inbuf || (*inbuf != '+' && *inbuf != '-') )
return FALSE;

char *tail; // in strtol() for err checking

errno = 0;
date->m = date->y = INVALID;

s_strip(inbuf, " \t\v"); // strip off blanks from inbuf

date->d = strtol(inbuf, &tail, 10); // convert inbuf to long
if ( *tail != '\0' || errno == ERANGE )
{
puts("\t*** error: invalid operation");
date->d = INVALID;
return FALSE;
}

return TRUE;
}

// ------------------------------------------------------------------------------------
// If string inbuf contains any of our recognized mnemonics, date is set accordingly
// and the function returns TRUE (otherwise it returns FALSE).
//
bool date_getmnemonic( Date *date, char *inbuf, const Date calstart, const Date calend )
{
if ( !inbuf || !*inbuf ) // inbuf is either non-existant or empty
return FALSE; // early exit

time_t today = time( NULL ); // get system time
struct tm *tmtoday = localtime( &today );// convert it to a tm structure
long jstart = date_2jdn( calstart ); // julian day of our calendar start date
long jend = date_2jdn( calend ); // julian day of our calendar end date
long jtoday;
Date caltoday;

caltoday.d = (long) tmtoday->tm_mday;
caltoday.m = (long) tmtoday->tm_mon + 1;
caltoday.y = (long) tmtoday->tm_year + 1900;
jtoday = date_2jdn( caltoday );

if ( !strcmp( inbuf, "start") ) {
jdn_2date( date, jstart );
return TRUE;
}
if ( !strcmp( inbuf, "yesterday") ) {
// jdn_2date( date, jtoday-1 ); // faster but no boundary checking
date_plusdays( date, caltoday, -1, calstart, calend);
return TRUE;
}
if ( !strcmp( inbuf, "today") ) {
jdn_2date( date, jtoday );
return TRUE;
}
if ( !strcmp( inbuf, "tomorrow") ) {
// jdn_2date( date, jtoday+1 ); // faster but no boundary checking
date_plusdays( date, caltoday, +1, calstart, calend);
return TRUE;
}
if ( !strcmp( inbuf, "end") ) {
jdn_2date( date, jend );
return TRUE;
}

return FALSE;
}

// ------------------------------------------------------------------------------------
// Read a Gregorian date as a string form stdin, validate it & return it inside *date
// IMPORTANT:
//
// The function returns TRUE if the input string is a valid operation (i.e "-200" )
// instead of a valid date string (i.e. "1/1/2000" ). In that case, date->d
// is assigned the numeric value of the operation ( -200 for the above example )
// while date->m and date->y are assined the value -1 ( INVALID ).
//
// Only the second date is allowed to accept an operation string, so we use
// the parameter 'id' in order to know whether we're dealing with date1 or
// date2 in here.
//
// Since in case of a valid operation in the input, the returned date does NOT
// hold a valid date, further processing needs to be done in the main() function,
// to ensure that date2 is properly converted to a valid date, equalling to:
// date1 + date2.d, before attempting to do anything else with it (e.g. printing
// it)
//
//
bool date_askuser( int id, char *prompt, Date *date,
int max_inbuf, int mdays[], Date calstart, Date calend )
{
if ( !prompt || !date) // inbuf does not exist or it is empty
return FALSE;

char inbuf[ max_inbuf ]; // for reading the user input
char *stokens[3]; // to read d, m, y as strings
char *tail; // in strtol() for err checking
bool stop = TRUE; // for controlling the main loop
bool operated = FALSE; // got a date or an operation?

do
{
stop = TRUE; // reset boolean flag to TRUE
operated = FALSE; // reset boolean flag to FALSE

// prompt and get user input
printf( prompt ); // ask for input
fflush(stdin); // clear input buffer (stdin)
s_get(inbuf, max_inbuf); // read input as string in inbuf

// check if user typed just an ENTER
if ( !*inbuf )
continue; // stop = TRUE

s_trim( s_tolower(inbuf) ); // trim leading & trailng blanks

// check if user typed an operation (+/-) followed by a number
if ( id == ID1 && (*inbuf =='+' || *inbuf == '-') ) {
puts("\t*** error: operations only allowed in the 2nd date");
stop = FALSE;
continue;
}
if ( date_getoperation(date, inbuf) ) {
operated = TRUE;
continue; // stop = TRUE
}

// check if user typed any of our mnemonic strings
if ( date_getmnemonic( date, inbuf, calstart, calend ) ) {
stop = TRUE;
continue;
}

// split inbuf in up to 3 strings (tokens) assuming d, m, y
if ( s_tokenize( inbuf, stokens, 3, " /,.;:\t") != 3 ) {
puts("\t*** error: invalid date");
stop = FALSE;
continue;
}

// demand from user to type a day between 1-31
errno = 0; // reset golbal var errno
date->d = strtol(stokens[0], &tail, 10);// convert str day to long
if ( !validday(date->d) || *tail != '\0' || errno == ERANGE )
{
puts("\t*** error: valid days are 1-31");
date->d = INVALID;
stop = FALSE;
continue;
}

// demand from user to type a month between 1-12
errno = 0; // reset golbal var errno
date->m = strtol(stokens[1], &tail, 10);// convert str month to long
if ( *tail != '\0' || errno == ERANGE || !validmonth(date->m) )
{
puts("\t*** error: valid months are 1-12");
date->m = INVALID;
stop = FALSE;
continue;
}

// demand from user to type a year between 1752-9999
errno = 0; // reset golbal errno
date->y = strtol(stokens[2], &tail, 10);// convert str year to long
if ( *tail != '\0' || errno == ERANGE || !validyear(date->y) )
{
puts("\t*** error: valid years are 1752-9999");
date->y = INVALID;
stop = FALSE;
continue;
}

/* now we have a complete date (d,m,y) but this
* does not gurantee us that it is a valid one
* (e.g. 29/2/2000 is valid, but 29/2/2001 is not)
* (also, e.g. 31/4 is invalid, an so on)
*/

// ensure day lyes inside the month boundary of the typed date
if ( !date_dayinbounds(*date, mdays) )
{
date->d = date->m = date->y = INVALID;
puts("\t*** error: invalid day");
stop = FALSE;
continue;
}

// ensure date is between 14/9/1752 and 31/12/9999
if ( !date_inbounds(*date, calstart, calend) )
{
date->d = date->m = date->y = INVALID;
puts("\t*** error: valid dates are 14/9/1752 - 31/12/9999");
stop = FALSE;
continue;
}

} while( !stop || !*inbuf );

return operated;
}

// ------------------------------------------------------------------------------------
void print_help( void )
{
//printf("\n\n%70s\n", "<mig_f1@hotmail.com>\n");
puts("A sample program performing various calculations between two dates in \nthe time interval: 14/9/1752 to 31/12/9999 (results never exceed it).\n\nEach date input is checked in real time against both syntax & logical\nerrors. It can be in one of the following formats...\n-\td/m/y\t\t: other separators: :,.; and tab\n-\ta signed number\t: e.g. -200 (subtract 200 days from 1st Date)\n-\tstart\t\t: equals to 14/9/1752\n-\tyesterday\t: equals to yesterday's date\n-\ttoday\t\t: equals to today's date\n-\ttomorrow\t: equals to tomorrow's date\n-\tend\t\t: equals to 31/12/9999\n\nThe calculated results include...\n-\tdifference expressed in days\n-\tdifference expressed in days, months, years\n-\tweekday indication\n-\tJulian Day Number indication\n-\tleap year indication\n-\tmonthly calendar of both dates (or 1st only, if same with 2nd)");
puts("\nBONUS:\tPass a year (1752 - 9999) in the command line, to create a text\n\tfile called \"calYEAR.txt\", containing the yearly calendar.");

return;
}

// ------------------------------------------------------------------------------------
// Print date in the form: MONTH DAY YEAR, Weekday (jdn) (is leap year ?)
//
void print_date(Date date, int id, char *mnames[], char *dnames[] )
{
if ( !validday( date.d ) || !validmonth( date.m ) || !validyear( date.y ) )
return;

printf( "\t%d. %s %02ld %04ld, %-9s (jdn: %ld) %s\n",
id,
mnames[ (int)(date.m)-1 ],
date.d, date.y, dnames[ date_2weekday(date) ],
date_2jdn( date ),
isleap( date.y ) ? "\t(leap year)" : ""
);

return;
}

// ------------------------------------------------------------------------------------
// Print the difference between date1 and date 2 expressed both in number of days
// and in the form: days, months, years
//
void print_diffs(long int ndays, Date date, char *mnames[], char *dnames[] )
{
printf("\tDiff:\t%ld day(s)\n", ndays);
printf( "\t\t%ld years(s), %02ld months(s) and %02ld days(s)\n",
date.y, date.m, date.d );

return;
}

// ------------------------------------------------------------------------------------
// Print the monthly calendar of date
//
void fprint_calmonth(Date date, int mdays[], char *mnames[], char *dnames[], FILE *fp )
{
register int i=0, j=0;
Date mon1date = { // temp date for 1/date.m/date.y
.d = 1, .m = date.m, .y = date.y
};
int monthdays = mdays[date.m - 1]; // calc # days of date.m
if ( isleap(date.y) && date.m == FEB ) // +1 if leap February
monthdays++;

// print month & year
fprintf(fp, "\n%s %ld\t", mnames[date.m - 1], date.y );

// print header (day names)
for (i=0; i<7; i++) {
fprintf(fp, "%3s ", dnames[i]);
}
fputc('\n', fp);

// now print the day numbers

// start with blanks, when needed
fprintf(fp, "\t\t");
for (i=0; i < date_2weekday( mon1date ); i++)
fprintf(fp, "%3s ", "");

// start printing the day numbers (i is carried from previous loop)
for ( j=0; j < monthdays; j++, i++ )
{
if ( i % 7 == 0)
fprintf(fp, "\n\t\t");
fprintf(fp, "%3d ", j+1);
}
fputc('\n', fp);

return;
}

// ------------------------------------------------------------------------------------
// Print the yearly calendar of date
//
void fprint_calyear( Date date, int mdays[], char *mnames[], char *dnames[], FILE *fp )
{
register int i;

for (i=0; i<12; i++) {
date.m = i+1;
fprint_calmonth( date, mdays, mnames, dnames, fp );
}

return;
}
// ------------------------------------------------------------------------------------
// Check for any command line arguments, if any and handle them accordingly.
// Currently we are only accepting 1 argument, representing a year for which we
// create a text file, holding the yearly calendar. Years earlier than 1752 or
// later than 9999 are automatically fixed to be equal with the lower or upper
// bound, respectively.
//
void do_cmlargs(char *argv[], Date calstart, Date calend,
int mdays[], char *mnames[], char *dnames[] )
{
Date ydate; // for 1/1/argv[1]
Date *pdate = NULL; // temp pointer
FILE *fp; // file pointer
char fname[12+1] = "";

s_strip( argv[1], " \t\v"); // strip off blanks

// construct a temporary date corresponding to: 1/1/argv[1]
ydate.d=1; ydate.m=1; ydate.y = strtol( argv[1], NULL, 10 );

// fix year if it either underflows or overflows (1752 - 9999)
pdate = &ydate;
if ( date_compare(ydate, calstart) < 0 )
pdate = &calstart;
else if ( date_compare(ydate, calend) > 0 )
pdate = &calend;

// construct filename
sprintf(fname, "cal%ld.txt", pdate->y);

// open file and write the yearly calendar
fp = fopen(fname, "w");
if ( !fp ) { // file open failed
printf("\t*** write error in file: %s\n", fname);
}
else {
fprint_calyear(*pdate, mdays, mnames, dnames, fp);
printf( "\t*** yearly calendar of %ld printed in %s\n",
pdate->y, fname );
fclose( fp );
}
printf("press ENTER to continue...");
fflush(stdin); getchar();

return;
}
// ------------------------------------------------------------------------------------
int main( int argc, char *argv[] )
{
char *dnames[7] = { // day names
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
};
char *mnames[12] = { // month names
"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"
};
// month lengths in days
int mdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Date calstart = { .d=14, .m=9, .y=1752 }; // our calendar starting date
Date calend = { .d=31, .m=12, .y=9999 }; // our calendar ending date

Date date1, date2; // dates to be read from user
Date diffdate; // for holding diff as (d,m,y)
long ndays; // difference in days
bool operated = FALSE; // input was date or operation?
char inbuf[MAX_INBUF] = ""; // our own input buffer

// check & execute any command line arguments
if ( argv[1] )
do_cmlargs( argv, calstart, calend, mdays, mnames, dnames );

// start the main loop of the program
do
{
print_help();

// read date1 and date2
date_askuser( ID1, "\nFirst date (d/m/y): ", &date1,
MAX_INBUF, mdays, calstart, calend );
operated = date_askuser(
ID2, "Second date (d/m/y): ", &date2,
MAX_INBUF, mdays, calstart, calend );

// if date2 was an operation, store the resulting date into date2
if ( operated )
date_plusdays( &date2, date1, date2.d, calstart, calend);

// calc difference between date1 and date2
ndays = date_diff( &diffdate, date1, date2, mdays );

// print dates and their difference
putchar('\n');
puts("\t--------------------------------------------------");
print_date( date1, ID1, mnames, dnames );
print_date( date2, ID2, mnames, dnames );
puts("\t--------------------------------------------------");
print_diffs( ndays, diffdate, mnames, dnames );
puts("\t--------------------------------------------------");

// display month calendars
fprint_calmonth( date1, mdays, mnames, dnames, stdout );
if ( date1.y != date2.y || (date1.y == date2.y && date1.m != date2.m) )
fprint_calmonth(date2, mdays, mnames, dnames, stdout);

printf("\ntry again (/n): ");
fflush(stdin);
} while ( *s_tolower( s_get(inbuf, MAX_INBUF) ) != 'n' );

exit(0);
}
Τελευταία επεξεργασία από migf1 και 25 Ιαν 2012, 16:33, έχει επεξεργασθεί 12 φορά/ες συνολικά
Go under the hood with C: Pointers, Strings, Linked Lists
Άβαταρ μέλους
migf1
powerTUX
powerTUX
 
Δημοσιεύσεις: 2082
Εγγραφή: 03 Ιουν 2011, 16:32
Εκτύπωση

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό medigeek » 14 Ιουν 2011, 09:17

github it :D :clap:

έγραψε:free for whatever use, plz give me credit

Μια αδεια χρήσης που πάει με αυτό που ζητάς είναι η MIT ή η BSD

Έλαβα μερικά warnings όταν έκανα compile τον κώδικα, δεν ξέρω αν είναι σημαντικό:
έγραψε:gcc -Wall -o "main" "main.c" (in directory: /home/savvas/Desktop/asf)
main.c: In function ‘date_askuser’:
main.c:307:7: warning: format not a string literal and no format arguments
main.c: In function ‘print_results’:
main.c:398:4: warning: format ‘%ld’ expects type ‘long int’, but argument 2 has type ‘int’
Compilation finished successfully.
Κύπριος; Κόπιασε στο ubuntu-cy! ┃ Launchpad Debian Github
Οδηγός για νεοεισερχόμενους -- Αρχικές οδηγίες για αρχάριους χρήστες του Ubuntu

1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 12.10 quantal 3.5.0-21-generic 64bit (en_US.UTF-8, GNOME cinnamon2d), Ubuntu 3.5.0-19-generic, Windows 7
3 Intel Core2 Duo CPU E6550 2.33GHz ‖ RAM 5970 MiB ‖ MSI MS-7235
4 nVidia G73 [GeForce 7300 GT] [10de:0393] {nvidia}
5 eth0: Realtek RTL-8110SC/8169SC Gigabit Ethernet [10ec:8167] (rev 10)
Άβαταρ μέλους
medigeek
Freedom
Freedom
 
Δημοσιεύσεις: 5023
Εγγραφή: 24 Μάιος 2008, 14:49
Τοποθεσία: Σερβία/Κύπρος
Launchpad: medigeek
IRC: savvas
Εκτύπωση

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό simosx » 14 Ιουν 2011, 10:51

Πράγματι, ρίξτο στο github!

Και βάλε στους Collaborators του έργου εμένα (simosx) και το Σάββα (medigeek).
προσωπικό ιστολόγιο ϗ πλανήτης 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 » 14 Ιουν 2011, 12:49

Για το 2ο warning, άλλαξε τον τύπο του ndays από int σε long int, στα ορίσματα της print_results(). Το 1ο warning απλά αγνόησέ το ;)

Σχετικά με την άδεια χρήσης, βρε παιδιά δεν είναι κάνα σοβαρό project ούτε τίποτα επίσημο για να το δεσμεύσω και με τη βούλα με άδεια χρήσης. Μικρά προγραμματάκια είναι αυτά, περισσότερο για μεταξύ μας και προσωπικά δεν έχω κανένα πρόβλημα να το πάρει ο καθένας και να του κάνει ότι νομίζει. To "plz give me credit" περισσότερο το έβαλα για να γεμίσει η γραμμή παρά για να μπει το πρόγραμμα στο... βιογραφικό μου :lol:

Σίμο, τα Github, Mercurial κλπ δεν τα έχω δουλέψει ποτέ και να πω το κρίμα μου βαριέμαι αφάνταστα να το κάνω, ειδικά για απλά προγραμματάκια όπως αυτό εδώ (+ ότι πρέπει να στήσω clients και σε 3 μηχανήματα: linux, win xp, win 7 μιας και τα χρησιμοποιώ και τα 3 πολύ συχνά). Κάποια στιγμή θα ασχοληθώ να μάθω κάποιο πάντως.

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

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό simosx » 14 Ιουν 2011, 13:38

migf1 έγραψε:
Σχετικά με την άδεια χρήσης, βρε παιδιά δεν είναι κάνα σοβαρό project ούτε τίποτα επίσημο για να το δεσμεύσω και με τη βούλα με άδεια χρήσης. Μικρά προγραμματάκια είναι αυτά, περισσότερο για μεταξύ μας και προσωπικά δεν έχω κανένα πρόβλημα να το πάρει ο καθένας και να του κάνει ότι νομίζει. To "plz give me credit" περισσότερο το έβαλα για να γεμίσει η γραμμή παρά για να μπει το πρόγραμμα στο... βιογραφικό μου :lol:


Και εμένα με πήρε χρόνο για να τα μάθω, ωστόσο όταν μάθεις την προϊστορία είναι πολύ απλά.
Κάθε πνευματικό μας δημιούργημα έχει αυτό που λέμε «All rights reserved», δηλαδή μόνο εσύ έχεις δικαιώματα στον κώδικα. Αυτό που λέω είναι νόμος, και επικυρώθηκε και από την ΕΕ στη δεκαετία του '90 ειδικά για λογισμικό.
Οπότε, όταν ζητούμε άδεια χρήσης δε σε βάζουμε να κάνεις άσκοπα πράγματα. Είναι κάτι πολύ απλό, όπου δίνεις τη δυνατότητα σε έναν τρίτο να επαναχρησιμοποιήσει τον κώδικα για κάτι καλύτερο.
Απλά επιλέγεις π.χ. GPLv3 και αυτό ήταν. Δεν υπάρχει θέμα βιογραφικού ή ευσήμων, απλά κάνουμε τα βήματα που χρειάζονται για λογισμικό ΕΛ/ΛΑΚ.

migf1 έγραψε:
Σίμο, τα Github, Mercurial κλπ δεν τα έχω δουλέψει ποτέ και να πω το κρίμα μου βαριέμαι αφάνταστα να το κάνω, ειδικά για απλά προγραμματάκια όπως αυτό εδώ (+ ότι πρέπει να στήσω clients και σε 3 μηχανήματα: linux, win xp, win 7 μιας και τα χρησιμοποιώ και τα 3 πολύ συχνά). Κάποια στιγμή θα ασχοληθώ να μάθω κάποιο πάντως.


Για το Git και το Github αρκεί να μάθεις τα βασικά που είναι να προσθέτεις τον κώδικά σου στο αποθετήριο. Υπάρχει οδηγός στο φόρουμ, και αν διαβάζεις το LinuxInside μπορείς να δεις άρθρο μου για το ίδιο θέμα.
Από τα άτομα στο φόρουμ είσαι από τα λίγα που έχουν τόσο ενδιαφέρον για προγραμματισμό.
Θα ήθελα να αφιερώσω μια ώρα κάποια μέρα στο IRC για όσους έχουν ενδιαφέρον να δούμε μαζί τη χρήση του Git και του Github.
Οπότε, αν θέλετε να γίνει κάτι τέτοιο, γράψτε εδώ.
προσωπικό ιστολόγιο ϗ πλανήτης 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

Δημοσίευσηαπό clepto » 14 Ιουν 2011, 13:45

+1
1 Γνώσεις Linux: Ικανοποιητικό ┃ Προγραμματισμού: Ικανοποιητικό ┃ Αγγλικών: Ικανοποιητικό
2 Ubuntu 13.04 raring 3.8.0-30-generic 64bit (en_US.UTF-8, Unity ubuntu), Ubuntu 3.8.0-19-generic, Windows 7
3 Intel Core i7-3537U CPU @ 2.00GHz ‖ RAM 3840 MiB ‖ ASUS K56CB
4 Intel 3rd Gen Core processor Graphics Controller [8086:0166] {i915}
5 wlan0: Atheros Inc. AR9485 Wireless Network Adapter [168c:0032] (rev 01) ⋮ eth0: Realtek RTL8111/8168 PCI Express Gigabit Ethernet controller [10ec:8168] (rev 0a)
clepto
antiwinTUX
antiwinTUX
 
Δημοσιεύσεις: 4102
Εγγραφή: 07 Ιαν 2010, 16:27
Τοποθεσία: Πάτρα
Launchpad: christriant
IRC: Clepto
Εκτύπωση

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό Qdata » 14 Ιουν 2011, 14:06

simosx έγραψε:Θα ήθελα να αφιερώσω μια ώρα κάποια μέρα στο IRC για όσους έχουν ενδιαφέρον να δούμε μαζί τη χρήση του Git και του Github.
Οπότε, αν θέλετε να γίνει κάτι τέτοιο, γράψτε εδώ.


Έχω διαβάσει το άρθρο σου στο LinuxInside αλλά θα ήθελα να παρακολουθήσω κάτι τέτοιο στο IRC. :)
Linux User: #530165
Γνώσεις ⇛ Linux: Μέτριο ┃ Προγραμματισμός: Ναι ┃ Αγγλικά: Καλά
Λειτουργικό ⇛ Ubuntu 11.04 32bit σε Intel(R) Atom(TM) CPU N270 @ 1.60GHz
(Notebook) Προδιαγραφές ⇛ 2x Intel(R) Atom(TM) CPU N270 @ 1.60GHz │ 1016MB │ HDA-Intel - HDA Intel -- USB-Audio - USB AUDIO│ 1024x600 pixels
Νέος στο Linux?Οδηγοί - How to - Tutorials
Qdata
powerTUX
powerTUX
 
Δημοσιεύσεις: 1875
Εγγραφή: 18 Ιουν 2010, 19:40
Τοποθεσία: Σέρρες
IRC: dimos
Εκτύπωση

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό migf1 » 14 Ιουν 2011, 14:31

Ευχαριστώ για τα καλά λόγια Σίμο, μάλλον όμως ανήκω σε εκείνη την στρυφνή κατηγορία ανθρώπων που έχουν σαν μοτο "you can't teach an old dog new tricks" :lol:

Το ενδιαφέρον μου για προγραμματισμό μεταφράζεται πια σε ενδιαφέρον για μεταλαμπάδευση (των όποιων μου γνώσεων) στις νέες γενιές προγραμματιστών και αναλυτών, μιας κι εγώ πλέον προγραμματίζω αραιά και που, αποκλειστικά και μόνο από χόμπι. Έχω περάσει πολλά από τα προγραμματιστικά κανάλια την τελευταία εικοσαετία (διανύω αισίως την 4η δεκαετία της ζωής μου) ξεκινώντας ως φοιτητής από BSD Unix και text-based Internet ( όταν στην αγορά των "σπιτικών" υπολογιστών μεσουρανούσε ο Apple II C :lol: )

Θέλω να πω, είμαι πολύ εξοικειωμένος και με άδειες και με revision control συστήματα και με πολλά & διάφορα άλλα, με τη διαφορά όμως πως βρίσκομαι εδώ και πολύ καιρό στη προγραμματιστική μου δύση, οπότε τις πολλές "εξωτερικές" τυπικότητες και την εκμάθηση πραγμάτων που ουσιαστικά για προσωπική χρήση μου είναι πλέον λίγο-πολύ άχρηστα τα αποφεύγω ;)

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

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό medigeek » 14 Ιουν 2011, 15:28

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

Αντε παιδιά τους λυχνους στα χέρια και πάμε για... προγραμ-mathon. :)
Κύπριος; Κόπιασε στο ubuntu-cy! ┃ Launchpad Debian Github
Οδηγός για νεοεισερχόμενους -- Αρχικές οδηγίες για αρχάριους χρήστες του Ubuntu

1 Γνώσεις Linux: Πολύ καλό ┃ Προγραμματισμού: Πολύ καλό ┃ Αγγλικών: Πολύ καλό
2 Ubuntu 12.10 quantal 3.5.0-21-generic 64bit (en_US.UTF-8, GNOME cinnamon2d), Ubuntu 3.5.0-19-generic, Windows 7
3 Intel Core2 Duo CPU E6550 2.33GHz ‖ RAM 5970 MiB ‖ MSI MS-7235
4 nVidia G73 [GeForce 7300 GT] [10de:0393] {nvidia}
5 eth0: Realtek RTL-8110SC/8169SC Gigabit Ethernet [10ec:8167] (rev 10)
Άβαταρ μέλους
medigeek
Freedom
Freedom
 
Δημοσιεύσεις: 5023
Εγγραφή: 24 Μάιος 2008, 14:49
Τοποθεσία: Σερβία/Κύπρος
Launchpad: medigeek
IRC: savvas
Εκτύπωση

Re: Παράδειγμα Υπολογισμού Ημερομηνιών σε C

Δημοσίευσηαπό migf1 » 14 Ιουν 2011, 21:31

V2 με κώδικα και σύνδεσμο κατεβάσματος, στην 1η δημοσίευση.

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

Επόμενο

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