Wildcards in Pascal

Jeder kennt sie, die Zeichen '?' und '', die man in der Fileselectorbox verwendet, um nur zwischen bestimmten Dateien wählen zu müssen. Dabei bedeutet das ’?', dass an dieser Stelle jedes beliebige Zeichen stehen darf, und der '' ersetzt eine beliebige Anzahl von Zeichen (auch 0). Wenn Sie z.B. in der Fileselectorbox die '*.BA?' einstellen, werden nur die Files angezeigt, die links eine beliebige Anzahl von Zeichen besitzen, dann folgen ein Punkt, ein 'B' und ein 'A' und am Schluss noch 1 beliebiges Zeichen. Es sind also alle Dateien der Extension BAS,BAK ... gemeint.

Solche Wildcards werden jedoch nicht nur auf Dateinamen angewandt. Auch so manches Textverarbeitungs- (z.B. Tempus) oder Datenbankprogramm verwendet sie ebenfalls. Die Pascal-Funktion maskepasst(...) ermöglicht auch Ihnen, auf einfache Weise Wildcards zu verwenden. Damit steht Ihrem Adressenverwaltungsprogramm, das alle 'H. Meier' ausdrucken kann, egal wie 'Meier' geschrieben wird ('H* M??er'). nichts mehr im Wege.

Der Befehl...

Fmaskepasst('?','*', maske, string) THEN WRITELN('paßt');

überprüft, ob string auf die Maske maske paßt. Wenn ja, wird paßt geschrieben. In diesem Beispiel wäre das Ersatzzeichen für 1 Zeichen. Existenzquantor genannt, ein '?' und für beliebig viele Zeichen, den Allquantor, ein '*'. Selbstverständlich dürfen hier auch andere Zeichen verwendet werden.

Das Beispielprogramm demonstriert die Arbeitsweise der Funktion. Es lädt eine beliebige Textdatei, deren Namen sie eingeben und druckt alle Zeilen aus. Diejenigen Zeilen, die auf Ihre Maske passen, werden dabei invers geschrieben.

Wie aber arbeitet die Funktion? Sie vergleicht von links beginnend Buchstabe für Buchstabe der Maske und des Strings. Unterscheiden sich die beiden Buchstaben, wird die Funktion beendet und FALSE zurückgegeben. Ist das Zeichen in der Maske jedoch '?', wird auf jeden Fall mit den nächsten beiden Zeichen fortgefahren. Schwierig wird es erst, wenn in der Maske ein '' angetroffen wird. Die Funktion ruft sich dann selbst rekursiv auf. Als Maske wird der Rest der Maske hinter dem '' übergeben und als der zu untersuchende String nacheinander erst der Teil-String vom dem Zeichen ab, das an dergleichen Stelle steht wie der '*' in der Maske, bis zum rechten Ende, dann 1 Zeichen danach bis zum Ende usw. Paßt irgendeiner dieser Teil-Strings auf die Maske, paßt auch der gesamte String auf die gesamte Maske, es wird TRUE zurückgegeben, sonst FALSE. Dieses Verfahren ist in der Unterfunktion alltest(...) festgelegt. Aus Zeitgründen wurde der eigentliche Vergleich in die Unterfunktion passt(...) verlegt, damit nicht für jeden rekursiven Aufruf alle Parameter neu übergeben werden müssen.

program wildcarddemo;
{
    Wildcards in Pascal 
          von R. Wisser 
    (c) MAXON Computer
}

type str=string[255];

var dat	       : text;
    fn,s,maske : str;

{ -----Beginn der Funktion ------- }

function maskepasst( existenz,all:char; var maske,s:str ):boolean; 
var mlen,slen,i:integer;

function passt( mpos,spos:integer ):boolean; 
var passtnicht,passt_exist:boolean;

    function alltest( mpos,spos:integer ):boolean; 
    var existiert:boolean; 
    begin { alltest }
        existiert:=(mpos>mlen); 
        while (spos<=slen) and not existiert do
        begin
            if passt(mpos,spos) then existiert:=true 
            else spos:=spos+1 
            end;
        alltest:=existiert 
    end; { alltest }

    begin { passt }
        passtnicht:=false; passt_exist:=false; 
        while (mpos<=mlen) and (not passt_exist) and not passtnicht do 
        begin
            if maske[mpos]=all then 
                begin
                    passt_exist:=alltest(mpos+1,spos);
                    if not passt_exist 
                     then passtnicht:=true; 
                    end
            else if spos>slen 
             then passtnicht:=true
                 else if maske[mpos]<>existenz then
                    if maske[mpos]<>s[spos] then passtnicht:=true; 
            mpos:=mpos+1; spos:=spos+1; 
            end;
        if passt_exist then passt:=true 
        else if passtnicht then passt:=false 
        else passt:=(mpos>mlen) and (spos>slen); 
    end; { passt }

begin { maskepasst }
    mlen:=length(maske); slen:=length(s); 
    maskepasst:=passt(1,1) 
end; { maskepasst }

{ ------------------- }

begin
    write('Filename : '); readln(fn);
    write('Maske    : '); readln(maske);
    writeln; writeln; 
    reset(dat,fn); 
    while not eof(dat) do 
        begin
        readln(dat,s);
        if maskepasst('?','*',maske,s) then 
            begin
            write(chr(27),'p'); writeln(s);write(chr(27),'q'); 
            end
        else writeln(s) 
        end
end.

Ralf Wisser
Aus: ST-Computer 03 / 1991, Seite 92

Links

Copyright-Bestimmungen: siehe Über diese Seite