Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 19 Zeitroutinen
Pfeil 19.1 Die Headerdatei <time.h>
Pfeil 19.1.1 Konstanten in der Headerdatei <time.h>
Pfeil 19.1.2 Datums- und Zeitfunktionen in <time.h>
Pfeil 19.2 Laufzeitmessung (Profiling)

In der C-Standard-Bibliothek sind einige Funktionen enthalten, mit denen Sie die Zeit bestimmen können. Die Zeit umfasst dabei das Datum und die Uhrzeit.

19 Zeitroutinen


Rheinwerk Computing - Zum Seitenanfang

19.1 Die Headerdatei <time.h> Zur nächsten ÜberschriftZur vorigen Überschrift

Es folgen einige Standardfunktionen der Headerdatei <time.h>, in denen Routinen für Zeit und Datum deklariert sind. Tabelle 19.1 gibt Ihnen einen kurzen Überblick über die speziellen (primitiven) Datentypen in dieser Headerdatei und ihre Bedeutungen.


Tabelle 19.1 (Primitive) Datentypen und Struktur für Datum und Zeit

Typ Bedeutung
size_t

arithmetischer Datentyp für Größenangaben

clock_t

arithmetischer Datentyp für die CPU-Zeit

time_t

arithmetischer Datentyp für Datums- und Zeitangaben

struct tm

enthält alle zu einer (gregorianischen) Kalenderzeit relevanten Komponenten


Laut ANSI-C-Standard sollten in der Struktur tm folgende Komponenten enthalten sein:


Tabelle 19.2 Bedeutung der Strukturvariablen in »struct tm«

»struct tm«-Variable Bedeutung
int tm_sec;

Sekunden (0–59)

int tm_min;

Minuten (0–59)

int tm_hour;

Stunden (0–23)

int tm_mday;

Monatstag (1–31)

int tm_mon;

Monate (0–11; Januar = 0)

int tm_year;

ab 1900

int tm_wday;

Tag seit Sonntag (0–6; Sonntag = 0)

int tm_yday;

Tag seit 1. Januar (0–365; 1. Januar = 0)

int tm_isdst;

Sommerzeit (tm_isdst > 0)

Winterzeit (tm_istdst == 0)

nicht verfügbar (tm_isdst < 0)


Auf Linux-Systemen sind außerdem noch folgende Komponenten vorhanden:

long int tm_gmtoff;

tm_gmtoff gibt die Sekunden östlich von UTC bzw. den negativen Wert westlich von UTC für die Zeitzonen an. UTC steht für Universal Time Coordinated und dient als Bezeichnung für eine auf der gesamten Erde einheitliche Zeitskala. Die Universal Time ist identisch mit der Greenwich Mean Time (GMT). Diese Angabe kann aber auch unter

long int __tm_gmtoff

vorliegen. Ebenfalls nur bei Linux ist folgende Komponente enthalten:

const char *tm_zone;

Diese Variable enthält den Namen der aktuellen Zeitzone. Diese kann auch in folgender Schreibweise angegeben sein:

const char *__tm_zone;

Rheinwerk Computing - Zum Seitenanfang

19.1.1 Konstanten in der Headerdatei <time.h> Zur nächsten ÜberschriftZur vorigen Überschrift

Folgende zwei Konstanten sind in der Headerdatei <time.h> deklariert:

  • CLOCKS_PER_SEC – Die Konstante enthält die Anzahl von clock_t-Einheiten pro Sekunde.
  • NULL – Das ist derselbe NULL-Zeiger, den Sie schon in der Headerdatei <stdio.h> kennengelernt haben.

Rheinwerk Computing - Zum Seitenanfang

19.1.2 Datums- und Zeitfunktionen in <time.h> topZur vorigen Überschrift

Die Zeit, mit der der Systemkern arbeitet, ist die Anzahl der Sekunden, die seit dem 1. Januar 1970, 00:00:00 Uhr, vergangen sind. Diese Zeit wird immer mit dem Datentyp time_t dargestellt und enthält das Datum und die Uhrzeit. Diese Zeit kann mit der Funktion

time_t time(time_t *zeitzeiger);

ermittelt werden. Wird für den Parameter zeitzeiger kein NULL-Zeiger verwendet, befindet sich an dieser Adresse die aktuelle Systemzeit. Hierzu folgt nun ein kleines Listing, das die Zeit in Sekunden fortlaufend seit dem 1. Januar 1970 um 00:00:00 Uhr mithilfe der Funktion time() ausgibt:

