Warum funktioniert diese delphi funktion nicht?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
hanibal
Beiträge: 369
Registriert: Sa 3. Mär 2007, 16:03
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Bramsche (Emsland)

Warum funktioniert diese delphi funktion nicht?

Beitrag von hanibal »

Code: Alles auswählen

function intCompare(s1, s2: string) :boolean;
// compares wors on a similar content
// (c) retnyg
  function reformat (s:string):string;
  var l,i : integer;
  begin
     l:=length(s);
     result := '';
     for i := 1 to l do
       case upcase(s[i]) of
         'A'..'Z': result := result + upcase(s[i]);
         'Ä','ä': result := result + 'AE';
         'Ö','ö': result := result + 'OE';
         'Ü','ü': result := result + 'UE';
       end;
  end;
 
type ad = array [0..26] of dword;
var
//    count1, count2: ad;
//    pcount: ^ad;
    usedletters1: string;
    usedletters2: string;
    plen : pinteger;
    i,l,l2:integer;
    p, p2: pstring;
 
begin
  result := false;
 
  if (length(s1) = 0) or (length(s2) = 0) then exit;
 
  s1:=reformat(s1);
  s2:=reformat(s2);
 
  l := length(s1);
  l2 := length(s2);
 
//  if (l * 100) div (length(s2) * 100)
  plen := @l;
  p := @s1;
  p2 := @usedletters1;
//  pcount:= @count1;
//  zeromemory(pcount,sizeof(ad));
  setlength(p2^,0);
 
  for i := 1 to plen^ do begin
     if pos(p^[i],p2^) = 0 then
      p2^ := p2^ + p^[i];
//     inc(count1[ord(p^[i])-65]);
  end;
 
  plen := @l2;
  p := @s2;
  p2 := @usedletters2;
//  pcount:= @count2;
//  zeromemory(pcount,sizeof(ad));
  setlength(p2^,0);
 
  for i := 1 to plen^ do begin
     if pos(p^[i],p2^) = 0 then p2^ := p2^ + p^[i];
//     inc(count1[ord(p^[i])-65]);
  end;
 
  if usedletters1 = usedletters2  then begin result := true; exit; end;
 
end;
diese funktion funktioniert nicht, bzw beim compieliren kommt volgende meldung:

Code: Alles auswählen

unit1.pas(42,14) Error: Constant and CASE types do not match
unit1.pas(42,14) Error: Ordinal expression expected
unit1.pas(42,19) Error: Constant and CASE types do not match
unit1.pas(42,19) Error: Ordinal expression expected
unit1.pas(42,19) Error: duplicate case label
unit1.pas(43,14) Error: Constant and CASE types do not match
unit1.pas(43,14) Error: Ordinal expression expected
unit1.pas(43,14) Error: duplicate case label
unit1.pas(43,19) Error: Constant and CASE types do not match
unit1.pas(43,19) Error: Ordinal expression expected
unit1.pas(43,19) Error: duplicate case label
unit1.pas(44,14) Error: Constant and CASE types do not match
unit1.pas(44,14) Error: Ordinal expression expected
unit1.pas(44,14) Error: duplicate case label
unit1.pas(44,19) Error: Constant and CASE types do not match
unit1.pas(44,19) Error: Ordinal expression expected
unit1.pas(44,19) Error: duplicate case label
unit1.pas(109) Fatal: There were 17 errors compiling module, stopping
die funktion soll strings vergleichen, und wenn die ähnlich sind true zurück geben.

aufgerufen wird sie z.B. mit

Code: Alles auswählen

if intCompare('Morrisette', 'moriset') then showmessage('same word');

hanibal
Beiträge: 369
Registriert: Sa 3. Mär 2007, 16:03
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Bramsche (Emsland)

Beitrag von hanibal »

und bei

Code: Alles auswählen

const IgnoreChars :Set of Char = ['.',' ','-','_','´','`','/','~'];
 
function min2(a,b:integer) : integer;
begin
  if a < b then
    result := a
  else
    result := b;
end;
function min3(a,b,c:integer) : integer;
begin
  if a < b then
    result := min2(a,c)
  else
    result := min2(b,c);
