Hallo,
das Überspringen einer Einheit in der for-Schleife habe ich eingefügt, wenn die Bezeichnung (Bez) der aktuellen Einheit gleich dem leeren String ist. Wenn ich nämlich von 0 nach High(n) durchlaufe ohne die Abfrage, dann ist es mir passiert, dass der erste und letzte n[i].Bez ein leerer String war.
Das Ergebnis von dieser Prozedur...
Delphi-Quellcode:
for i := 0 to High(n) do
begin
ShowMessage(n[i].Bez);
end;
ist
''
'ms'
'sec'
'min'
'hrs'
'day'
''
.
Ich könnte dann i von 1 bis High(n)-1 durchlaufen lassen, aber die Abfrage dient eher zur Sicherheit (vielleicht ein kleiner Schönheitsfehler).
Hier nochmal der Code mitErklärung:
Delphi-Quellcode:
function ZeitString(msec: integer):
string;
type
Einheit =
record // definiere einen record beliebiger Einheiten, die sich um Vielfache entsprechen
Bez:
string;
// Name der Einheit
Mul: integer;
// Faktor zur Vorherigen Einheit (Bsp: Stunde->Tag = 24, weil 24hrs=1day)
Bek: integer;
// Faktor zur ursprünglichen Einheit (ms). z.B. von Minute ist es 60*1000
Res: integer;
// Wie viel in msec von der jeweiligen Einheit drin sind
end;
const
p = '
, ';
// Trenner zur nächsten Einheit
var
n:
array of Einheit;
// Da sind alle Einheiten drin
c: integer = 1;
// gibt die Größe des Arrays an
i, j, u, a: integer;
// Hilfsvariablen
procedure SetN(ABez:
string; AMul: integer);
// Hiermit kann man eine neue Einheit hinzufügen
begin
SetLength(n, c + 2);
// Zuerst den Array vergrößeren (das ganz oben genannte Problem könnte auch hierher kommen, weil ich die Länge auf c+2 setze, bei c+1 oder gar c gibts aber Access violation)
n[c].Bez := ABez;
// einfach die Bezeichnung setzen
n[c].Mul := AMul;
// und hier den entsprechenden Faktor (Erklärung oben beim record)
Inc(c);
// für weitere Hinzufügungen um eins vergrößeren, damit die anderen reinpassen
end;
begin
Result := '
';
// hier kann man ganz einfach Einheiten hinzufügen, so wie es schon erkannt wurde - ganz toll erweiterbar!
SetN('
ms', 1);
SetN('
sec', 1000);
SetN('
min', 60);
SetN('
hrs', 60);
SetN('
day', 24);
//...
// Zunächst bekommt jeder seinen Faktor zur msec (Bsp sec:1000,min:60*1000,hrs:60*60*1000)
// Um diese Multiplikationen hinzubekommen, beziehe ich mich immer wieder auf das vorherige j (Hilfsvar.)
j := 1;
for i := 0
to High(n)
do
begin
if n[i].Bez = '
'
then
Continue;
j := j * n[i].Mul;
// hier wird der Faktor zur msec berechnet
n[i].Bek := j;
// ...und gesetzt
end;
// u bedeutet "übrig", was also noch vergeben werden muss.
// Wenn ich z.B. 9999 habe (in msec natürlich) sind das natürlich 9sek, aber jetzt sind nur noch 999 übrig.
u := msec;
for i := High(n)
downto 0
do // von der größten Einheit beginnen (zuerst also schauen, ob ganze! Tage drin sind)
begin
if n[i].Bez = '
'
then
Continue;
n[i].Res := u
div n[i].Bek;
// hier kommt die "Res" ins Spiel: div gibt nämlich den Ganzzahl-anteil an
u := u
mod n[i].Bek;
// mit Modulo kriegt man den Rest bei der Division, so kann ich sicherstellen, dass alles richtig verbraucht wird.
end;
for i := High(n)
downto 0
do // jetzt schließlich das Ergebnis ausgeben
begin
if n[i].Bez = '
'
then
Continue;
a := n[i].Res;
if (a <> 0)
then // genau diese Zeile (Abfrage ob Null-Werte sein sollen) könnte man nach Furtbichler streichen, wenn man es will
Result := Result + IntToStr(a) + '
' + n[i].Bez + p;
end;
Result := HintenEntfernen(Result, p);
// letzte ', ' entfernen. Das war's
end;
noch ein Beispiel:
ZeitString(1234567890) = 14 day, 6 hrs, 56 min, 7 sec, 890 ms
Hoffentlich ist es jetzt nachvollziehbarer.
Grüße