B.14    Antworten und Lösungen zu Kapitel 15

Das Programm wochentag.c gibt den Wochentag zu einem bestimmten Datum aus. Hierzu werden die Funktionen der Standardbibliothek time.h benutzt, die sowohl auf Windows, als auch auf UNIX-Derivaten wie beispielsweise Linux laufen. Es folgt hier das Listing zu wochentag.c

00  // Kapitel15/wochentag.c
01 #include <stdio.h>
02 #include <stdlib.h>
03 #include <time.h>

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

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

11 /* Jahr, Monat und Tag eingeben zum
12 * Herausfinden des Wochentags */


13 printf("Jahr:");
14 scanf("%d",&year);
15 printf("Monat:");
16 scanf("%d",&month);
17 printf("Tag:");
18 scanf("%d",&day);

19 /* Wir füllen unsere Struktur struct tm time_check
20 * mit Werten. */


21 time_check.tm_year = year - 1900;
22 time_check.tm_mon = month - 1;
23 time_check.tm_mday = day;

24 /* 00:00:01 Uhr */

25 time_check.tm_hour = 0;
26 time_check.tm_min = 0;
27 time_check.tm_sec = 1;
28 time_check.tm_isdst = -1;

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

31 /* Der Tag des Datums wird ausgegeben. */

32 printf("Dieser Tag ist/war ein %s\n", wday[time_check.tm_wday]);
33 return 0;
34 }

Listing B.1    wochentag.c gibt zu einem bestimmten Datum den Wochentag als Text aus.

Die Standardbibliothek time.h bietet keine Unterstützung für Wochentage in Textform, weil es viel zu viele Sprachen gibt, die hier unterstützt werden müssten. Und selbst, wenn dies der Fall wäre, könnten Sie ja durchaus ein Rollenspiel-Adventure programmieren, das Ihre Charaktere aus Mittelerde Elfisch sprechen ließe, und schon hätten Sie wieder neue Text-Ausdrücke für die Wochentage.

Die Lösung, die in dieser Übung verwendet wird, ist das globale Array char *wday[], das in den Zeilen Zeilen (04) bis (07) definiert wird. Das Array wday[] ist eine String-Tabelle, welche die Textform für die Wochentage enthält, angefangen mit dem Sonntag. Der Sonntag bekommt also standardmäßig den Wert 0 zugeordnet, der Montag den Wert 1.

Das Hauptprogramm definiert nun in den Zeilen (09) und (10) zunächst die Variable struct tm time_check und liest anschließend in den Zeilen (13) bis (18) das Jahr, den Monat und den Tag mit scanf() von der Tastatur ein. Diese Angaben werden in den Variablen year, month und day gespeichert. Wir benutzen hier die englischen Begriffe, weil diese Benennung auch dem aktuellen C18-Standard entspricht.

Nach dem Einlesen des aktuellen Datums über die Tastatur in Form von Jahr, Monat und Tag wird nun die Strukturvariable time_check so mit den Benutzereingaben gefüllt, dass Sie später mit time_check weitere Berechnungen ausführen können. Hierzu dienen die Zeilen (21) bis (23):

time_check.tm_year = year - 1900;
time_check.tm_mon = month - 1;
time_check.tm_mday = day;

Wir sehen an dieser Stelle, dass die Zeitfunktionen in time.h erstens die Jahre ab dem Jahr 1900 zählen (wir müssen also von year 1900 subtrahieren) und zweitens dem Januar mit den Wert 0 zuordnen (wir müssen also von month 1 subtrahieren). Die Werte für den Tag müssen wir nicht mehr korrigieren, dies haben wir schon dadurch erreicht, dass das globale Array wday[] mit dem Sonntag beginnt. In den folgenden Zeilen (Zeile (24) bis (28)) setzen wir dann einfach die Uhrzeit in der Strukturvariablen time_check auf 0 Uhr Mitternacht. Eigentlich interessieren uns die Uhrzeitangaben nicht, wir müssen diese aber trotzdem hier einsetzen, weil die Ausgabe des Wochentages an dieser Stelle nur mit einer vollständig gefüllten Struktur vom Typ tm funktioniert.

Bis hierhin enthält das Listing wochentag.c eigentlich nur Standardfunktionen, wie scanf() und das Eintragen von Elementen in Strukturvariablen. Die eigentliche Arbeit leistet am Schluss folgende Funktion:

time_t mktime (struct tm * timeptr)

Die Funktion mktime() konvertiert eine Variable vom Typ struct tm in eine Variable von Typ time_t. Der Parameter *timeptr wird hier als Zeiger übergeben, deshalb kann mktime() fehlende Angaben (wie z. B. hier den Wochentag) automatisch ergänzen. Dies geschieht in unserem Beispiel in Zeile (29) und (30):

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

Hier wird auch mit if(mktime(&time_check)==-1) gleich geprüft, ob das eingegebene Datum einen gültigen Wochentag zurückliefert. Ist dies der Fall, dann enthält die Variable time_check am Ende einen gültigen Wochentag. Ist dies nicht der Fall, liefert mktime() den Wert -1 zurück. In diesem einfachen Beispiel werden allerdings ungültige Eingaben nicht abgefangen, sondern es wird in Zeile (32) direkt der Wochentag zu dem eingegebenen Datum ausgegeben. Dies ist deshalb ohne weiteres möglich, weil wir das Array wday[] so gewählt haben, dass dieses genau die Wochentag-Nummern verwendet, die mktime() automatisch ergänzt. Das Programm wochentag.c gibt bei der Ausführung z. B. Folgendes aus:

Jahr:2020
Monat:04
Tag:24
Dieser Tag ist/war ein Freitag