Einzelnen Beitrag anzeigen

thomasschaf
(Gast)

n/a Beiträge
 
#7

AW: Vorstellung des Codes zur übersichtlichen Anzeige von Zeiten

  Alt 26. Mär 2012, 12:09
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
  Mit Zitat antworten Zitat