end;
 
 
function costChange(c1,c2: char): integer;
begin
  if (AnsiLowerCase(c1)=AnsiLowercase(c2))
    // Umlaute würden ja sonst doppelt bestraft: einmal für a-ä und dann für "e nach nix"
    or ((AnsiLowerCase(c1)='ä') AND (AnsiLowerCase(c2)='a') )
    or ((AnsiLowerCase(c1)='ö') AND (AnsiLowerCase(c2)='o') )
    or ((AnsiLowerCase(c1)='ü') AND (AnsiLowerCase(c2)='ü') )
    or ((AnsiLowerCase(c1)='ß') AND (AnsiLowerCase(c2)='s') )
    or ((AnsiLowerCase(c2)='ä') AND (AnsiLowerCase(c1)='a') )
    or ((AnsiLowerCase(c2)='ö') AND (AnsiLowerCase(c1)='o') )
    or ((AnsiLowerCase(c2)='ü') AND (AnsiLowerCase(c1)='ü') )
    or ((AnsiLowerCase(c2)='ß') AND (AnsiLowerCase(c1)='s') )
    then result := 0
  else result := 1;
end;
 
function costGap(c1: char):integer;
begin
  if c1 in IgnoreChars then
    result :=0
  else
    result :=1;
end;
 
function costGap2(c1: char):integer;
begin
  if c1 in IgnoreChars then
    result :=0
  else
    result :=1;
end;
 
function EditierDistanz(s1,s2: string; tolerance:integer) : integer;
{ Diese Funktion berechnet eine modifizierte Editierdistanz,
  bzw. bricht die Berechnung ab, wenn die Editierdistanz größer
  wird als ein vorgegebener Wert}
var A: array of array of integer;
  i, j, min: integer;
  ls1,ls2:integer;
begin
{ s1: Der String, der gesucht wird
  s2: Der String, in dem gesucht wird
  Array A, was zur Berechnung der Distanz verwendet wird:
      String_in_dem_gesucht_wird
    s 01...                    |
    t  0                       |
    r   0...                   |
    1 .........................X <-Ergebnis }
 
  ls1 := length(s1);
  ls2 := length(s2);
  setlength(A,ls1+1);
  for i:=0 to length(A)-1 do
  setlength(A[i],ls2+1);
 
{ Ziel: Der zu suchende String soll in dem anderen möglichst gut enthalten sein
  Daher: Nullte Zeile des Arrays mit 0 initialisieren}
  for j := 0 to ls2 do
    A[0,j] := 0;
 
{ Änderungen am Suchstring sollen aber bestraft werden
  Daher: Nullte Spalte mit Werten füllen, die u.a. vom char an der betreffenden
        Stelle abhängen }
  for i := 1 to ls1 do
    A[i,0] := A[i-1,0] + costGap(s1[i]);
 
{ Bedeutung des Parameters 'tolerance':
  Die Editierdistanz kann von oben nach unten nur immer weiter zunehmen
  Wenn man das Minimum der Werte einer Zeile schon größer als die Toleranz ist,
  dann kann abgebrochen werden.}
  min := tolerance + 1;
  for i := 1 to ls1-1 do // Zeilenweise arbeiten
  begin
    min := tolerance + 1;
    for j := 1 to ls2 do // jede Zelle der Zeile durchgehen, davon gibt es |s2| viele
    begin
      A[i,j] := min3(
        A[i-1,j] + costGap2(s1[i]),  // insertion von s1[i] in s2, bzw. löschen in s1
        A[i,j-1] + costGap(s2[j]) ,  // löschen in s2, bzw. insertion in s1, in der letzten Zeil soll das ok sein
        A[i-1,j-1] + costChange(s1[i],s2[j]) );
      if A[i,j] < min then
        min := A[i,j];
    end;
    if min > tolerance then break;
  end;
 
  if min > tolerance then
  begin
    result := tolerance+1;
    exit;
  end;
{ Die letzte Zeile verdient besondere Aufmerksamkeit:
  Ein löschen von Buchstaben aus dem s2-String soll hier nicht mehr bestraft werden
  -> finde "die toten" in "die toten hosen"}
  for j := 1 to ls2 do
  begin
      A[ls1,j] := min3(
        A[ls1-1,j] + costGap2(s1[ls1]),
        A[ls1,j-1]  , // !!!!
        A[ls1-1,j-1] + costChange(s1[ls1],s2[j]));
  end;
  result := A[ls1,ls2];
end;
kommt in der ersten zeile
const IgnoreChars :Set of Char = ['.',' ','-','_','´','`','/','~'];

Code: Alles auswählen

unit1.pas(29,38) Error: Ordinal expression expected

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Wahrsch. weil dei Quelldatei in UTF8 ist und da die deutschen Umlaute nicht als einfache Char gesehen werden.
Probier mal sowas:
#196,#228: result := result + 'AE';

hanibal
Beiträge: 369
Registriert: Sa 3. Mär 2007, 16:03
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Bramsche (Emsland)

Beitrag von hanibal »

ah, danke hat funktioniert

Antworten