![]() |
String vorne mit Nullen auffüllen
Hallo ich möchte ein String mit variabler Länge immer bis zur einer bestimmten Länge vorne mit 0 auffüllen. habe dazu folgende Function:
Delphi-Quellcode:
aufrufen der Function:
function FillString(AString: String; AChar: Char; ALength: integer): String;
var i:integer; begin FillChar(Result, ALength, Ord(AChar)); Result := copy(AString, 1, ALength) + copy(Result, ALength - Length(AString), ALength); end;
Delphi-Quellcode:
leider bekomme ich beim Aufruf der function eine Exception. Exception-Klasse $C0000005 mit Meldung 'access violation at 0x0040e4c6: read of address 0x3030302c
BelegNr := FillString(BelegNr,'0',9);
was ist da falsch? |
AW: String vorne mit Nullen auffüllen
|
AW: String vorne mit Nullen auffüllen
1. Es gibt dafür bereits existierende Funktionen, die das machen.
2. In deinem Code schreibst du in einen nicht allozierten Speicher und erhälst dadurch die AV. Den Result String musst du zuerst entsprechend allozieren, bevor du da ein FillChar machst. Also einfach ein SetLength(Result, ALength) davor einfügen. 3. Mach aus dem ersten Parameter eine Const Parameter. Das solltest du für allen String Parameter machen, die du in der Funktinon nicht veränderst. Ohne const wird der String bei jedem Aufruf der Funktion kopiert, während er bei einem const als Pointer übergeben wird und die Zeit für das Kopierren gespart wird.
Delphi-Quellcode:
function FillString(const AString: String; AChar: Char; ALength: integer): String;
var i:integer; begin SetLength(Result, ALength); FillChar(Result, ALength, Ord(AChar)); Result := copy(AString, 1, ALength) + copy(Result, ALength - Length(AString), ALength); end; |
AW: String vorne mit Nullen auffüllen
Hallo Rolf,
habe die Function geändert aber die Exception kommt immer noch. |
AW: String vorne mit Nullen auffüllen
Wenn es keine fertige Funktion gibt, dann:
Delphi-Quellcode:
Bis bald...
function FillStringLeft(const pmcSource: String; pmChar: Char; pmStrLen: Integer): String;
begin if Length(pmcSource) >= pmStrLen then Result := pmcSource else Result := Result.Create(pmChar, pmStrLen - Length(pmcSource)) + pmcSource; end; var sBelegNr: String; begin sBelegNr := '12345'; ShowMessage(FillStringLeft(sBelegNr, '0', 9)); Thomas |
AW: String vorne mit Nullen auffüllen
Zitat:
|
AW: String vorne mit Nullen auffüllen
oder total oldschool:
Delphi-Quellcode:
function FillString(AString: String; AChar: Char; ALength: integer): String;
var i:integer; s: string; begin if Length(AString) > ALength then Exit(AString); s := ''; for i := 0 to Pred(ALength - Length(AString)) do s := s + AChar; Result := s + AString; end; |
AW: String vorne mit Nullen auffüllen
Weiß nicht mehr woher ich das habe, aber hier ein Einzeiler
Delphi-Quellcode:
function AddLeadingZeroes(const aNumber, aFinalLength: Integer): string;
begin Result := System.SysUtils.Format('%.*d', [aFinalLength, aNumber]); end; |
AW: String vorne mit Nullen auffüllen
Ja, hier ist nicht das Delphi-Char gemeint, sondern das Char der C-Welt und dort heißt es "Byte".
Bissl verwirrend. Früher hatte ich für sowas ![]() Wobei, wenn BelegNr eine "Nummer" ist, dann einfach dem ![]() [edit] @DieDolly: jupp. [/edit]
Delphi-Quellcode:
S := S.PadLeft(10, '0');
S := StringOfChar('0', 10 - Length(S)) + S; S := string.Create('0', 10 - S.Length) + S; // es geht auch andersrum, aber sowas will niemand machen S := Copy('0000000000', 1, 10 - Length(S)) + S; S := Copy('0000000000', Length(S) + 1) + S; |
AW: String vorne mit Nullen auffüllen
Danke an alle jetzt funktioniert es.
Function von mytbo habe ich jetzt benutzt. |
AW: String vorne mit Nullen auffüllen
@mytbo: statt Result.Create besser string.Create verwenden.
Du erzeugst einen neuen String und mit dem Result hat es eigentlich garnichts zu tun, abgesehn von dem Typ dieser Variable. Funktionell geht es hier zwar, aber syntaktisch ist es eher fragwürdig missverständlich und in anderen Fällen auch fehleranfällig. Zum Glück ist es hier aber kein schlimmer "Fehler". Anders sieht es z.B. bei dem anderen syntaktisch gleichen Problem aus, wo es bei sowas ganz böse knallen kann/wird. MyClass.Create anstatt TMyClass.Create aka Variable.Create anstatt Class.Create, weil hier kommt der Typ aus dem, auf was die Variable zeigt und nicht aus der Variablen-Deklaration selber. @Walter: In mytbo's Code, entspricht die Schleife dem StringOfChar bzw string.Create und die ganze Funktion entspricht dem PadLeft. Vorallem die Schleife, bzw. die unnötig vielen String-Operationen darin, sind eher suboptimal. Man kann es machen, aber man kann auch die manuellen Codes durch etwas ersetzen, was es bereits fertig gibt. (vor allem, da Diese hier sogar optimaler arbeiten) |
AW: String vorne mit Nullen auffüllen
Zitat:
Bis bald... Thomas |
AW: String vorne mit Nullen auffüllen
Zitat:
|
AW: String vorne mit Nullen auffüllen
Upss. (ein Zwerg)
Joar, aber der String heißt "Nummer" :lol: OK, fast überall ist er dennoch ein String. |
AW: String vorne mit Nullen auffüllen
Zitat:
Zitat:
Delphi-Quellcode:
Rein historisch betrachtet ist es sehr schnell.
function FillString(const AString: AnsiString; const AChar: AnsiChar; const ALength: Integer): AnsiString;
var Len: Integer; begin Len := ALength - Length(AString); // padding "berechnen" if (Len > 0) then // kurzer check begin SetLength(Result, ALength); // länge setzen FillChar(Result[1], Len, AChar); // padding einfügen Move(AString[1], Result[Succ(Len)], Length(AString)); // zusammenfügen end else Result := AString; // das original so belassen end; Ich bete das mir da kein Fehler unterlaufen ist :twisted: |
AW: String vorne mit Nullen auffüllen
Das mit dem Fillchar und dem String war mir beim schreiben ganicht aufgefallen, ist aber natürlich korrekt. Fillchar darf hier nicht verwendet werden. Da gibt es eine andere Funktion "StringOfChar()" dafür:
Delphi-Quellcode:
function FillString(const AString: String; AChar: Char; ALength: integer): String;
var i:integer; begin Result := StringOfChar(AChar, ALength); Result := copy(AString, 1, ALength) + copy(Result, ALength - Length(AString), ALength); end; |
AW: String vorne mit Nullen auffüllen
Zitat:
Zitat:
Delphi-Quellcode:
Das klappt dann nebenbei auch mit UnicodeString.
function FillString(const AString: AnsiString; const AChar: AnsiChar; const ALength: Integer): AnsiString;
var Len: Integer; begin Len := ALength - Length(AString); Result := StringOfChar(AChar, Len) + AString; end; |
AW: String vorne mit Nullen auffüllen
@Dennis07 Weil meine AnsiString Variante um ein dutzendfach schneller ist.
|
AW: String vorne mit Nullen auffüllen
per se ist AnsiString und String/UnicodeString gleich schnell, bzüglich der Speicherverwaltung, da sie intern identisch sind.
Man darf nur nicht das *2 bzw. *SizeOf(WideChar) vergessen Wenn mann will, dann kann man in einen AnsiString auch Unicode rein tun (CP_UTF16) und andersrum auch ANSI in einen UnicodeString (auch wenn ich Letzteres nicht empfehlen würde). |
AW: String vorne mit Nullen auffüllen
Zitat:
//edit und der AnsiChar sollte dann natürlich ein WideChar bzw nur Char sein |
AW: String vorne mit Nullen auffüllen
Dennis07, wieso hast du den ersten Parameter auf einen AnsiString geändert? Die Funktion StringOfChar gibt es für Ansi und Unicode und somit läuft die Funktion mit dem String Typ tadellos.
|
AW: String vorne mit Nullen auffüllen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Um ein ein relevantes Ergebnis zu haben habe ich beide Funktionen je 100.000 mal hintereinander mit zufälligen Strings und einem '0'-Zeichen durchlaufen lassen und habe zufällige Einrückungen im selben Spektrum genommen. Das ganze habe ich 100 mal durchlaufen lassen und den Durchschnitt gebildet. Die Ergebnisse siehst du im Anhang. Gerne gebe ich dir den Quelltext, damit du es selbst probieren kannst. FillString1 ist von dir, FillString2 ist meine Variante. In dem Beispiel war deine um ca. 2 Ticken schneller bei der Aufrufzahl, was mich jetzt nicht überrascht hat. Kann aber auch an ungleichen Zufallszahlen liegen, wer weiß. Es geht mir jetzt halt nicht darum, deinen Code schlecht zu reden oder so, nichts läge mir ferner. Aber ich wollte mich selbst davon überzeugen, dass der unter Win32 auf keinen Fall "dutzendfach langsamer" ist. Selbst, wenn meiner jetzt schneller wäre, würden wir hier von durchschnittlich zwei Ticks pro 100.000 Aufrufen sprechen, was in so ziemlich allen Anwendungsgebieten wohl kaum ins Gewicht fallen würde. |
AW: String vorne mit Nullen auffüllen
Zitat:
|
AW: String vorne mit Nullen auffüllen
Zitat:
Weiterhin würde ich TStopWatch zur Messung nehmen. Das ist potentiell genauer. |
AW: String vorne mit Nullen auffüllen
Zitat:
|
AW: String vorne mit Nullen auffüllen
Die "Einfachste" ist doch wohl eher
![]() oder bei "Integer" ansatt String, das mit dem Format. ![]() ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz