Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi ToString: IntToStr-Ersatz (https://www.delphipraxis.net/151382-tostring-inttostr-ersatz.html)

implementation 15. Mai 2010 14:58


ToString: IntToStr-Ersatz
 
Ihr wollt Zahlen in unterschiedlichen Stellenwertsystemen ausgeben? Dezimal, Oktal, Binär, Hexadezimal und am besten noch im 5er-, 13er- und 31er-System? Hier kommt die Universallösung:
Delphi-Quellcode:
function ToString(Val: UInt64; Alphabet:string): AnsiString;
var sub: uint64;
    base: byte;
   function GetChar(dgt:byte):char;
   begin
      Result := Alphabet[dgt+1];
   end;
begin
   Base := Length(Alphabet);
   Result := '';
   while val>0 do begin
      sub := val mod base;
      val := val div base;
      Result := GetChar(sub)+Result;
   end;
   if Result='' then Result := '0';
end;

function ToString(Val: UInt64; Base: Byte): AnsiString;
const Alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
begin
   Result := ToString(Val, Copy(Alphabet, 1, Base));
end;
Und andersrum:
Delphi-Quellcode:
function ToUnsigned(Val:string; Alphabet:string; IgnoreCase: Boolean):UInt64;
var
   factor: UInt64;
   i: byte;
   base: byte;

   function Digit(c:char):byte;
   var i: Integer;
   begin
      if IgnoreCase then
         c := UpCase(c);
      i := Pos(c, Alphabet);
      if (i=-1) then
         raise Exception.Create('Invalid Character.');
      Result := i-1;
   end;

begin
   base := length(Alphabet);
   if IgnoreCase then
      Alphabet := Uppercase(Alphabet);
   factor := 1;
   Result := 0;
   for i := Length(Val) downto 1 do begin
      Result := Result + factor*digit(Val[i]);
      Factor := Factor * Base;
   end;
end;

function ToUnsigned(Val: string; Base: Byte): UInt64;
const Alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
begin
   Result := ToUnsigned(Val, Copy(Alphabet, 1, Base), true);
end;
Sind zwar beide nur für vorzeichenlose Zahlen (Byte, Word, DWord=LongWord, QWord=UInt64),
lassen sich aber schnell zu Int64 ausweiten.

Edit: += und *= ersetzt.
Edit: Alzaimar's Rat befolgt und Alphabetsangabe eingebaut.

rollstuhlfahrer 15. Mai 2010 18:04

Re: ToString: IntToStr-Ersatz
 
Ein Problem hat die Routine dennoch. Wenn du ein System mit über 62 Zeichen/Ziffer hast, dann produziert die Rückwandlungsroutine schon mal Müll, sie lässt nämlich alle Zeichen größer 62 aus. Die ToString-Prozedure hat dann ein unbestimmtes Ende, es wenden dann nämlich Sonderzeichen verwendet und anfangs war das so nicht gewollt.

Bernhard

himitsu 15. Mai 2010 18:14

Re: ToString: IntToStr-Ersatz
 
Eigentlich war ich mir 101%ig sicher, daß wir schon eine Klasse (auch ohne rollstuhlfahrers Fehler) in der CL/DP hatten, aber ich finde einfach nichts. :gruebel:
(für Puffer statt Int64, also auch für Quellen/Ziele mit über 8 Byte)

implementation 15. Mai 2010 19:14

Re: ToString: IntToStr-Ersatz
 
@himitsu:
Ich dachte auch, dass es in der Code-Library schon was dafür gab.
Umso schockierter war ich, als ich nix gefunden hab.
Da hab ich dann einfach mal die Codeauschnitte aus nem älteren Projekt rausgesucht und reingestellt.

@rollstuhlfahrer:
Ach ja, hatte ich vergessen zu erwähnen... Geht nur bis zum 36er-System, GROß- und klein-Schreibung wird ignoriert.

alzaimar 15. Mai 2010 22:19

Re: ToString: IntToStr-Ersatz
 
Die Probleme lassen sich durch Angabe des zu verwendenden Ziffernalphabets umgehen. So kann man Dualzahlen nicht nur als 0/1 schreiben, sondern z.B auch mit x und o. Wenn man denn will. Ein adäquates Alphabet für Dualzahlen wäre dann '01', 'xo', '-X' usw. Hex-Zahlen wäre dann '0123456789ABCDEF' oder auch '0123456789abcdef'.

implementation 16. Mai 2010 10:08

Re: ToString: IntToStr-Ersatz
 
Gute Idee, hab ich jetzt auch umgesetzt. Danke!


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz