String auf spezielles Format untersuchen

  • Ich habe hier ein spezielles Zahlenformat worauf ich gerne meine Strings überprüfen möchte. Die Umsetzung ist kein Problem, allerdings bin ich am überlegen wie ich das performant gestalten kann...

    Erst mal zum Problem. Es geht darum eine einfache Zeichenkette auf ein spezielles Format zu untersuchen. Dabei müssen folgende Regeln beachtet werden:
    - Ein String muss mit einem "-" oder einer Zahl von 0 bis 9 beginnen - Leerstrings sind unzulässig
    - Beginnt der String mit einem "-" Zeichen muss eine Ziffer von 0 bis 9 als nächstes Zeichen folgen
    - Beginnt der String mit der Ziffer "0" darf lediglich nur noch ein Dezimalpunkt folgen
    - Beginnt der String mit einer Ziffer von 1 bis 9 dürfen weitere Ziffern sowie ein Dezimalpunkt folgen
    - Nach dem Dezimalpunkt muss eine weitere Ziffer von 0 bis 9 folgen
    - Ein kleines "e" oder großes "E" für die Exponentenschreibweise darf nur einmalig nach einer Ziffer von 0 bis 9 erfolgen
    - Nach einem "e" oder "E" darf ein "+" oder "-" folgen - Danach mindestens eine Ziffer von 0 bis 9. (Ansonsten beliebig viele Ziffern hier nach)

    Einige Beispiele:
    1
    2.3
    -0
    -0.12e-1
    22.123912e+3
    0e12

    Hat hier jemand eine Idee wie man das gescheit umsetzen kann? Momentan gehe ich den String Zeichen für Zeichen durch und prüfe ihn auf die Regeln. Sollte was nicht passen gebe ich "False" zurück - Ansonsten "True". Allerdings bin ich unsicher ob das die beste Möglichkeit ist. :/

    Zudem hoffe ich auch dass ich alle Regeln korrekt genannt habe. xD

    Mein bisheriger Lösungsvorschlag:

    [autoit]

    Func _IsNumber($sParam)
    Local $aParam = StringToASCIIArray($sParam)
    Local $iCase

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

    For $i = 0 To UBound($aParam) -1
    Switch $iCase
    Case 0 ; Minus-Zeichen?
    If $aParam[$i] <> AscW("-") Then $i -= 1
    If $i = UBound($aParam) -1 Then Return False
    $iCase = 1
    Case 1 ; 1 bis 9 oder 0?
    If $aParam[$i] >= AscW("1") And $aParam[$i] <= AscW("9") Then
    $iCase = 2
    ElseIf $aParam[$i] == AscW("0") Then
    $iCase = 3
    Else
    Return False
    EndIf
    Case 2 ; Ziffer?
    If $aParam[$i] < AscW("0") And $aParam[$i] > AscW("9") Then
    $i -= 1
    $iCase = 3
    EndIf
    Case 3 ; Punkt-Zeichen oder Potenz?
    If $aParam[$i] = AscW(".") Then
    $iCase = 4
    If $i = UBound($aParam) -1 Then Return False
    ElseIf $aParam[$i] = AscW("e") Or $aParam[$i] = AscW("E") Then
    $iCase = 5
    If $i = UBound($aParam) -1 Then Return False
    Else
    Return False
    EndIf
    Case 4 ; Ziffer oder Potenz?
    If $aParam[$i] < AscW("0") And $aParam[$i] > AscW("9") Then
    If $aParam[$i] <> AscW("e") Or $aParam <> AscW("E") Then Return False
    If $i = UBound($aParam) -1 Then Return False
    $iCase = 5
    EndIf
    Case 5 ; Plus oder Minus?
    If $aParam[$i] <> AscW("+") Or $aParam[$i] <> AscW("-") Then $i -= 1
    $iCase = 6
    Case 6 ; Ziffer?
    If $aParam[$i] < AscW("0") And $aParam[$i] > AscW("9") Then Return False
    EndSwitch
    Next

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

    Return True
    EndFunc

    [/autoit]
  • Ich denke am einfachsten wird sich das mit einem regulären Ausdruck lösen lassen. Scheint mir eine gute Übung zum einarbeiten :)

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Noch lauter konntest du gar nicht schreien: "REGULAR EXPRESSION!!!!!"

    Für nen Einsteiger hiefür gibt es aber einfachere Sachverhalte.
    Daher hier mein Vorschlag dafür:

  • Das schaut mir kompakter und handlicher aus. Danke - Ich hab mich zwar schon an einer RegEx Lösung hingesetzt aber da kam nichts gescheites bei heraus. Daher hab ich das wieder verworfen... ^^

  • Hallo MakeGrafik! ^^

    Wenn du solch schöne Regeln aufstellst, dann bietet sich Regex wirklich an...
    Das kann man dann 1:1 übersetzen!
    Bspw. so:

    Ich habe mal deine Funktion testweise mitlaufen lassen, die ist noch verbesserungswürdig^^

    //EDIT so ist das, wenn man erst nach 2h auf "Post abschicken" klickt...AspirinJunkie hat das "schönere" Regex :thumbup:

  • @Andy - Kenne das nur zu gut wenn man an einer Antwort dran ist und diese eben offen lässt im Browser :D
    By the way - Ich habe den Namen Make-Grafik abgelegt. Ist dir das aufgefallen oder hast du mich lediglich am Profilbild erkannt? xD

    €dit: Vergebt mir, ich bin in RegEx wirklich nicht mehr fitt. Ich war es mal aber ich hab das nun seit 3 Jahren nicht mehr gebraucht. Hab mich gerade mal so in AspirinJunkie sein Pattern eingelesen und verstanden. :P

  • Kann man das Ganze nicht mit der Funktion Execute() erschlagen oder zumindest den größten Teil?

    AutoIt
    ConsoleWrite(Execute("1") & @CRLF)
    ConsoleWrite(Execute("2.3") & @CRLF)
    ConsoleWrite(Execute("-0") & @CRLF)
    ConsoleWrite(Execute("-0.12e-1") & @CRLF)
    ConsoleWrite(Execute("22.123912e+3") & @CRLF)
    ConsoleWrite(Execute("0e12") & @CRLF)
    
    
    ConsoleWrite(Execute("-0A") & @CRLF)
    ConsoleWrite(Execute("1e12e20") & @CRLF)

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • @UEZ - Execute bietet immer ein Sicherheitsrisiko. Was ist wenn die Funktion oben Eingaben von Usern entgegen nimmt und auf deren Formation prüft? Ggf. könnten somit Kommandos von außerhalb ausgeführt werden ohne dass dies eigentlich beabsichtigt ist.

    Zudem nimmt Execute auch andere Eingaben an wie z.B. "0x1234" als Zahl oder so etwas in der Richtung. Diese EIngaben müssten also extra vorab heraus gefiltert werden. Da ist es einfacher von selbst auf eine Funktion zu schreiben welche die Formation einfach überprüft anstatt alles andere explizit auszuschließen.

  • By the way - Ich habe den Namen Make-Grafik abgelegt. Ist dir das aufgefallen oder hast du mich lediglich am Profilbild erkannt? xD

    Abgelegt hin- oder her.....juckt mich ehrlich gesagt nicht, denn Namen werden keine abgelegt. X/
    DU bist für MICH eben Make-Grafik, damit verbinden sich alle schönen gemeinsam hier im Forum verbrachten Stunden und so soll es (jedenfalls für mich) auch weiter so sein. Und da gehört der "richtige" Name auch zur Person ;)

    €dit: Vergebt mir, ich bin in RegEx wirklich nicht mehr fitt. Ich war es mal aber ich hab das nun seit 3 Jahren nicht mehr gebraucht. Hab mich gerade mal so in AspirinJunkie sein Pattern eingelesen und verstanden.

    Ich bin auch nicht fit in Regex, wie du siehst führen viele Wege zum Ziel!
    Genau wie beim Programmieren gehe ich davon aus, dass mit 5-10% der "Befehle" 90% aller Lösungen zu erstellen sind. Prinzip verstanden, umgesetzt, fertig. Der Rest ist learning by doing, Und wenn man ein Regex nur alle 3 Monate braucht, muss man sicherlich kein "Crack" sein, um eine Lösung zurechtzustricken.
    Und mit so einer "Steilvorlage" wie deiner Beschreibung im Startpost schonmal garnicht 8)

  • Abgelegt hin- oder her.....juckt mich ehrlich gesagt nicht, denn Namen werden keine abgelegt. X/ DU bist für MICH eben Make-Grafik, damit verbinden sich alle schönen gemeinsam hier im Forum verbrachten Stunden und so soll es (jedenfalls für mich) auch weiter so sein. Und da gehört der "richtige" Name auch zur Person ;)

    wenn das mal kein Kompliment ist ^^

  • Mensch Andy - lange nicht mehr gesehen - kommst du jetzt wieder öfter? :)
    Hier noch ein Beispiel für dein Pattern wo noch Anpassung nötig ist: 01.1
    (und das große E noch)
    Übrigens: {1} ist implizit schon alles - kann also weggelassen werden.