/* time1.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef  __unix__
   #define clrscr() printf("\x1B[2J")
#else
   #include <stdlib.h>
   #define clrscr() system("cls")
#endif

int main(void) {
   time_t t;

   time(&t);
   while(1) {
      clrscr();
      printf("%ld\n",t);
      printf("Mit <STRG><C> bzw. <STRG><D> beenden!! ");
      time(&t);
   }
   return EXIT_SUCCESS;
}

Ob es nach dem »Jahr 2000«-Problem zum Jahre 2038 zum nächsten Problem kommt, bleibt noch offen. Bei vielen Rechnern ist time_t als long implementiert, womit Platz für etwa 2 Milliarden Sekunden wäre. Dies wäre im Jahr 2038 erreicht. Der Standard schreibt hier nicht vor, welchen Wert time_t haben soll, und somit ist der Wertebereich von der Implementierung abhängig.

»localtime()« und »gmtime()« – Umwandeln von »time_t« in »struct tm«

Die Ausgabe der Sekunden als Zeitformat ist nicht gerade originell. Sie könnten jetzt anfangen, Funktionen zu schreiben, mit denen der Rückgabewert der Funktion time() in ein entsprechendes Format umgerechnet wird. Oder Sie verwenden bereits geschriebene Standardfunktionen wie:

struct tm *localtime(const time_t *zeitzeiger);
struct tm *gmtime(const time_t *zeitzeiger);

Beide Funktionen liefern als Rückgabewert die Adresse einer Zeitangabe vom Typ struct tm. Diese Struktur wurde bereits zu Beginn dieses Kapitels behandelt. Die Funktion localtime() wandelt die Kalenderzeit der Adresse time_t *zeitzeiger in lokale Ortszeit um – unter der Berücksichtigung von Sommer- und Winterzeit. gmtime() dagegen wandelt die Kalenderzeit in die UTC-Zeit um.

Hierzu ein Beispiel, das die Eingabe eines Geburtsdatums erwartet und anschließend das Alter in Jahren, Monaten und Tagen ausgibt:

/* time2.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct tm *tmnow;

void today(void) {
   time_t tnow;

   time(&tnow);
   tmnow = localtime(&tnow);
   printf("Heute ist der ");
   printf("%d.%d.%d\n",
      tmnow->tm_mday, tmnow->tm_mon + 1, tmnow->tm_year + 1900);
}

int main(void) {
   int tag, monat, jahr;
   unsigned int i=0, tmp;

   printf("Bitte gib Deinen Geburtstag ein!\n");
   printf("Tag : ");
   scanf("%d", &tag);
   printf("Monat : ");
   scanf("%d", &monat);
   printf("Jahr (jjjj) : ");
   scanf("%d", &jahr);
   today();
   if(tmnow->tm_mon < monat) {
      i = 1;
      tmp=tmnow->tm_mon+1-monat;
      monat=tmp+12;
   }
   else {
      tmp=tmnow->tm_mon+1-monat;
      monat=tmp;
   }
   if(monat == 12) {
      monat = 0;
      i = 0;
   }
   printf("Sie sind %d Jahre %d Monat(e) %d Tag(e) alt\n",
      tmnow->tm_year+1900-jahr-i,monat, tmnow->tm_mday-tag);
   return EXIT_SUCCESS;
}

Abbildung 19.1 Verwendung der Funktion »localtime()«

Eine Anmerkung zur if else-Bedingung im Programm: Diese war erforderlich, damit im Monatsdatum kein negativer Wert zurückgegeben wird und Sie nicht auf einmal 1 Jahr älter sind.

»mktime()« – Umwandeln von »struct tm« in »time_t«

Kommen wir jetzt zum Gegenstück der Funktionen localtime() und gmtime():

time_t mktime(struct tm *zeitzeiger);

Auf diese Weise wird eine Zeit im struct tm-Format wieder in eine Zeit im time_t-Format umgewandelt. Ist die Kalenderzeit nicht darstellbar, gibt diese Funktion –1 zurück. Die echten Werte der Komponenten tm_yday und tm_wday in zeitzeiger werden ignoriert. Die ursprünglichen Werte der Felder, tm_sec, tm_min, tm_hour, tm_mday und tm_mon, sind nicht auf den durch die tm-Struktur festgelegten Bereich beschränkt. Befinden sich die Felder nicht im korrekten Bereich, werden diese angepasst.

Das heißt konkret: Wird z. B. das fehlerhafte Datum 38.3.2001 eingegeben, muss die Funktion mktime() dieses Datum richtig setzen. Bei richtiger Rückgabe erhalten Sie entsprechende Werte für tm_yday und tm_wday. Der zulässige Bereich für die Kalenderzeit liegt zwischen dem 1. Januar 1970, 00:00:00 Uhr, und dem 19. Januar 2038, 03:14:07 Uhr.

Ein Beispiel soll zeigen, wie Sie den genauen Wochentag durch diese Funktion ermitteln können:

/* time3.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

char *wday[] = {
   "Sonntag", "Montag", "Dienstag", "Mittwoch",
   "Donnerstag", "Freitag", "Samstag", "??????"
};

int main(void) {
   struct tm time_check;
   int year, month, day;

   /* Jahr, Monat und Tag eingeben zum
    * Herausfinden des Wochentags */
   printf("Jahr : ");
   scanf("%d", &year);
   printf("Monat: ");
   scanf("%d", &month);
   printf("Tag  : ");
   scanf("%d", &day);

   /* Wir füllen unsere Struktur struct tm time_check
    * mit Werten. */
   time_check.tm_year = year - 1900;
   time_check.tm_mon = month - 1;
   time_check.tm_mday = day;

   /* 00:00:01 Uhr */
   time_check.tm_hour  = 0;
   time_check.tm_min   = 0;
   time_check.tm_sec   = 1;
   time_check.tm_isdst = -1;

   if(mktime(&time_check) == -1)
      time_check.tm_wday = 7;  /* = unbekannter Tag */


   /* Der Tag des Datums wird ausgegeben. */
   printf("Dieser Tag ist/war ein %s\n",
      wday[time_check.tm_wday]);
   return EXIT_SUCCESS;
}

