String nach zeichen durchsuchen

  • Hallo,

    Wie kann herausfinden wenn in einem String z.b ein " ! " vorkommt , irgendwo mittendrin ?

    mfg

    Einmal editiert, zuletzt von Tecoist (8. Februar 2010 um 16:09)

  • OB in einem String ein ! vorkommt kannst du so prüfen:

    [autoit]

    $string="Hallo, das ist ein Test!"
    stringreplace($string,"!","!")
    if @extended then msgbox(0,0,"Das ! ist im string enthalten")

    [/autoit]

    Die Position des ! im String findest du per

    [autoit]

    $string="Hallo, das ist ein Test!"
    $position=stringinstr($string,"!")
    if $position then msgbox(0,0,"Das ! ist im string enthalten an Position "&$position)

    [/autoit]
  • Warum empfiehlst du die Methode per StringReplace wenn er wirklich nur suchen will?
    Ein If StringInStr($String, "c") Then sollte doch übersichtlicher sein.
    Außerdem auch schneller weil der String intern nur Readonly gesetzt werden braucht und vor allem weil StringInStr beim ersten Vorkommen die Suche abbricht während StringReplace logischerweise weitermacht.
    Also hat das irgendeinen anderen Hintergrund den ich bisher nicht beachtet habe?
    Weil sonst würde ich ja nicht wirklich für die Überprüfung zu StringReplace raten.

  • Zitat

    StringReplace könnte interessant werden, wenn man zusätzlich die genau Anzahl der ! im String benötigt

    erstens das und weil es auch die wesentlich schnellere Variante ist.( bei großen Strings bis zu 7x schneller)

    Zitat

    und vor allem weil StringInStr beim ersten Vorkommen die Suche abbricht

    aber nur, wenn man das auch vorschreibt ;)

    [autoit]

    stringinstr($string,"!",0,1)

    [/autoit]

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (8. Februar 2010 um 16:54)

  • StringReplace könnte interessant werden, wenn man zusätzlich die genau Anzahl der ! im String benötigt.

    Wie ich ja sagte - es geht hier rein um den Anwendungsfall das nur geprüft werden soll OB er vorkommt - nicht mehr.

    und weil es auch die wesentlich schnellere Variante ist.

    Sorry - bei mir nicht - in meinen Durchläufen war StringInStr immer schneller:

    Spoiler anzeigen
    [autoit]

    Global $String = "!agdshgnsdgsdhgpüömf-asldgmstgü+pksletiosetjsehtgisdogj;dfligxjxlignxclkgndglksdnglkdgnldkngdfg fsdf dsfsdfndf?"
    Global $Timer, $N = 10000, $Temp

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite("---- Teilstring am Anfang -------------" & @CRLF)
    $Timer = TimerInit()
    For $i = 1 To $N
    If StringInStr($String, "!") Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringInStr : " & Round($Timer / $N, 4) & "ms" & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    For $i = 1 To $N
    StringReplace($String, "!", "!")
    If @extended Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringReplace : " & Round($Timer / $N, 4) & "ms" & @CRLF & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite("---- Teilstring am Ende -------------" & @CRLF)
    $Timer = TimerInit()
    For $i = 1 To $N
    If StringInStr($String, "?") Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringInStr : " & Round($Timer / $N, 4) & "ms" & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    For $i = 1 To $N
    StringReplace($String, "?", "?")
    If @extended Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringReplace : " & Round($Timer / $N, 4) & "ms" & @CRLF & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite("---- Teilstring nicht vorhanden -------------" & @CRLF)
    $Timer = TimerInit()
    For $i = 1 To $N
    If StringInStr($String, ".") Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringInStr : " & Round($Timer / $N, 4) & "ms" & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    For $i = 1 To $N
    StringReplace($String, ".", ".")
    If @extended Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringReplace : " & Round($Timer / $N, 4) & "ms" & @CRLF & @CRLF)

    [/autoit]

    ( bei großen Strings bis zu 7x schneller)

    Bei großen Strings wird der Unterschied erst richtig krass - aber nicht zugunsten der Methode mit StringReplace:

    Spoiler anzeigen
    [autoit]

    #include <INet.au3>
    Global $String = _INetGetSource ("http://autoit.de/")

    [/autoit] [autoit][/autoit] [autoit]

    Global $Timer, $N = 100, $Temp

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    For $i = 1 To $N
    If StringInStr($String, "!") Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringInStr : " & Round($Timer / $N, 4) & "ms" & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $Timer = TimerInit()
    For $i = 1 To $N
    StringReplace($String, "!", "!")
    If @extended Then $Temp = True
    Next
    $Timer = TimerDiff($Timer)
    ConsoleWrite("StringReplace : " & Round($Timer / $N, 4) & "ms" & @CRLF & @CRLF)

    [/autoit]


    Also wo hast du die Angabe her dass das 7x schneller sein soll?
    Ich kann das beim besten Willen bei mir nicht reproduzieren.

    aber nur, wenn man das auch vorschreibt ;)

    [autoit]

    stringinstr($string,"!",0,1)

    [/autoit]

    Warum? - das sind Default-Werte.

  • Hi,
    habe einen Vergleich von AutoIt-Funktionen und auch externen dll´s gemacht.
    Die Boyer-Moore.dll (freundlicherweise von einem hiesigen Forenmitglied Namens AspirinJunkie :thumbup: in C erstellt) und die Funktion Findbytes() aus der prospeed.dll sind auch am Start.

    Spoiler anzeigen
    [autoit]

    $post = "Die Vögel singen im Wald abcdefghijklmnopqrstuvwxyz"
    $Pattern = $post
    $pre = ""
    $string = ""
    $hDll = DllOpen("Boyer-Moore.dll")
    $S_DLL = DllOpen("prospeed.dll")

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(" Stringlänge Suchzeit Boyer-Moore StringInstr FindBytes StringRegExp Stringreplace" & @CRLF)
    For $i = 1 To 18

    [/autoit] [autoit][/autoit] [autoit]

    For $s = 1 To 100
    $string &= Chr(Random(35, 127, 1))
    Next
    $string = StringReplace($string, $post, "") ; $post löschen
    $string &= $string & $post ;string aufpumpen und den $post und ans ende bringen

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    $a1 = BoyerMoore($string, $Pattern, $hDll) ;Boyer-Moore by AspirinJunkie
    $m1 = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    $a2 = StringInStr($string, $Pattern)
    $m2 = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    $a3 = _findbytes($string, $Pattern, 0) ;Assemblercode by Frank Abbing
    $m3 = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    $a = StringRegExp($string, $Pattern)
    $m4 = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    $t = TimerInit()
    StringReplace($string, $Pattern, "", 1, 2)
    if @extended then $x=true
    $m5 = TimerDiff($t)

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite(StringFormat(" %10.10s ", StringLen($string)) & _
    StringFormat(" %5.10s ", $m1) & _
    StringFormat(" %5.10s ", $m2) & _
    StringFormat(" %5.10s ", $m3) & _
    StringFormat(" %5.10s ", $m4) & _
    StringFormat(" %5.10s ", $m5) & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func BoyerMoore(ByRef $sString, ByRef $sPattern, $hDll = 0)
    Local $aRet = DllCall($hDll, "str", "boyerMoore", "str", $sPattern, "str", $sString)
    If @error Then Return SetError(2, @error, '')
    Return $aRet[0]
    EndFunc ;==>BoyerMoore

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _findbytes($string_1, $string_2, $count)
    $struct_1 = DllStructCreate("ubyte[" & StringLen($string_1) & "]")
    $struct_2 = DllStructCreate("ubyte[" & StringLen($string_2) & "]")
    DllStructSetData($struct_1, 1, $string_1)
    DllStructSetData($struct_2, 1, $string_2)
    $pos = FindBytes(DllStructGetPtr($struct_1), $count, DllStructGetSize($struct_1), DllStructGetPtr($struct_2), DllStructGetSize($struct_2)) + 1
    ;MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$pos' & @lf & @lf & 'Return:' & @lf & $pos) ;### Debug MSGBOX
    $struct_1 = 0
    $struct_2 = 0
    If $pos = -1 Or $pos = StringLen($string_1) + 1 Then Return 0
    Return $pos
    EndFunc ;==>_findbytes

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func FindBytes($B,$O,$A,$S,$L) ;auszug aus der prospeed.au3
    $S_FindBytes = DllCall($S_DLL, "long", "FindBytes", _
    "long", $B, _
    "long", $O, _
    "long", $A, _
    "long", $S, _
    "long", $L)
    Return $S_FindBytes[0]
    EndFunc

    [/autoit]

    die beiden benötigten dll´s autoit.de/wcf/attachment/7640/

    das ganze sieht dann so aus:

    Spoiler anzeigen

    Was man sehr deutlich sieht ist die vernachlässigbar minimale Abweichung der unterschiedlichen Verfahren bei "kleinen" Strings. Ich verwende sehr gerne StringInstr() und überhaupt die AutoIt-Stringbefehle, bin nicht so der RegExp-Fuzzi^^
    Aber bei der Suche in vielen (sehr) großen Dateien ist es ein Unterschied, ob man 10 Minuten auf ein Ergebnis wartet oder nur 1.5 Minuten. Übrigens ist das "alte" DOS-Programm FIND.EXE nur sehr schwer zu toppen (i love it^^)

    AspirinJunkie
    Btw, deine dll bzw der Algorithmus an sich profitiert von der Länge des Suchstrings, je länger der Suchstring, desto schneller.Ein Bekannter von mir sucht große Muster in sehr großen Dateien, ich soll dir bestellen, deine dll sei absolute Spitze und wenn du mal zufällig in Rheinhessen auf einem Weinfest einschlagen solltest sag vorher Bescheid, dann brauchst du dir über die Getränkeversorgung keine Gedanken mehr machen :o)
    In Anlehnung an Beerware haben wir bei uns die SpätleseWare eingeführt, ein sehr gefälliges Lizenzmodell....:)


    /EDIt/ natürlich sieht es anders aus, wenn casesensitiv gesucht wird! Dann ist stringinstr() nicht zu schlagen....

    [autoit]

    StringInStr($string, $Pattern,1) ;Groß- und Kleinschreibung wird berücksichtigt!

    [/autoit]
  • Die Boyer-Moore.dll (freundlicherweise von einem hiesigen Forenmitglied Namens AspirinJunkie :thumbup: in C erstellt)

    Der Code war eigentlich nur die Umsetzung des Wikipedia-Artikels - da war nicht viel Eigengrips im Spiel.
    Bisher war ich nicht sehr aktiv was C und C++ Programmierung angeht - momentan bin ich aber sehr intensiv dabei C++ effektiv im Rahmen meiner Studienarbeit zu erlernen.
    Ich kann gerne in dem Zusammenhang aus Übungszwecken mal sehen was ich noch aus der DLL rausholen kann aber momentan hab ich eh bisschen Probleme DLLs von C++ in AutoIt zu nutzen.

    Sei´s drum - Back to Topic: Können wir uns darauf einigen das wir als allgemeine Empfehlung zur reinen Überprüfung von Teilstrings StringInStr vorschlagen?

    Ein Bekannter von mir sucht große Muster in sehr großen Dateien, ich soll dir bestellen, deine dll sei absolute Spitze und wenn du mal zufällig in Rheinhessen auf einem Weinfest einschlagen solltest sag vorher Bescheid, dann brauchst du dir über die Getränkeversorgung keine Gedanken mehr machen

    Darauf komm ich zurück!
    Hab allgemein mit Rheinländern sehr gute Erfahrungen gemacht.
    Ich selbst wohn an der Elbe und da liegen mir andere Flussbewohner wohl besonders ;)

  • Zitat

    Sei´s drum - Back to Topic: Können wir uns darauf einigen das wir als allgemeine Empfehlung zur reinen Überprüfung von Teilstrings StringInStr vorschlagen?

    Abber sischäääärrr!