![]() |
Delphi-Version: 2010
string inkrementieren
Hallo zusammen,
wahrscheinlich ist es nur eine Bagatelle aber ich suche nach einer Möglichkeit, eine Zahl, die in einem string gespeichert ist, zu inkrementieren. Beispiel: ZahlAlsString := '0470726'; die nächste Zahl sollte dann '0470727' sein. Das Problem hierbei für mich ist, wenn ich die Zahl als Integer umwandle verliere ich die führende Null. Da diese Zahl Bestandteil eines Barcodes sein soll muss die führende Null bleiben. Wie mache ich sowas, gibt's eine fertige Funktion oder hat jemand eine selbst geschriebene für mich? |
AW: string inkrementieren
Dann musst du die 0 bei der Rückwandlung in einen string halt wieder anfügen ( Format)
|
AW: string inkrementieren
merk dir wie viele Stellen der Barcode hatte. Dann umwandeln, erhöhen und dann mit Format und führenden 0en zurückwandeln.
Delphi-Quellcode:
function IncCode(Code: String): String;
var len: Integer; Val: Integer; begin len := Length(Code); Val := StrToInt(Code); inc(Val); Result := Format('%.'+IntToStr(Len)+'d',[Val]); end; |
AW: string inkrementieren
Zitat:
Zitat:
Würde dein String in ein Integer casten und dann inkrementieren und dann zurückwandeln. Schreib mir ne PM dann schick ich dir meine Methode. Ausser jmd will die hier sehen?! |
AW: string inkrementieren
Die wäre u.U. auch für andere interessant, obwohl Format() das ja auch kann
|
AW: string inkrementieren
..
Delphi-Quellcode:
procedure incBCStr(var AStr: string);
var i, l: Integer; begin l := Length(AStr); AStr := IntToStr(StrToInt64(AStr)+1); for i := Length(AStr) to l-1 do AStr := '0' + AStr; end; |
AW: string inkrementieren
Zitat:
|
AW: string inkrementieren
Zitat:
|
AW: string inkrementieren
Ich habe dafür eine Funktion, die
![]() Dabei gibt man an, auf wieviel Zeichen der String aufgefüllt werden soll (pad_size), mit welcher zeichenfolge aufgefüllt werden soll(pad_string) und dann noch, ob links oder rechts aufgefüllt werden soll (pad_type 0/1)
Delphi-Quellcode:
// pad a string to pad_size with pad_string characters (php-like)
function str_pad(const Input : string; pad_size : integer; const pad_string : string = '0'; const pad_type : Integer = 0) : string ; var i : integer; dif : Integer ; c: char ; begin Result := Input; if Length(Input) < pad_size then begin dif := pad_size - Length(Input) ; SetLength(Result,pad_size) ; case pad_type of // STR_PAD_LEFT 0: begin for i := 1 to dif do begin if i <= Length(pad_string) then c := pad_string[i] else c := pad_string[Length(pad_string)] ; Result[i] := c ; end; try for i := dif+1 to pad_size do Result[i] := Input[i-dif] ; except end; end; // STR_PAD_RIGHT 1: begin for i := Length(Input)+1 to pad_size do begin if i-dif <= Length(pad_string) then c := pad_string[i-dif] else c := pad_string[Length(pad_string)] ; Result[i] := c ; end; try for i := 1 to dif do Result[i] := Input[i] ; except end; end; end; end; end; |
AW: string inkrementieren
Zitat:
Delphi-Quellcode:
.
Format( '%.*d', [ Len, Val ] )
![]() |
AW: string inkrementieren
Super! Vielen Dank für die schnellen Antworten!!!
|
AW: string inkrementieren
Zitat:
Lesbarer finde ich sowas:
Delphi-Quellcode:
Das versteht man auch in 100 Jahren noch, ohne nachschlagen zu müssen, was welcher Wert für pad_type bedeutet.
type
TPadType = (ptPadLeft, ptPadRight); function str_pad(const Input: string; pad_size: Integer; const pad_string: string = '0'; const pad_type: TPadType = ptPadLeft): string; |
AW: string inkrementieren
Inkrementiert die Zahl in dem String und verändert nicht deren Länge.
Macht einfach genau das, was man in Mahte mal gelernt hat, wenn man eine Zahl um 1 erhöhen muß.
Delphi-Quellcode:
oder
function StrInc(const Number: String): String;
var i: Integer; begin Result := Number; i := Length(Result); while (i > 0) and (Result[i] in ['0'..'9']) do begin Result[i] := Chr(Ord(Result[i]) + 1); if Result[i] <> Chr(Ord('9') + 1) then Break; Result[i] := '0'; Dec(i); end; end;
Delphi-Quellcode:
function StrInc(const Number: String): String;
var i: Integer; begin Result := Number; i := Length(Result); while (i > 0) and (Result[i] in ['0'..'9']) do begin Result[i] := Chr((Ord(Result[i]) - Ord('0') + 1) mod 10 + Ord('0')); if Result[i] <> '0' then Break; Dec(i); end; end; |
AW: string inkrementieren
Zitat:
|
AW: string inkrementieren
Zitat:
|
AW: string inkrementieren
Hier kommt die ultimative Funktion um einen String zu inkrementieren.
Dabei wird nicht auf Integer umgewandelt, sondern es wird alles nur durch reine Stringverarbeitung erledigt. Das hat folgende Vorteile: * kein Integer Überlauf möglich * über eine Maske kann genau gesteuert werden, welche Positionen erhöht werden dürfen
Delphi-Quellcode:
{**************************************************************************
* NAME: IncrementWithMask * DESC: erhöht eine Nummer (die als String vorliegt) um Eins * Dabei darf "Number" an bestimmten Stellen auch Buchstaben enthalten * "Mask" bestimmt, an welchen Positionen Ziffern oder Buchstaben erlaubt sind * Mask: 0 = Ziffern (0..9) * A = Buchstaben (A..Z) * Z = Ziffern & Buchstaben * H = Hex-Ziffern (0..9, A..F) * = diese Stelle bleibt * PARAMS: [-] * RESULT: die erhöhte Nummer *************************************************************************} function IncrementWithMask(const Number, Mask:string):string; function IncrementDigit(x:PChar; m:Char):Boolean; begin Result := False; case m of '0': begin x^ := Succ(x^); if x^ > '9' then begin x^ := '0'; Result := True; end; end; 'A': begin x^ := Succ(x^); if x^ > 'Z' then begin x^ := 'A'; Result := True; end; end; 'Z': begin if x^ = '9' then x^ := 'A' else if x^ = 'Z' then begin x^ := '0'; Result := True; end else x^ := Succ(x^); end; 'H': begin if x^ = '9' then x^ := 'A' else if x^ = 'F' then begin x^ := '0'; Result := True; end else x^ := Succ(x^); end; ' ': Result := True; else raise Exception.CreateFmt('IncrementWithMask(%s, %s) - invalid Mask', [Number, Mask]); end; end; var i : Integer; begin Result := Number; for i := Length(Result) downto 1 do begin if not IncrementDigit(@result[i], Mask[i]) then Break; end; end; // Aufruf neueNummer := IncrementWithMask(alteNummer, '00000000'); |
AW: string inkrementieren
so etwas ähnliches suche ich schon länger :thumb:
Hast Du es noch etwas ultimativer irgendwo herumliegen?:
Delphi-Quellcode:
function IncrementWithMask(const Number, Mask:string, n: Integer):string;
// alteNummer := 'Z024D00F'; neueNummer := IncrementWithMask(alteNummer, 'A000A00A', 10000); |
AW: string inkrementieren
Nun ja, man kann's ja mal so machen:
(die Performance bei hohen Werten von n ist natürlich nicht so berauschend)
Delphi-Quellcode:
function IncrementWithMask2(const Number, Mask:string, n: Integer):string;
begin Result := Number; while n > 0 do begin Result := IncrementWithMask(Result, mask); Dec(n); end; end; |
AW: string inkrementieren
ja, wegen der Performance hatte ich nachgefragt.
Meine Versuche eine Funktion zu erstellen, die direkt um einen Wert per Pointer-Arithmetik erhöht, haben bisher leider nicht zum Ziel geführt.:( Trotzdem Danke, habe meine bisherige durch Deine ausgetauscht, ich werde dann mal meine Bemühungen fortsetzen. |
AW: string inkrementieren
Um einen 8-stellige Hex-String ohne Überlauffehler hochzuzählen:
Delphi-Quellcode:
.
Caption := GetIncStr('$1234ABCD', '~XXXXXXXX', i);
oder einen Hex-String mit beliebig vielen Stellen
Delphi-Quellcode:
.
Caption := GetIncStr('1234ABCD', '*X', i);
oder 'ne GUID
Delphi-Quellcode:
.
Caption := GetIncStr('{CDDB2E23-022D-47AA-B205-EEA2890E30A2}', '~_XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX_', i);
oder
Delphi-Quellcode:
oder mal ganz Krank eine schöne Base64-Hexadezimal-Dezimal-Oktal-Binär-Mischung :stupid:
const TreeState: TIncStringFormat1 = ((Mode: ['T']; Chars: '012'; CaseSensitive: True));
Caption := GetIncStr('012', 'TTT', 16, TreeState);
Delphi-Quellcode:
var
S: String; i: Integer; begin S := 'A0000'; Memo1.Lines.BeginUpdate; try for i := 0 to 1000 do begin IncStr(S, '~ZDHCB', 1); Memo1.Lines.Add(S + ' = ' + IntToStr(i)); end; IncStr(S, '~ZDHCB', 162800); Memo1.Lines.Add(''); for i := 163800 to 163840 do begin IncStr(S, '~ZDHCB', 1); Memo1.Lines.Add(S + ' = ' + IntToStr(i)); end; finally Memo1.Lines.EndUpdate; end; end;
Delphi-Quellcode:
Ich hoff es ist kein Fehler drin.
uses
SysUtils, StrUtils; type TIncStringFormatRec = record Mode: TSysCharSet; Chars: String; CaseSensitive: Boolean; end; TIncStringFormat = array of TIncStringFormatRec; TIncStringFormat1 = array[0..0] of TIncStringFormatRec; TIncStringFormat8 = array[0..7] of TIncStringFormatRec; const NoneIncFormat: TIncStringFormat1 = ( (Mode: ['-', '_']; Chars: ''; CaseSensitive: True)); DecIncFormat: TIncStringFormat1 = ( (Mode: ['D', '0']; Chars: '0123456789'; CaseSensitive: True)); HexIncFormat: TIncStringFormat1 = ( (Mode: ['X', 'H']; Chars: '0123456789ABCDEF'; CaseSensitive: False)); AlphaIncFormat: TIncStringFormat1 = ( (Mode: ['A']; Chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; CaseSensitive: False)); AlphaNumIncFormat: TIncStringFormat1 = ( (Mode: ['N']; Chars: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; CaseSensitive: False)); BinIncFormat: TIncStringFormat1 = ( (Mode: ['B']; Chars: '01'; CaseSensitive: True)); OctIncFormat: TIncStringFormat1 = ( (Mode: ['C']; Chars: '01234567'; CaseSensitive: True)); Base64IncFormat: TIncStringFormat1 = ( (Mode: ['Z']; Chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; CaseSensitive: True)); AllIncFormats: TIncStringFormat8 = ( (Mode: ['-', '_']; Chars: ''; CaseSensitive: True), (Mode: ['D', '0']; Chars: '0123456789'; CaseSensitive: True), (Mode: ['X', 'H']; Chars: '0123456789ABCDEF'; CaseSensitive: False), (Mode: ['A']; Chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; CaseSensitive: False), (Mode: ['N']; Chars: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; CaseSensitive: False), (Mode: ['B']; Chars: '01'; CaseSensitive: True), (Mode: ['C']; Chars: '01234567'; CaseSensitive: True), (Mode: ['Z']; Chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; CaseSensitive: True)); procedure IncStr(var Number: String; Format: String; Increment: UInt64; IncFormat: array of TIncStringFormatRec; RightAligned: Boolean = True); overload; var N, F, M, D, i: Integer; NCNum: String; B: Boolean; begin NCNum := UpperCase(Number); Format := UpperCase(Format); for F := Length(Format) downto 1 do begin B := Format[F] in [' ', '~', '*']; for i := High(IncFormat) downto 0 do if Format[F] in IncFormat[i].Mode then begin B := True; Break; end; if not B then raise Exception.CreateFmt('Ungültiger Format-Befehl "%s".', [Format[F]]); end; if not RightAligned then begin N := Length(Format); if ContainsStr(Format, '*') then raise Exception.Create('Format-Befehl "*" darf nicht verwendet werden.'); end else N := Length(Number); F := Length(Format); while Increment > 0 do begin while (F > 0) and (Format[F] = ' ') do begin Dec(F); Dec(N); end; if F <= 0 then raise Exception.Create('Format-String zu kurz.'); if Format[F] = '~' then // Überlauf ignorieren break; M := -1; for i := High(IncFormat) downto 0 do if (Format[F] in IncFormat[i].Mode) or ((Format[F] = '*') and (Format[F + 1] in IncFormat[i].Mode)) then begin M := i; Break; end; if M < 0 then raise Exception.CreateFmt('Ungültiger Format-Befehl "%s".', [Copy(Format, F, 2)]); if N = 0 then begin Insert(IncFormat[M].Chars[1], Number, 1); Insert(' ', NCNum, 1); end else if N < 0 then raise Exception.Create('Number-String konnte nicht erweitert werden.'); D := Length(IncFormat[M].Chars); if D <> 0 then begin if IncFormat[M].CaseSensitive then i := Pos(Number[N], IncFormat[M].Chars) - 1 else i := Pos(NCNum[N], IncFormat[M].Chars) - 1; if i < 0 then raise Exception.CreateFmt('Ungültiger Wert "%s" in Number-String.', [Number[N]]); Inc(i, Increment mod D); Number[N] := IncFormat[M].Chars[i mod D + 1]; Increment := Increment div D + i div D; end; if Format[F] <> '*' then Dec(F); Dec(N); end; end; procedure IncStr(var Number: String; const Format: String; Increment: UInt64 = 1; RightAligned: Boolean = True); overload; begin IncStr(Number, Format, Increment, AllIncFormats, RightAligned); end; function GetIncStr(const Number, Format: String; Increment: UInt64; IncFormat: array of TIncStringFormatRec; RightAligned: Boolean = True): String; overload; begin Result := Number; IncStr(Result, Format, Increment, IncFormat, RightAligned); end; function GetIncStr(const Number, Format: String; Increment: UInt64 = 1; RightAligned: Boolean = True): String; overload; begin Result := Number; IncStr(Result, Format, Increment, AllIncFormats, RightAligned); end; function IncStrPos(const Str: String; Start, Length: Integer; Format: String; Increment: UInt64; IncFormat: array of TIncStringFormatRec; RightAligned: Boolean = True): String; overload; begin Result := Copy(Str, 1, Start - 1) + GetIncStr(Copy(Str, Start, Length), Format, Increment, IncFormat, RightAligned) + Copy(Str, Start + Length); end; function IncStrPos(const Str: String; Start, Length: Integer; const Format: String; Increment: UInt64 = 1; RightAligned: Boolean = True): String; overload; begin Result := Copy(Str, 1, Start - 1) + GetIncStr(Copy(Str, Start, Length), Format, Increment, RightAligned) + Copy(Str, Start + Length); end; '~' um einen Überlauf zu ignorieren, '*' wiederholt das letzte Formatzeichen, ' ', '-' und '_' als Nichtformatzeichen und der Rest wird als Format interpretiert. |
AW: string inkrementieren
Wofür doch so die Lebenszeit draufgeht...:stupid:
|
AW: string inkrementieren
Zitat:
Delphi-Quellcode:
PS: Ohhjee, jetzt haben wir 2 Implementierungen :shock:
function FastCharPos(const S: AnsiString; const C: AnsiChar): Integer;
begin for Result := 1 to Length(S) do if S[Result] = C then Exit; Result := 0; end; function IncSingleDigit(var c:AnsiChar; n : Integer; const d:string):Integer; var z : Integer; len : Integer; begin len := length(d); z := FastCharPos(d, c) - 1; if z < 0 then z := 0; z := z + n; c := d[(z mod len) +1]; Result := z div len; end; function IncBinary(var x:Byte; n : Integer):Integer; var z : Integer; begin z := Ord(x) + n; x := z and $FF; Result := z div 256; end; {************************************************************************** * NAME: IncrementWithMask * DESC: erhöht eine Nummer (die als String vorliegt) um den Wert N * Dabei darf "Number" an bestimmten Stellen auch Buchstaben enthalten * "Mask" bestimmt, an welchen Positionen Ziffern oder Buchstaben erlaubt sind * Mask: 0 = Ziffern (0..9) * 2 = Binär (0..1) * A = Buchstaben (A..Z) * a = Buchstaben (a..z) * Z = Ziffern & Gross-Buchstaben * z = Ziffern & Klein-Buchstaben * H = Hex-Ziffern (0..9, A..F) * h = Hex-Ziffern (0..9, a..f) * B = Zeichen wird binär erhöht * = diese Stelle bleibt * PARAMS: [-] * RESULT: die erhöhte Nummer * CHANGED: 03-06-2011/shmia *************************************************************************} function IncrementWithMask(const Number, Mask:AnsiString; N : Integer):AnsiString; function IncrementDigit(x:PAnsiChar; m:Char; n:Integer):Integer; const digits : AnsiString = '0123456789'; alpha : AnsiString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; hex : AnsiString = '0123456789ABCDEF'; numalpha : AnsiString = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; begin case m of '0': Result := IncSingleDigit(x^, n, digits); '2': Result := IncSingleDigit(x^, n, '01'); 'A': Result := IncSingleDigit(x^, n, alpha); 'a': Result := IncSingleDigit(x^, n, LowerCase(alpha)); 'Z': Result := IncSingleDigit(x^, n, numalpha); 'z': Result := IncSingleDigit(x^, n, LowerCase(numalpha)); 'H': Result := IncSingleDigit(x^, n, hex); 'h': Result := IncSingleDigit(x^, n, LowerCase(hex)); 'B': Result := IncBinary(PByte(x)^,n); ' ': Result := n; else begin Result := n; x^ := m; end end; end; var i : Integer; begin Result := Number; UniqueString(Result); for i := Length(Result) downto 1 do begin N := IncrementDigit(@result[i], Mask[i], N); if N = 0 then Break; end; end; |
AW: string inkrementieren
epeen contest? :twisted:
|
AW: string inkrementieren
Zitat:
Meinen besten Dank an shmia und himitsu :thumb: Die Codes funktionieren vorzüglich und sind etwa gleich performant. Sie sind ca. 170 mal schneller als die Möglichkeit mit einer Schleife: ![]() |
AW: string inkrementieren
Dabei könnte man in meinem Code auch noch mit PChars rumpfuschen, um den noch schneller zu machen.
Am Ende bin ich aber auch immer wieder "schockiert" wie schnell solche Stringmanipulationen doch sein können, falls man keine großen und immer wieder begangen Designfehler verbaut. Bei der ![]() OK, gegen eine etwas höheroptimiertere Mathe-Lib ist sowas zwar immernoch noch sehr lahm, aber für den einfachen Gebrauch isses doch schon oftmals flott genug. |
AW: string inkrementieren
Wenn ich string Operationen und Optimierung in einem Satz lese, könnt ich schon wieder :kotz:
|
AW: string inkrementieren
Disoptimieren geht ganz schnell um 1000x die 0 zusammenzubekommen
Delphi-Quellcode:
:stupid:
s := ''; for i := 1 to 1000 do s := s + '0';
|
AW: string inkrementieren
Zitat:
@himitsu: damit es richtig langsam wird, Verkettung umdrehen:
Delphi-Quellcode:
:zwinker:
s := ''; for i := 1 to 1000 do s := '0' + s;
|
AW: string inkrementieren
Zitat:
Mir ist klar, dass mittlerweile sehr viele Möglichkeiten gepostet worden sind. Ich hab ein wenig nach meiner Funktion gesucht und habe sie endlich gefunden. Hier mal meinen Vorschlag:
Delphi-Quellcode:
function erweiternFuehrendeNull(laenge : integer; zahl : string) : string ;
var temp : string; begin temp := zahl; while (length(temp) < laenge) do begin temp := '0' + temp; end; result := temp; end; |
AW: string inkrementieren
Delphi-Quellcode:
in einer Schleife = Aua
temp := '0' + temp;
Delphi-Quellcode:
- Warum nicht gleich Result verwenden? (Wir sind hier nicht in C, wo das zuweisen des Results [return] die Funktion verläßt)
result := temp;
Aber statt Temp hätte man auch Zahl verändern können (solange man den Parameter nicht als CONST übergibt)
Delphi-Quellcode:
- Delphi kommt mit wesentlich weniger Klammern aus.
while (...) do
Und dann noch völlig unnötige Leerzeilen entfernt (hier machen die ja nichts übersichtlicher) und schon kommt man von 13 auf 6 Code-Zeilen.
Delphi-Quellcode:
function ErweiternFuehrendeNull(const Zahl: String; Laenge: Integer): String;
begin Result := Zahl; while Length(Result) < Laenge do Include('0', Result, 1); //Result := '0' + Result; ist aber dennoch nicht viel besser (Aua) end;
Delphi-Quellcode:
PS: Nicht wundern, aber "Zahl soll Länge lang werden", also hab ich die Parameter getauscht.
function ErweiternFuehrendeNull(const Zahl: String; Laenge: Integer): String;
begin Result := DupeString('0', Laenge - Length(Zahl)) + Zahl; end; |
AW: string inkrementieren
Darf ich auch noch mal? :stupid:
Delphi-Quellcode:
function PadLeft(const S: AnsiString; const ResultLength: integer; const PadChar: AnsiChar = '0'): AnsiString;
begin if ResultLength <= 0 then Result := '' else begin SetLength(Result, ResultLength); if Length(S) < ResultLength then FillChar(Result[1], ResultLength-Length(Zahl), PadChar); if Length(S) > 0 then Move(S[1], Result[ResultLength-Length(Zahl)+1], Length(S)); end; end; |
AW: string inkrementieren
Seit Delphi 2009 (Unicode) kann man nicht mehr über
Delphi-Quellcode:
ein Char mehrfach reinschreiben, da FillChar mit Bytes und nicht mit Words (oder mehr) arbeitet.
FillChar(Result[1], ..., PadChar);
Intern würde es schon gehn, aber es nimmt nur ein Byte vom Parameter entgegen. Und beim Unicode würden überall auch nur 50% der Bytes koppiert/geschrieben. So
Delphi-Quellcode:
würde es aber weiterhin funktionieren. :stupid:
function PadLeft(const S: AnsiString; ResultLength: Integer; PadChar: AnsiChar = '0'): AnsiString;
|
AW: string inkrementieren
Zitat:
Ich sag immer jeder kann von jedem lernen! :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:32 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