Συναρτήσεις Χρόνου <time.h>



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

Χρήσεις των συναρτήσεων χρόνου:

Βασικές συναρτήσεις

time_t time(time_t *tloc) 

επιστρέφει τον ημερολογιακό χρόνο από την 00:00:00 GMT, Jan. 1, 1970 (γνωστή ως 'the epoch', GMT=Greenwitch Mean Time), μετρούμενο σε δευτερόλεπτα.

Αν ο δείκτης tloc δεν είναι NULL, η τιμή που επιστρέφει η συνάρτηση επίσης αποθηκεύεται στη θέση που δείχνει ο tloc.

Σε περίπτωση επιτυχίας η συνάρτηση time() επιστρέφει το χρόνο, ενώ σε περίπτωση αποτυχίας -1. Ο τύπος  time_t ορίζεται ως long int στη βιβλιοθήκη time.h

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

struct tm *localtime(const time_t *time) 

δέχεται ως όρισμα τον ημερολογιακό χρόνο σε δευτερόλεπτα και επιστρέφει ένα δείκτη σε μια αναλυτική δομή χρόνου tm που ορίζεται στη βιβλιοθήκη time.h και περιλαμβάνει, δευετρόλεπτα, λεπτά, ώρες, ημέρα, μήνα, έτος, ημέρα της εμβδομάδας, ημέρα του χρόνου, ζώνη ώρας κλπ. Για τον ακριβή ορσμό ανατρέξτε στο αρχείο κεφαλής της βιβλιοθήκης.

Οι συναρτήσεις 

char *ctime(const time_t *time)
char *asctime(const tm *time)

μεταφράζουν το χρόνο από τύπο time_t ή δομή tm στη σγνωστή αναγνώσιμη συμβολοσειρά που εμφανίζει η εντολή date του UNIX/Linux. Αντίθετα η συνάρτηση

struct tm *getdate(const char *string)

μεταφράζει μια συμβολοσειρά ημερομηνίας σε δομή tm. Η συμβολοσειρά μπορεί να έχει πολλές διαφορετικές μορφές, συμβουλευετείτε το εγχειρίδιο της πρότυπης βιβλιοθληκης της C. Οι συναρτήσεις ορίζονται στo time.h.

Από την άλλη πλευρά η συνάρτηση 

int gettimeofday(struct timeval *tp, struct timezone *tzp) 

επιστρέφει δύο ορίσματα, το δείκτη tp σε δομή timeval και τον δείκτη tzp σε δομή timezone. Η πρώτη δομή ορίζεται στη βιβλιοθήκη sys/times.h και δίνει τον ημερολογιακό χρόνο σε ακρίβεια microseconds

struct timeval{
  long int tV_sec;  
  long int t_usec;
};

ενώ η δομή timezsone ορίζεται στη βιβλιοθήκη time.h και περιέχει την απόσταση της ζώνης ώρας σε λεπτά δυτικά του GMT, και ένα flag για το αν η θερινή ώρα ισχύει ή όχι, τη συγκεκριμένη στιγμή στο συγκεριμένο τόπο. Στην ίδια βιβλιοθήκη βρίσκονται και οι συναρτήσεις διαχείρισης της ζώνης ώρας.

Η συνάρτηση 

int settimeofday(struct timeval *tp, struct timezone *tzp)

θέτει την ώρα του συστήματος (αν έχει το κατάλληλο δικαίωμα διαχειριστή). Τόσο η gettimeofday() όσο και η settimeofday() στην επιτυχία επιστρέφουν 0, σε ποτυχία -1. Σε περίπτωση αποτυχίας θέτουν ορισμένα σφάλματα στο errno, τα οποία ορίζονται στη βιβλιοθήκη time.h

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

Τελικά, για μεγαλύτερη ακρίβεια στο χρόνο CPU που χρησιμοποιεί ένα πρόγραμμα υπάρχει η συνάρτηση 

clock_t clock() 

επιστρέφει τον αριθμό των παλών του ρολογιού της CPU στον τύπο clock_t που ορίζεται στη βιβλιοθήκη time.h. Εκεί ορίζεται και η σταθερά CLOCKS_PER_SEC.
#include <time.h>

clock_t start, end;
double cpu_time_used;

start = clock();
... /* Do the work. */
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

Παραδείγματα

Παράδειγμα 1: Χρόνος εκτέλεσης υπολογισμού

Ακολουθούν δύο προγράμματα, ένα που μετρά σε δευτερόλεπτα και ένα σε μεγαλύτερη ακρίβεια, κανοντας πράξεις συμμιγών αριθμών:


/* timer.c */
 
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
 
main()
{int i;
time_t t1,t2;
 
(void) time(&t1);
for (i=1;i<=300;++i)
printf("%d %d %d\n",i, i*i, i*i*i);
(void) time(&t2);
printf(``\n Time to do 300 squares and cubes= %d seconds\n'', (int) t2-t1);
}

/* Subtract the `struct timeval' values X and Y,
storing the result in RESULT.
Return 1 if the difference is negative, otherwise 0. */

int
timeval_subtract (result, x, y)
struct timeval *result, *x, *y;
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}

/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;

/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}

Παράδειγμα 2: Σπόρος γεννήτριας τυχαίων αριθμών

Η συνάρτηση lrand48() παράγει ακολουθία μη-αρνητικών long int τυχαίων αριθμών στο διάστημα (0, 2**31):


/* random.c */
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
 
main()
{ int i;
time_t t1;
 
(void) time(&t1);
srand48((long) t1);
/* use time in seconds to set seed */
printf(``5 random numbers (Seed = %d):\n'',(int) t1);
for (i=0;i<5;++i)
printf(``%d '', lrand48());
printf(``\n\n''); /* flush print buffer */
}

Ασκήσεις

Άσκηση 12708

Γράψετ ένα πρόγραμμα C που μετρά ένα τμήμα κώδικα σε millisevods.

Άσκηση 12709

Γράψτε ένα πρόγραμμα C για τη παραγωγή ακολουθίας τυχαίων αριθμών στα διαστήματα (α) 0.0 - 1.0 (β) 0.0 - n όπου nο αριθμός κινητής υποδιαστολής. Ο σπόρος να παράγεται με συνάρτηση χρόνου.



Dave Marshall
1/5/1999
μετάφραση και προσαρμογή στα Ελληνικά Κ.Γ. Μαργαρίτης
12/3/2008