Doc_McSky: mit regulärem Ausdruck Zahlen prüfen

Hallo Leute,

ich möchte ganz gerne die eingabe einer reellen Zahl prüfen, ob diese so eingegeben wurde, wie ich es gerne hätte.

Da ich immer so meine Probleme mit regulären Ausdrücken habe habe ich bisher zwei Konstrukte, von denen einer mich nicht wirklich stolz macht, aber vielleicht kann das einer von euch ganz schnell richtig stellen.

Zum einen muss ich in einem Feld eine ganze Zahl prüfen, mache ich mit:

  
if (!eregi("^[0-9]{3}", $_POST["height"])) {  
 ...eingabefehler...  
}  

Das funktioniert eigentlich prima (oder falls da noch einer was verbessern will...)

Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden. Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma? Versucht habe ich folgendes zunächst:

  
if (!eregi("^[0-9]+\.[0-9]{0,2}", $_POST["weight"]))  

Hier wird natürlich noch nicht die Eingabe des "," erlaubt und auch die Vor-/Nachkommastellen nicht richtig gesetzt, vielleicht kann das einer schnelle und besser als ich, ich wäre euch mal wieder dankbar.

Gruß
Doc

  1. Hi!

    Zum einen muss ich in einem Feld eine ganze Zahl prüfen, mache ich mit:
    if (!eregi("^[0-9]{3}", $_POST["height"])) {
    Das funktioniert eigentlich prima (oder falls da noch einer was verbessern will...)

    Die ereg-Funktionen sind missbilligt. Verwende die preg-Version, was aber bedeutet, dass die Syntax der regulären Ausdrücke teilweise eine andere ist, jedoch nicht in deinem einfachen Fall.

    Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden. Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma? Versucht habe ich folgendes zunächst:
    if (!eregi("^[0-9]+\.[0-9]{0,2}", $_POST["weight"]))

    Beim obigen Fall wusstest du, wie man eine Anzahl begrenzt. In diesem Fall weißt du sogar, wie man dafür einen unteren und oberen Wert festlegt. Was ist das Problem dies an der Vorkommastelle auch anzugeben? Du weißt auch, wie man eine Klasse von Zeichen anspricht. Mit den Ziffern klappt das gut, was ist dein Problem, das mit Punkt und Komma ebenso zu machen? Wenn du dann noch die Dezimalzeichen und die Nachkommazahlen gruppierst und auf 0 oder 1 Vorkommen gegrenzt, solltest du dein Ziel erreicht haben.

    Lo!

  2. hi,

    Da ich immer so meine Probleme mit regulären Ausdrücken habe habe ich bisher zwei Konstrukte, von denen einer mich nicht wirklich stolz macht, aber vielleicht kann das einer von euch ganz schnell richtig stellen.

    Vielleicht hilft dir dieser Link, deine Kenntnisse zu Regexen zu erweitern: http://tut.php-quake.net/de/regex.html

    Zum einen muss ich in einem Feld eine ganze Zahl prüfen [...] Das funktioniert eigentlich prima (oder falls da noch einer was verbessern will...)

      
    if(!preg_match("/^\d{3}$/", $_POST["height"])) {  
     //...eingabefehler...  
    }  
    
    

    Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden. Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma? [...]

      
    if(!preg_match("/^\d{1,3}[\.,]\d{1,2}$/", $_POST["height"])) {  
     //...eingabefehler...  
    }  
    
    

    Hier wird natürlich noch nicht die Eingabe des "," erlaubt und auch die Vor-/Nachkommastellen nicht richtig gesetzt, vielleicht kann das einer schnelle und besser als ich, ich wäre euch mal wieder dankbar.

    Ich hoffe dir gefällt die oben genannte Methode. Ich habe auch eine andere Funktion genutzt, da du für solch einfache Regexe keine POSIX-Erweiterung benötigst und auch die Groß-/Kleinschreibung nicht ignoriert werden muss, da es sich ja eh nur um Zahlen handelt. Außerdem habe ich dir mit ^ davor und $ danach definiert, dass davor und danach keine anderen Zeichen stehen dürfen.

    lg JeSchnell

    1. Hallo,

      vielen Dank für alle Antworten, entschieden habe ich mich für die gute Variante von JeSchnell:

      »»Zum einen muss ich in einem Feld eine ganze Zahl prüfen [...] Das funktioniert eigentlich prima (oder falls da noch einer was verbessern will...)

        
      if(!preg_match("/^\d{3}$/", $_POST["height"])) {  
       //...eingabefehler...  
      }  
      
      

      Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden. Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma? [...]

        
      if(!preg_match("/^\d{1,3}[\.,]\d{1,2}$/", $_POST["height"])) {  
       //...eingabefehler...  
      }  
      
      

      Der Codec funzt ganz prima und macht genau was ich von ihm erwarte, Danke.

      Gruß
      Doc

      1. Hi!

        if(!preg_match("/^\d{3}$/", $_POST["height"])) {

        Dieser Ausdruck will unbedingt eine dreistellige Zahl haben, also auch 000. 42 wäre jedoch ungültig. So wolltest du das doch aber nicht, oder?

        Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden. Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma? [...]
        [code lang=php]if(!preg_match("/^\d{1,3}[.,]\d{1,2}$/", $_POST["height"])) {

        Das entspricht nicht ganz der Aufgabenstellung, es sei denn, du prüfst "123" bereits mit dem anderen Ausdruck. Wenn du aber beides mit einem Ausdruck prüfen willst, so ist eine Änderung erforderlich. Doch zunächst: [.,] In einer Zeichenklasse verlieren viele der Zeichen ihre Sonderbedeutung. Außer ^ am Anfang und - als Bereichsangabe können alle anderen Zeichen direkt verwendet werden, selbst das schließende ], wenn es als erstes Zeichen oder direkt nach dem Anfangs-^ notiert wird. Es schadet aber auch nicht, ein Zeichen zu maskieren. Das . wirkt also genauso wie wenn du nur [.,] schreibst.

        /^\d{1,3}([.,]\d{1,2})?$/

        Die ()-Klammerung bewirkt, dass Dezimalzeichen und Nachkommaziffern eine Gruppe bilden. Diese darf aufgrund des folgenden ? weggelassen werden oder genau einmal vorkommen. Somit testet der Ausdruck auf ganze Zahlen mit 1 bis drei Ziffern und reelle mit zwei Nachkommastellen.

        Der Codec funzt ganz prima und macht genau was ich von ihm erwarte, Danke.

        Ein Codec ist eigentlich was ganz anderes. Wenn das zweite c nur ein Tippfehler ist, dann Schwamm drüber (im doppeldeutigen Sinne).

        Lo!

        1. Hallo nochmal,

          was würde man nur machen, wenn nicht noch andere auch mal Korrektur lesen, vielen lieben Dank @dedlfix !

          if(!preg_match("/^\d{3}$/", $_POST["height"])) {

          Dieser Ausdruck will unbedingt eine dreistellige Zahl haben, also auch 000. 42 wäre jedoch ungültig. So wolltest du das doch aber nicht, oder?

          Ja, da hast du Recht, aber das macht in meinem speziellen Fall nichts, da ich ohnehin noch auf einen Minimal- und Maximalwert prüfe und da sind ohnehin nur Werte über 100 erlaubt.
          Solltest du aber einen besseren Code (<- nicht Codec :-) ) haben, so habe ich nichts dagegen einzuwenden.

          /^\d{1,3}([.,]\d{1,2})?$/

          Danke für diese Codeberichtigung im zweiten Teil, dieser macht nun wirklich alles was er soll. :o)

          Gruß
          Doc

          1. Hi!

            [...] da ich ohnehin noch auf einen Minimal- und Maximalwert prüfe und da sind ohnehin nur Werte über 100 erlaubt.
            Solltest du aber einen besseren Code (<- nicht Codec :-) ) haben, so habe ich nichts dagegen einzuwenden.

            Nun, einerseits kannst du es auch wie Der Martin schon vorschlug gänzlich ohne Regexp versuchen. Da du leider darauf nicht eingegangen bist, weiß ich deine Gründe nicht, warum du dir die Mühe einer Musterprüfung machst und nicht gleich nur die üblicherweise wesentlich einfacher zu realisierende Einhaltung der Wertebereiche implementierst. Andererseits kann man natürlich auch mit einer Musterprüfung eine Wertebereichsprüfung nachstellen. Es ist wie gesagt nur aufwendiger, weil du gegebenenfalls die Regeln für jede einzelne Stelle mehr oder weniger separat definieren musst.

            Von 100 bis 899 ist beispielsweise noch einfach. Die erste Ziffer darf [1-8] sein, und die beiden anderen Stellen beliebige Ziffern: \d{2}
            Geht der Wertebereich von 100 bis 849, so ist die zweite Stelle in Abhängigkeit zur ersten zu betrachten und der daraus entstehende Reguläre Ausdruck muss schon tiefer in die Trickkiste greifen. Wie einfach (zu formulieren, zu verstehen und vom Rechner auszuwerten) ist hingegen ein »if (x >= 100 and x < 850)«? Die Dreistelligkeit wird quasi mitgeprüft, weil sie durch den Wertebereich implizit vorgegeben ist.

            Lo!

  3. Hallo,

    Zum einen muss ich in einem Feld eine ganze Zahl prüfen, mache ich mit:

    if (!eregi("^[0-9]{3}", $_POST["height"]))

    also müssen die Zahlen immer dreistellig eingegeben werden. Das heißt, "0" ist ebenso verboten wie "42", "007" ist aber in Ordnung. Möchtest du die Stellenzahl nicht flexibel halten?

    Meine andere Abfrage für eine reelle Zahl funzt nicht wirklich, es darf also nur "123", "123.45" oder "123,45" eingegeben werden.

    Also bis zu drei Stellen vor dem Dezimalpunkt, bis zu zwei danach.

    if (!eregi("^[0-9]+\.[0-9]{0,2}", $_POST["weight"]))

    Wie kann ich noch die Zahlenmengen um das Komma begrenzen, also vielleicht maximal 3 Stellen vor und maximal 2 Stellen nach dem Komma?

    Die Dezimalstellen hast du doch schon auf 0..2 eingeschränkt; warum nicht die Vorkommastellen auf 1..3 festlegen? Außerdem erlaubt der obige Ausdruck natürlich auch die Eingabe von "23901258.7" oder "2.", aber nicht "120" (weil der Punkt zwingend gefordert ist) oder ".25" (weil mindestens eine Stelle vor dem Punkt gefordert ist). Schade eigentlich ...

    Ich würde die Eingabe von Zahlenwerten übrigens nicht mit einem RegEx prüfen, sondern einfach mit intval() oder floatval() die Eingabe wandeln, dann nur den rein numerischen Wertebereich abprüfen und erst bei der Ausgabe wie gewünscht formatieren.
    Dann kann es dir nämlich auch egal sein, wenn jemand einen Tick für Hexadezimalzahlen hat und "0x64" eingibt, oder wenn jemandem die Kurzschreibweise ohne führende Null gefällt und er deshalb ".4" eingibt.

    So long,
     Martin

    --
    PCMCIA: People Can't Memorize Computer Industry Acronyms
    1. Ich würde die Eingabe von Zahlenwerten übrigens nicht mit einem RegEx prüfen, sondern einfach mit intval() oder floatval() die Eingabe wandeln, dann nur den rein numerischen Wertebereich abprüfen und erst bei der Ausgabe wie gewünscht formatieren.

      Ich würde mit is_numeric() (oder, wenn es genauer definiert ist z.B. mit is_int()) prüfen ob es sich um eine Zahl handelt. Automatische Korrektur von Benutzereingaben durch z.B. intval() ist ggf. nicht forderlich, da ggf. der Sinn der Eingabe entstellt werden kann.

      Da halte ich das Prüfen und ggf. ein Hinweis auf das Format angebrachter.

      Eingabe "4.2"
      Fehlermeldung "Es sind nur Ganzzahlen erlaubt - meinten Sie vielleicht 42? - Denn intval() würde 4.2 afaik nach 4 casten.

      1. Hi!

        Ich würde mit is_numeric() (oder, wenn es genauer definiert ist z.B. mit is_int()) prüfen ob es sich um eine Zahl handelt.

        is_int() ist ein Variablentyp-Prüfung und keine Inhaltsprüfung à la is_numeric(). Letztere Funktion untersucht auch Zahlen in Strings, erstere nicht.

        Lo!

        1. is_int() ist ein Variablentyp-Prüfung und keine Inhaltsprüfung à la is_numeric(). Letztere Funktion untersucht auch Zahlen in Strings, erstere nicht.

          Recht hast du, mein Fehler.