Announcement

Collapse
No announcement yet.

Case Anweisung mit Strings...

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Case Anweisung mit Strings...

    Hallo,
    mir fehlt irgendwie der Glaube! laut Hilfe und Büchern (OK, das eine das ich gelesen habe) gibt es keine Möglichkeit Case Anweisungen auf einen String zu prüfen.

    Ich versuche ( will!!) auf verschiedene mögliche (Text)Eingaben in einem Editfeld per Case Anwesung zu reagieren. Gibt´s da nicht irgend einen Trick oder Tool?

    Heiko

  • #2
    Na die einfachste Moeglichkeit ist eine Funktion, die eine Zahl anbietet:<br>
    <pre>
    function Zuliefern(S: string): Integer;
    const
    Liste: array [0..3] of PChar =
    (
    'null',
    'eins',
    'zwei',
    'drei'
    );

    var
    I: Integer;
    begin
    for I := Low(Liste) to High(Liste) do
    if S = Liste[I] then
    begin
    Result := I;
    Exit;
    end;
    Result := -1;
    end

    Comment


    • #3
      Man kann die "case" Strings in einen ordinalen Wert umwandeln. Man nutzt einen Prüfsummenalgo, berechnet von allen vorkommenden Strings deren Prüfsumme und vergleicht per case die aktuelle Prüfsumme damit.<br>
      Natürlich setzt dies bestimmte "Regeln" voraus, 1.) jede Prüfsumme muß/sollte eindeutig sein und 2.) die Eingabe sollte von vornherein mit der Annahme leben das nur die in der Case Anweisung vorkommenden Werte als Inputs zugelassen sind.<br>

      Als praktisches Beispiel nutze ich in meinen CPU-Routinen ein solches Case Mapping. Man weis welche CPU's welchen Hersteller Namen enthalten und dieses Set hat klare Grenzen. D.h. als Input kann nur ein Wert dieses Sets auftreten. Um nun den Memoryfootprint klein zu halten und die Performance zu erhöhen berechnet man von allen heutigen CPU-Namen eine Tabelle von Prüfsummen. Zur Laufzeit wird dann die gleiche Prüfsumme über den CPU-Namen erzeugt und mit hilfe einer case oder Lookuptabelle verglichen.

      <pre>

      <code><font size=2 face="Courier New"><b>const
      </b><font color="#008080"><i>// Vendor codes
      </i></font>cvIntel = <font color="#0000FF">$506E7F40</font>; <font color="#008080"><i>// CRC('GenuineIntel'); Intel
      </i></font>cvAMD = <font color="#0000FF">$454D5A47</font>; <font color="#008080"><i>// CRC('AuthenticAMD'); AMD
      </i></font>cvCyrix = <font color="#0000FF">$7E7D554F</font>; <font color="#008080"><i>// CRC('CyrixInstead'); Cyrix
      </i></font>cvUMC = <font color="#0000FF">$20434D55</font>; <font color="#008080"><i>// CRC('UMC UMC UMC '); UMC
      </i></font>cvNexGen = <font color="#0000FF">$5B597D42</font>; <font color="#008080"><i>// CRC('NexGenDriven'); NexGen
      </i></font>cvCentaur = <font color="#0000FF">$4F706543</font>; <font color="#008080"><i>// CRC('CentaurHauls'); Centaur/IDT
      </i></font>cvRise = <font color="#0000FF">$65736952</font>; <font color="#008080"><i>// CRC('RiseRiseRise'); Rise Technology
      </i></font>cvTransmeta = <font color="#0000FF">$17337363</font>; <font color="#008080"><i>// CRC('GenuineTMx86'); Transmeta
      <br>
      </i></font><b>function </b>CRC(<b>const </b>Value): Cardinal; <b>assembler</b>;
      <font color="#008080"><i>// Value muß 16 Bytes groß sein, sprich CPU-Vendorname
      </i></font><b>asm
      </b><font color="#008080">MOV EDX,EAX
      MOV EAX,[EDX + 0]
      XOR EAX,[EDX + 4]
      XOR EAX,[EDX + 8]
      </font><b>end</b>;
      <br>
      <b>begin
      case </b>CRC(VendorName) <b>of
      </b>cvIntel: ;
      cvAMD: ;
      <font color="#008080"><i>// ... usw.
      </i></font><b>end</b>;
      <b>end</b>;
      </font>
      </code></pre>

      Im Grunde "komprimiert" CRC() einen 16 Zeichen String in einen 4 Bytes=ordinalen Cardinal und kann dann in einer case benutzt werden.<br> Wichtig dabei ist aber das diese "komprimierung" NICHT das komplette set ALLER 16 Zeichen langen Strings enthalten kann, da wir ja dann Duplikate hätten.

      Gruß Hage

      Comment


      • #4
        Für variable Strings mit variablen Inputs wären case Anweisungen dann aber extrem ineffizient. Datenbanken z.B. sortieren ihre "Vergleichsstrings" und können dann viel viel schneller als eine case Abfrage überprüfen ob der Input zulässig ist. Lookuptabellen würde also ein array of String mit einem array of procedure verlinken, als erstes den Input String in der Lookuptabelle ermitteln, und dessen Index als Index in die Sprungtabelle benutzen:

        <pre>

        procedure Proc_XXX;
        begin
        end;<br>

        const
        Names: array[0..x] of String = ('xxx', 'yyy', usw.);
        Procs: array[0..x] of procedure = (Proc_XXX, Proc_YYY, usw. );<br>

        procedure Func(const Input: String);
        var
        I: Integer;
        begin
        for I := Low(Names) to High(Names) do
        if Names[I] = Input then
        begin
        Procs[I];
        exit;
        end;
        raise Exception.Create('Input not fond');
        end;<br>

        Dieses Konzept ist sehr sehr alt und jeder BASIC Interpreter oder Delphi Tokeninzer nutzt es.<br>

        Gruß Hage

        Comment

        Working...
        X