»asctime()« und »ctime()« – Umwandeln von Zeitformaten in einen String

Mit zwei Funktionen können die beiden Zeitformen struct tm und time_t in einen String konvertiert werden. Hier sehen Sie die Syntax der beiden:

char *asctime(struct tm *zeitzeiger);
char *ctime(const time_t *zeitzeiger);

Auch dazu ein kleines Beispiel in einem Listing:

/* time4.c */
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char **argv) {
   FILE *datei;
   time_t time1;
   struct tm *time2;
   char zeit[25];
   int c;

   if(argc<2) {
      printf("Bitte eingeben : %s textdatei.txt\n",*argv);
      return EXIT_FAILURE;
   }
   if((datei = fopen(*++argv,"w+")) == NULL) {
      printf("Konnte Datei : %s nicht öffnen!!!!\n",*argv);
      return EXIT_FAILURE;
   }
   printf("Eingabe machen (mit '#' beenden)\n>");
   /* Wir schreiben in unsere Datei und beenden diese
    * mit dem Zeichen '#'. */
   while((c=getchar()) != '#')
      putc(c, datei);
   putc('\n', datei);

   /* zuerst time_t-Format */
   time(&time1);
   printf("Heute ist %s und Sie haben eben die "
          "Datei %s geschlossen\n",ctime(&time1), *argv);

   /* jetzt struct tm-Format mit asctime() */
   time1=time(NULL);
   time2=localtime(&time1);
   strcpy(zeit,asctime(time2));

   /* Das Datum schreiben wir in die Datei ... */
   fprintf(datei,"%s\n",zeit);
   fclose(datei);
   return EXIT_SUCCESS;
}

Dieses Listing gibt zum einen das heutige Datum mit der Funktion ctime() auf dem Bildschirm aus und schreibt zum anderen den Rückgabewert der Funktion asctime() in eine Textdatei.

»difftime()« – Differenz zweier Zeiten

Wird eine Differenz zwischen zwei Zeiten benötigt, lässt sich diese mit der folgenden Funktion ermitteln:

double difftime(time_t zeit1, time_t zeit0);

Diese Funktion liefert die Differenz von zeit1 minus zeit0 als double-Wert zurück. Hierzu ein einfaches und kurzes Beispiel:

/* time5.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
   time_t start, stop;
   double diff;

   printf("Einen Augenblick bitte ...\n");
   start=time(NULL);
   while((diff=difftime(stop=time(NULL),start)) != 5);
   printf("%.1f sek. vorbei!!\n",diff);
   return EXIT_SUCCESS;
}

Das Programm wartet fünf Sekunden, bis es einen entsprechenden Text ausgibt. Bei

while((diff=difftime(stop=time(NULL),start)) !=5);

wurde die Funktion time() gleich in der Funktion difftime() ausgeführt. Natürlich ist dies nicht so gut lesbar, aber es erfüllt denselben Zweck wie:

while((diff=difftime(stop,start)) != 5)
   stop=time(NULL);

»clock()« – Verbrauchte CPU-Zeit für ein Programm

Eine weitere häufig gestellte Frage lautet: Wie kann ich herausfinden, wie lange das Programm schon läuft? Sie können dies mit folgender Funktion ermitteln:

clock_t clock(void);

Diese Funktion liefert die verbrauchte CPU-Zeit seit dem Programmstart zurück. Falls die CPU-Zeit nicht verfügbar ist, gibt die Funktion –1 zurück. Wenn Sie die CPU-Zeit in Sekunden benötigen, muss der Rückgabewert dieser Funktion durch CLOCKS_PER_SEC dividiert werden; Beispiel:

/* runtime.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
   clock_t prgstart, prgende;
   int c;

   prgstart=clock();
   printf("Geben Sie etwas ein, und beenden Sie mit #\n");
   printf("\n > ");
   while((c=getchar())!= '#')
      putchar(c);
   prgende=clock();
   printf("Die Programmlaufzeit betrug %.2f Sekunden\n",
      (float)(prgende-prgstart) / CLOCKS_PER_SEC);
   return EXIT_SUCCESS;
}

Abbildung 19.2 Verbrauchte Zeit eines Programms mit »clock()« ermitteln

Damit dürfte es Ihnen nicht schwerfallen, die Nutzungsdauer eines Programms herauszubekommen.

»strftime()« – »struct tm« in einen benutzerdefinierten String umwandeln

Als Nächstes folgt eine Funktion, die Sie als die sprintf()-Funktion für Zeit- und Datumswerte ansehen können. Die Syntax lautet:

size_t strftime(char * restrict puffer, int maxzeichen,
                const char * restrict format,
                struct tm * restrict zeitzeiger);

So kann die Kalenderzeit aus struct tm *zeitzeiger in einem entsprechenden Format in die Adresse puffer geschrieben werden. Folgende Umwandlungsvorgaben können Sie dabei verwenden:


Tabelle 19.3 Formatierungszeichen für eine benutzerdefinierte Zeitangabe

Format … wird ersetzt durch … Beispiel
%a

Wochenname (gekürzt)

Sat

%A

Wochenname (ausgeschrieben)

Saturday

%b

Monatsname (gekürzt)

Jan

%B

Monatsname (ausgeschrieben)

January

%c

entsprechende lokale Zeit- und Datumsdarstellung

Thu Jun 11 22:22:22 MET 2009

%d

Monatstag (1–31)

22

%H

Stunde im 24-Stunden-Format (0–23)

23

%I

Stunde im 12-Stunden-Format (1–12)

5

%j

Tag des Jahres (1–366)

133

%m

Monat (1–12)

5

%M

Minute (0–59)

40

%p

AM- oder PM-Zeitangabe; Indikator für das 12-Stunden-Format (USA)

PM

%S

Sekunden (0–69)

55

%U

Wochennummer (0–53; Sonntag als erster Tag der Woche)

33

%w

Wochentag (0–6, Sonntag = 0)

3

%W

Wochennummer (0–53; Montag als erster Tag der Woche)

4

%x

lokale Datumsdarstellung

02/20/09

%X

lokale Zeitdarstellung

20:15:00

%y

Jahreszahl (ohne Jahrhundertzahl 0–99)

09 (2009)

%Y

Jahreszahl (mit Jahrhundertzahl YYYY)

2009

%Z, %z

Zeitzone (gibt nichts aus, wenn Zeitzone unbekannt)

MET

%%

Prozentzeichen

%



Hinweis

Bei einigen Compilern (beispielsweise GNU-GCC) findet man noch mehr von diesen Umwandlungszeichen. Hierzu will ich Sie allerdings auf die entsprechende Manual-Page von strftime() (http://linux.die.net./man/3/striftime) verweisen.



Hinweis

Zu strftime() gibt es mit wcsftime() auch noch ein Gegenstück für breite Zeichen. Die Funktion entspricht im Grunde der von strftime(), nur dass der Formatstring ein String mit breiten Zeichen ist. Auch die maximale Länge (zweiter Parameter) ist hierbei die Anzahl der breiten Zeichen und nicht die Anzahl von Bytes.


Das folgende Listing zeigt, wie diese Angaben verwendet werden können:

/* time6.c */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
   struct tm *zeit;
   time_t sekunde;
   char string[80];
   time(&sekunde);
   zeit = localtime(&sekunde);
   strftime(string, 80,
   "Es ist %H Uhr und %M Minuten (%Z) %A, %B %Y",zeit);
   printf("%s\n",string);
   return EXIT_SUCCESS;
}

Es wird übrigens empfohlen, bei der formatierten Zeitausgabe des Jahres %Y statt %y zu verwenden, um Probleme mit dem Datum ab dem Jahr 2000 zu vermeiden.

Abbildung 19.3 fasst alle Funktionen, die Sie hier kennengelernt haben, anhand ihrer Beziehungen zueinander zusammen.

Abbildung 19.3 Datums- und Zeitfunktionen im Überblick



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: C/C++






 C/C++


Zum Katalog: Einstieg in C






 Einstieg in C


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de