Thema: Delphi string inkrementieren

Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#20

AW: string inkrementieren

  Alt 3. Jun 2011, 13:02
Um einen 8-stellige Hex-String ohne Überlauffehler hochzuzählen: Caption := GetIncStr('$1234ABCD', '~XXXXXXXX', i); .
oder einen Hex-String mit beliebig vielen Stellen Caption := GetIncStr('1234ABCD', '*X', i); .
oder 'ne GUID Caption := GetIncStr('{CDDB2E23-022D-47AA-B205-EEA2890E30A2}', '~_XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX_', i); .
oder
Delphi-Quellcode:
const TreeState: TIncStringFormat1 = ((Mode: ['T']; Chars: '012'; CaseSensitive: True));
Caption := GetIncStr('012', 'TTT', 16, TreeState);
oder mal ganz Krank eine schöne Base64-Hexadezimal-Dezimal-Oktal-Binär-Mischung
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:
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;
Ich hoff es ist kein Fehler drin.

'~' um einen Überlauf zu ignorieren,
'*' wiederholt das letzte Formatzeichen,
' ', '-' und '_' als Nichtformatzeichen
und der Rest wird als Format interpretiert.
$2B or not $2B

Geändert von himitsu ( 3. Jun 2011 um 13:07 Uhr)
  Mit Zitat antworten Zitat