Hi
Und zwar soll ich aus der Datei in der die Daten stehen die Gesamt-Differenz zwischen den Start- und Endzeiten bestimmten.
Dafür müsstest du ja die Datei lesen - tust du aber in deinem Code nicht wirklich. Hier macht es Sinn, sich um die Dateistruktur Gedanken zu machen. Momentan schreibst du überraschend viel und öffnest die Dateien viel zu oft - in deinem rein sequentiellen Programm ist das kein Problem, aber alleine schon, um sich auf eine eventuelle Parallelisierung vorzubereiten, lohnt es sich, das zu überdenken.
Bspw. kannst du menschenlesbare Daten schreiben, etwa
Code:
start:<Zeit>
end:<Zeit>
diff:<Zeit>
Dann kannst du alles mittels
C:
fscanf(f, "%[^:]:%[^\n]", type, value); //"%[^:]" heisst: Lies den String, bis ein ':' auftritt (Genauer: Lies alles, was nicht (^) ':' ist). Analog für '\n'.
//Verzweigung nach type
if(strcmp(type, "start") == 0) /*...*/;
Man bemerke: Da (end - start = diff) sind die Informationen redundant: Wir haben 1 Gleichung und keine Unbekannten. Wir können das entweder ignorieren und ggf. als Prüfwert verwenden, oder aber wir können einen beliebigen Wert streichen und jeweils rekonstruieren.
Du kannst zudem überlegen, ob du die Zeiten tatsächlich als asctime speichern willst - für Menschen sind die Dinger leichter lesbar, aber die Maschine hat nix davon. Du kannst dir überlegen, ob du nicht einfach nur das time_t als 64bit-Wert direkt in die Datei speichern und jeweils für die menschenlesbare Ausgabe konvertieren willst.
Ich weiß nicht wie ich alle Startzeiten/ Endzeiten addiere und dann davon die Differenzzeit bilden soll.
Die Summe aller Startzeiten ist S_S, die Summe aller Endzeiten S_E, die Summe aller Differenzen S_D.
Also ist (S_E - S_S = S_D). Es gilt aber auch: S_D = Sum(diff) = Sum(end - start).
Du musst also nicht alle Startzeiten und alle Endzeiten addieren (das ist auch keine gute Idee; da die Zeit >> Diff (Zeit sehr viel grösser als die Differenz), sind Overflows sehr viel wahrscheinlicher), sondern du kannst auch nur alle Differenzen addieren.
Zudem soll es auch möglich sein mehrere Start-, sowie End Zeiten hintereinander einzulesen.
Es ist recht schwierig, das optimal zu gestalten. Aber damit dies überhaupt funktioniert, musst du irgendeine Art Schlüssel haben - eine ID für jede "Person", die sich ein- oder austrägt. Und jetzt funktionieren deine Dateizugriffe definitiv nicht mehr. Entweder, du speicherst bei jedem start und end die ID mit (chronologisch nach Event), oder du schreibst die Blöcke pro ID (chronologisch nach Austragung der ID). Du brauchst dafür sowas wie
C:
typedef struct {
unsigned int ID;
time_t start;
time_t end;
} entry;
für jede ID und du müsstest die Startzeit speichern, bis sich jemand austrägt, und dann alle Informationen auf einen Schlag schreiben. Damit das einigermassen flott geht, bietet sich ein Hashtable (gepimpter Array), hier ggf. mit Listenerweiterung, an. Als Eingabe für scanf() ist entsprechend eine ID anzugeben.
Kurze Erläuterung, bei weiteren Fragen einfach nachfragen:
Ein Array hat n Elemente, die irgendwie gefüllt werden können. Aber wenn du n Elemente hast und ein bestimmtes Element suchst, kann es sein, dass du n Elemente vergleichen musst - das ist doof, weil langsam. In Hashtabellen beinhaltet der Index einen Teil der Information. Bspw. kann man faulerweise eine ID modulo 10 rechnen, also nur die letzte Ziffer berücksichtigen.
Bei einer Tabelle mit 10 Elementen ist die ID mit der letzten Ziffer "5" also am Index 5, in C:
C:
table[ID % 10] = /*...*/;
Das ist sehr schnell (man weiss immer, wo eine ID hinkommt und falls man eine ID sucht, weiss man, wo sie sein muss).
Dummerweise gibt es mehrere IDs an derselben Stelle, z.B. käme damit 10 an dieselbe Stelle wie 0, 20, 30, ... (abzählbar viele).
Dies nennt man eine (Hash-)kollision. Die ist doof; die mögen wir nicht. Eine einfach Lösung? Verdoppeln wir die Grösse der Tabelle! Dann haben wir x % 20 als Hashfunktion und haben nur noch halb so viele Kollisionen - die sind aber (theoretisch) noch immer unbegrenzt viele. So viel Speicher haben wir aber nicht, ergo können wir die Tabelle nicht ewig vergrössern.
Es gibt mehrere Lösungen für dieses Problem: Bei statistisch gleichmässiger Verteilung (z.B. Jeden Tag kommen 10 Leute mit beliebiger ID) ist es relativ wahrscheinlich, dass Kollisionen auftreten, aber wir haben in einer Hashtabelle der Grösse 10 sicher genug Platz, also kann man sondieren; die Position also immer gleich verschieben, bis Platz ist. Bei dieser Art von Verteilung ist linear wohl am Besten, bei anderen ist quadratisches Sondieren zu bevorzugen.
Da man aber nicht so ganz weiss, wie viele Leute tatsächlich arbeiten gehen, lohnt sich die Listenform eher.
Dann ist "in" jedem Tabelleneintrag eine Liste von Arbeitern; wir verteilen quasi die Liste aller Arbeiter auf kleinere Listen, die gewisse Eigenschaften (eben z.B. unterschiedliche letzte Ziffern) haben.
Doof dabei: Listen sind miserabel für Computer. Sie sind indirekt (erfordern Dereferenzierung) und sind nicht / nur schlecht parallelisierbar, da man für das n-te Element n Schritte machen muss. Bei Arrays kannst du einfach mit einer Zahl (dem Index) auf den Wert zugreifen, also in einem Schritt. Bei intelligent gewählten Kritieren (und Grösse) der Hashtabelle sollte es aber möglich sein, die Listen möglichst kurz zu halten, sodass dies nicht ins Gewicht fällt.
Dein Ansatz mit Arrays mit 200 Elementen kann funktionieren, aber wie schon angetönt geht das ins Unendliche (was, wenn jemand 201 Mitarbeiter hat? 202? 203? 10123159859173?). Eine Liste ist auf jeden Fall notwendig, und sei es nur, um diejenigen abzufangen, die im (schnelleren) Array keinen Platz mehr haben.
(Mir ist schon klar, dass das eine Übungsaufgabe ist und entsprechend nicht alles so genau genommen werden muss, aber es ist wohl besser, schon früh eine Aufmerksamkeit für diese Probleme zu entwickeln)
Jedenfalls: Beide Dateiformate sind gleichwertig, Konvertierungen sind also problemlos möglich; das "bessere" Format kommt ein bisschen darauf an, ob der Fokus auf Tagesablauf (chronologische Ordnung) oder Arbeitnehmer (Ordnung nach ID) liegt.
Die folgende Aufteilung ist übrigens auch nicht optimal:
C:
fprintf(fp, "end ");
fprintf(fp, asctime(localtime(&end_t)));
//Geht als
fprintf(fp, "end %s", asctime(localtime(&end_t)));
//...in einem Aufruf (schneller). Analog bei der anderen Stelle.
Gruss
cwriter