Announcement

Collapse
No announcement yet.

Mit Pos rückwärts suchen?

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

  • Mit Pos rückwärts suchen?

    Hi,

    mit der Prozedur Pos wird der Teil- im Hauptstring gesucht und der Index des ersten Zeichen vom Teilstring zurückgeliefert. (So weit so gut)

    Wenn es sich nur um ein Suchzeichen handelt, könnte der Hauptstring zeichenweise (umgekehrt) in einen Hilfsstring kopiert und danach Pos bemüht werden <P>=> leider nicht sehr effizient :-(

    Ich habe mir bereits die Prozedur _Pos in der Unit "System" angesehen,
    aber mit Assembler kenne ich mich nicht aus :-(

    Kennt jemand eine Möglichkeit den Teilstring im Hauptstring von hinten zu suchen?
    (Mit geringen Aufwand & hohe Geschwindigkeit ;-))

    MFG

    Dominic

  • #2
    Hi Dominic,
    ich würde erstmal im Umfeld von StrPos & Co. nachkucken.
    Die Routinen arbeiten zwar auf PChar's, nicht auf Delphi-Strings, aber dafür gibt's mehr davon.
    <p>Wenn's da nichts gibt, kannst du ja die harte Tour versuchen:
    Such erstmal mit ner for-downto-Schleife nach dem Anfangsbuchstaben
    des Suchstrings, und wann immer du den im Hauptstring findest, vergleich den nachfolgenden Teil des Hauptstrings mit dem Suchstring
    (per CompareMem oder so). Ich bin sicher, dass es effizientere
    Algorithmen gibt, aber den versteh ich wenigstens. ;-)
    <p>
    Ciao, Uli

    Comment


    • #3
      maybe StrRScan() or AnsiStrRScan()

      Comment


      • #4
        Hi

        Also hab ich LastPos damals doch nicht nur für mich geschrieben.
        Dachte schon, es brauche nie einer .

        <pre>
        function LastPos(const SubStr: AnsiString; const S: AnsiString): LongInt;
        asm
        TEST EAX,EAX // EAX auf 0 prüfen (d.h. SubStr = nil)
        JE @@noWork // wenn EAX = 0 dann Sprung zu noWork

        TEST EDX,EDX // Test ob S = nil
        JE @@stringEmpty // bei Erfolg -> Sprung zum Label 'stringEmpty'

        PUSH EBX
        PUSH ESI
        PUSH EDI // Register auf dem Stack sichern Grund: OH
        // OH: "In einer asm-Anweisung muß der Inhalt
        // der Register EDI, ESI, ESP, EBP und EBX
        // erhalten bleiben (dh. vorher auf dem Stack
        // speichern)

        MOV ESI, EAX // ESI = Sourceindex -> Adresse vom SubStr
        MOV EDI, EDX // EDI = Destinationindex -> Adresse von S

        MOV ECX,[EDI-4] // Länge von S ins Zählregister

        MOV EDX,[ESI-4] // Länge des SubStr in EDX
        DEC EDX // Length(SubStr) - 1

        JS @@fail // Vorzeichenbedingter Sprung (JumpIfSign)
        // d.h. (EDX < 0) -> Sprung zu 'fail'

        STD; // SetDirectionFlag -> Stringroutinen von hinten
        // abarbeiten

        ADD ESI, EDX // Pointer auf das letzte Zeichen vom SubStr
        ADD EDI, ECX
        DEC EDI // Pointer auf das letzte Zeichen von S

        MOV AL, [ESI] // letztes Zeichen des SubStr in AL laden
        DEC ESI // Pointer auf das vorletzte Zeichen setzen.

        SUB ECX, EDX // Anzahl der Stringdurchläufe
        // = Length(s) - Length(substr) + 1

        JLE @@fail // Sprung zu 'fail' wenn ECX <= 0

        @@loop:
        REPNE SCASB // Wdh. solange ungleich (repeat while not equal)
        // scan string for byte

        JNE @@fail

        MOV EBX,ECX { Zähleregister, ESI und EDI sichern, da nun der
        Vergleich durchgeführt wird ob die nachfolgenden
        Zeichen von SubStr in S vorhanden sind }

        PUSH ESI
        PUSH EDI

        MOV ECX,EDX // Länge des SubStrings in ECX
        REPE CMPSB // Solange (ECX > 0) und (Compare string fo byte)
        // dh. solange S[i] = SubStr[i]
        POP EDI
        POP ESI // alten Source- und Destinationpointer vom Stack holen

        JE @@found // Und schon haben wir den Index da ECX = 0
        // dh. alle Zeichen wurden gefunden

        MOV ECX, EBX // ECX wieder auf alte Anzahl setzen und
        JMP @@loop // Start bei 'loop'

        @@fail:
        XOR EAX,EAX // EAX auf 0 setzen
        JMP @@exit

        @@stringEmpty:
        XOR EAX,EAX
        JMP @@noWork

        @@found:
        MOV EAX, EBX // in EBX steht nun der aktuelle Index
        INC EAX // um 1 erhöhen, um die Position des 1. Zeichens zu
        // bekommen
        @@exit:
        POP EDI
        POP ESI
        POP EBX
        @@noWork:

        CLD; // DirectionFlag löschen
        end;
        </pre>

        MfG other

        Comment

        Working...
        X