Hallo Zusammen!
Ich habe das Problem, dass ich nicht weiß und nicht herausfinde, wie man aus einer 1 → 01 macht
Ich möchte ein Output geben wo vorne eine Nummerierung ist. Aber da hapert es.
Was muss ich wo hinzufügen, dass das folgendermaßen aussieht:
01
02
03
04
05
06
07
08
09
10
11
...
Danke im Vorraus!
Grüße
Ben
Vorkommastellen
Re: Vorkommastellen
Ich nehme an, dass 1, 2, 3, ... in deinem Beispiel Integer sind. Diese kannst du mit der FormatFloat-Funktionen in einen String umwandeln, der wie gewünscht aussieht, wenn du die Formatmaske '00' verwendest. Jede '0' ist dabei ein Platzhalter, der durch die Ziffern der zu wandelnden Zahl ersetzt wird, oder unverändert bleibt, wenn die Zahl dort keine Ziffer hat. Wenn die Zahl mehr Stellen hat als die Maske, werden die zusätzlichen Ziffern zusätzlich in den Ausgabestring aufgenommen.
Also: Aus 1 wird '01', aus 12 wird '12', aus 135 wird '135'.
Also: Aus 1 wird '01', aus 12 wird '12', aus 135 wird '135'.
Code: Alles auswählen
program Project1;
uses
SysUtils;
var
i: Integer;
begin
for i:=0 to 12 do
WriteLn(FormatFloat('00', i));
WriteLn(FormatFloat('00', 135));
ReadLn;
end.
- Winni
- Beiträge: 1577
- Registriert: Mo 2. Mär 2009, 16:45
- OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
- CPU-Target: 64Bit
- Wohnort: Fast Dänemark
Re: Vorkommastellen
Hi!
Oder selber machen:
Kurz und knapp.
Winni
Oder selber machen:
Code: Alles auswählen
function fillLeadingZeros ( Value, len : integer) : string ;
begin
result := IntToStr(Value);
while length(result) < len do result := '0'+result;
end;
Kurz und knapp.
Winni
-
- Beiträge: 1910
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Vorkommastellen
Winni hat geschrieben:Hi!
Oder selber machen:Code: Alles auswählen
function fillLeadingZeros ( Value, len : integer) : string ;
begin
result := IntToStr(Value);
while length(result) < len do result := '0'+result;
end;
Kurz und knapp.
Winni
Nein das willst du nicht machen. Mal ganz davon abgesehen das das ganze nicht korrekt ist (beispiel fillLeadingZeros (-2, 3) wird zu 0-2), macht dein Code string konkatination im loop, was ein echter performance Killer ist.
Der Grund dafür ist das folgende, bei jeder String konkatination passiert das:
Code: Alles auswählen
function ConcatStrings(const str1: string; const str2: String): String;
begin
SetLength(Result, Str1.Length + Str2.Length);
Move(str1[1], Result[1], str1.length);
Move(str2[1], Result[str1.length], str2.length);
end;
Das alloziieren des neuen speichers ist sehr teuer (im vergleich dazu sind die beiden Moves vernachlässigbar), denn der Memory-Manager führt eine First-Fit suche über den Speicher aus. Der FPC Memory Manager hat den Vorteil das er nicht so einfach fragmentiert, was bedeutet das nach einer gewissen laufzeit das ganze nicht extremst langsam wird (was ein vorteil für solche konkatinationen ist), allerdings braucht es trozdem zeit, und selbst auf einem nicht fragmentierten systemm willst du das wenn möglich vermeiden, und vor allem nicht in einem loop machen. Wenn möglich willst du lieber direkt von anfang an die korrekte menge Speicher alloziieren
Wenn du etwas hinten dran hängen würdest, wäre das nicht ganz so schlimm, da dann der string nur extended werden müsste, was bedeutet das du nur setlength + den zweiten move ausführen müsstest, da sich der anfang ja nicht ändert. Da du aber vorn anhängst, muss zu erst der speicher erweitert werden, dann der inhalt nach hinten gezogen werden, und schließlich der neue Inhalt vorne hin kopiert werden muss.
Das ist aber alles nicht notwendig, die länge eines integers ist Ceil(log10(value+1)) und damit effizient berechenbar (zumindest effizienter als jede memoryoperation, und eine integer log10 funktion lässt sich im notfall auch noch effizienter bauen als die float funktion die math bietet). Leider bietet der FPC keine inplace konvertierungsfunktion wie C's itoa funktion an (natürlich könnte man gegen die libc linken, aber damit hat man mehr probleme als das es hilft), aber FPC bietet die Str Funktion, welche einen String mit einer mindestlänge returned. Basteln wir also damit mal die Funktion:
Code: Alles auswählen
function FillLeadingZerosStr(Value: Integer; len: Integer): String; inline;
var
i: Integer;
begin
Str(Value:len, Result);
for i:=1 to len do
if Result[i] = ' ' then
Result[i] := '0'
else
break;
end;
Wohlgemerkt die Funktion ist immernoch genauso kaputt wie deine funktion (also -2, 3 gibt 0-2), aber fast 3 mal so schnell
Das ist aber nur die Lösung wenn Geschwindigkeit relevant ist, dann sollte man es halt selbst machen (aber dann auch nicht mit sinnlosen String Konkatinationen, sondern richtig).
Wenn Geschwindigkeit nicht relevant ist, tuts auch der Einzeiler mit Format. Wenn man keine floats braucht kann man auch den folgenden Format-Befehln nutzen:
Code: Alles auswählen
Result := Format('%.*d', [len, Value]);
Damit wird die Zahl value auf len stellen gepadded. Mit Format ist ein gutes stück langsamer (etwa 80% langsamer als deine Funktion) dafür aber ist man flexibler als mit einer eigens geschriebenen Funktion (grade wenn man es auf Floats mit FormatFloat erweitern will), und es hat natürlich den Charme das es ein Einzeiler ist.
Je nachdem für was man es braucht lohnt es sich das ganze selbst zu schreiben, aber in den allermeisten Fällen ist Format nicht nur ausreichend, sondern mit der Flexibilität und der Robustheit (wie gesagt, deine Funktion ist allein schon kaputt), oftmals genau das was man will