Hugo Egon Balder: Formularverarbeitung bei Zahlen

Hallo Forum!

Bei der Verarbeitung einer Formulareingabe mit der Funktion var_dump(); sehe ich, dass die eingetragene Zahl 2 nicht als Zahl, sondern als String verarbeitet wird. Die Funktion var_dump(); zeigt also string(1) "2" an und erst nach der Umwandlung mit der Funktion intval(); liegt die eingetragene 2 als Zahl vor:

$eingabe=intval($_POST['eingabe']);

Jetzt liefert mir var_dump($eingabe); also ein int(2).

Soweit ist mir alles klar. Wenn ich aber den selben Prozess mit der Eingabe der Kommazahl 2,5 mache, dann entsteht zuerst der String "2,5" und die Funktion intval(); macht ein int(2) daraus.

Sehe ich das also richtig?

intval(); bei einem String, in dem ein oder mehrere Buchstaben oder Sonderzeichen vorkommen liefert die ganze Zahl 0 (als Integer Typ).

intval(); bei einem String, der nur aus einer ganzen Zahl besteht, liefert diese Zahl als Integer Typ.

intval(); bei einem String, der aus einer Kommazahl besteht, liefert den Wert _vor_ dem Komma als ganze Zahl (als Integer Typ)?

Und meine 2. Frage:

Welche Funktion nehme ich, wenn ich für eine Weiterverarbeitung die Umwandlung eines Strings in einen Zahlenwert mit Komma erreichen möchte? Also dass aus "Hans" ein 0 wird, aus 2 ein 2 und aus 2,5 ein 2,5.

MfG

Hugo Egon Balder

  1. Hi,

    Bei der Verarbeitung einer Formulareingabe mit der Funktion var_dump(); sehe ich, dass die eingetragene Zahl 2 nicht als Zahl, sondern als String verarbeitet wird.

    Natürlich - die Übertragung der Daten erfolgt als reiner Text, und darin gibt es keine „Datentypen“.

    Sehe ich das also richtig?

    intval(); bei einem String, in dem ein oder mehrere Buchstaben oder Sonderzeichen vorkommen liefert die ganze Zahl 0 (als Integer Typ).

    var_dump(intval('57foo6bar'));

    intval(); bei einem String, der nur aus einer ganzen Zahl besteht, liefert diese Zahl als Integer Typ.

    Sofern sie in Integer „rein passt“, ja. Andernfalls bekommst du den Wert von PHP_INT_MAX.

    intval(); bei einem String, der aus einer Kommazahl besteht, liefert den Wert _vor_ dem Komma als ganze Zahl (als Integer Typ)?

    Analog zum ersten Fall.

    Und meine 2. Frage:

    Welche Funktion nehme ich, wenn ich für eine Weiterverarbeitung die Umwandlung eines Strings in einen Zahlenwert mit Komma erreichen möchte? Also dass aus "Hans" ein 0 wird, aus 2 ein 2 und aus 2,5 ein 2,5.

    Sowas willst du gar nicht zur Weiterverarbeitung im Script haben - weil nicht das Komma, sondern der Punkt als Dezimaltrennzeichen verwendet wird.

    Du willst also das Komma durch einen Punkt ersetzen, bevor du floatval darauf anwendest. (Und dir noch über die Behandlung von Sonderfällen bzw. Fehleingaben durch den Nutzer Gedanken machen.)

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hallo ChrisB!

      Danke für Deine Antwort! Dass innerhalb von php bei einer Kommazahl das Komma ein Punkt und kein Beistrich ist, war mir bewußt, ich habe nur im Zuge meiner Problemformulierung den im realen Leben gewohnten Beistrich gesetzt.

      var_dump(intval('57foo6bar'));

      Danke für den Denkanstoß! Natürlich ... das liefert ein 57 und kein 0, wie von mir angenommen. Ich habe das nach Deinem Input jetzt auch im Manual gelesen und verstanden.

      Andernfalls bekommst du den Wert von PHP_INT_MAX

      Ich nehme mal an, diese Konstante definiert die vom System höchst zulässige ganze Zahl, oder?

      Und dir noch über die Behandlung von Sonderfällen bzw. Fehleingaben durch den Nutzer Gedanken machen.

      Selbstverständlich. Ich habe meinen Versuch nun folgendermaßen gelöst: Gegeben sei ein Formular, in dem der User aufgefordert wird, eine ganze Zahl von 1 bis 1000 einzugeben. Bei der Prüfung der Eingabe gehe ich nun so vor, dass ich zunächst überprüfe, ob die Eingabe auch wirklich nur aus Ziffern besteht, also eine Kommazahl oder Eingabe mit Buchstaben oder Sonderzeichen schon mal auf jeden Fall falsch wäre. Und zusätzlich wird überprüft, ob, nachdem der String in eine Zahl umgewandelt worden ist, diese Zahl auch wirklich eine Zahl von 1 bis 1000 ist. Hier mein Code dazu:

      <?php  
        if((ctype_digit($_POST['eingabe']))AND(intval($_POST['eingabe'])>0)AND(intval($_POST['eingabe'])<1001))  
          {  
            // Verarbeitung ...  
          }  
        else  
          {  
            echo"<p>Sorry, aber ".htmlspecialchars($_POST['eingabe'])." ist <strong>keine</strong> gültige Zahl von 1 bis 1000!</p>\n";  
          }  
      ?>
      

      Ich hoffe, so kann man es nun lassen.

      MfG

      Hugo Egon Balder

      1. Warum verwendest Du kein "filter_input"?

      2. Hallo Ego Hugon,

        Dass innerhalb von php bei einer Kommazahl das Komma ein Punkt und kein Beistrich ist, war mir bewußt, ich habe nur im Zuge meiner Problemformulierung den im realen Leben gewohnten Beistrich gesetzt.

        im realen Leben bin ich überwiegend den Punkt als Dezimaltrennzeichen gewohnt; nur in sehr seltenen Fällen (z.B. beim Onlinebanking) sehe ich mich gezwungen, stattdessen das Komma zu verwenden. Das ärgert mich jedesmal gewaltig.

        Andernfalls bekommst du den Wert von PHP_INT_MAX
        Ich nehme mal an, diese Konstante definiert die vom System höchst zulässige ganze Zahl, oder?

        Ja, wie man aus dem Namen der Konstanten schon vermuten kann.

        Bei der Prüfung der Eingabe gehe ich nun so vor, dass ich zunächst überprüfe, ob die Eingabe auch wirklich nur aus Ziffern besteht, ...

        Also würdest du die Eingabe "1E3" anstatt "1000" abweisen? Schade.

        Ciao,
         Martin

        --
        Time's an illusion. Lunchtime doubly so.
          (Douglas Adams, "The Hitchhiker's Guide To The Galaxy")
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Hi Martin!

          Bei der Prüfung der Eingabe gehe ich nun so vor, dass ich zunächst überprüfe, ob die Eingabe auch wirklich nur aus Ziffern besteht, ...

          Also würdest du die Eingabe "1E3" anstatt "1000" abweisen? Schade.

          Im "normalen" Leben ist "1E3" anstatt "1000" wohl eher unüblich, oder? Ich schreibe ja auch in ein Feld "PLZ" nicht "B955", weil ich HEX-Zahlen so praktisch finde. Oder so....

          off:PP

          --
          "You know that place between sleep and awake, the place where you can still remember dreaming?" (Tinkerbell)
          1. Hallo,

            Also würdest du die Eingabe "1E3" anstatt "1000" abweisen? Schade.
            Im "normalen" Leben ist "1E3" anstatt "1000" wohl eher unüblich, oder?

            kommt auf deine Definition von "normal" an. ;-)

            Also zumindest in einer technisch orientierten Umgebung halte ich die Exponentialschreibweise für, sagen wir, nicht üblich, aber zumindest gebräuchlich. Vor allem bei Zahlenwerten mit vielen Nullen. Ja, wenn ich z.B. in Stücklisten für Elektronik-Baugruppen den Bauteilwert eintragen muss, schreib ich durchaus 22E3 (für einen Widerstandswert von 22kΩ) oder 4.7E-6 (für einen Kondensator mit 4.7µF). Die in der Elektronik ebenfalls sehr häufige Schreibweise 4µ7 wird leider von den wenigsten Programmen von Haus aus unterstützt - höchstens Leiterplatten-Layoutsysteme.

            Ich schreibe ja auch in ein Feld "PLZ" nicht "B955", weil ich HEX-Zahlen so praktisch finde. Oder so....

            Das nicht. Aber als Speichergröße eines µC-Bausteins würde ich eher 4000h als 16384 eintragen. Oder eben 16k.

            Ciao,
             Martin

            --
            PCMCIA: People Can't Memorize Computer Industry Acronyms
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Halo Martin!

              Natürlich ... für die abertausenden Formulare im Internet, wo es um die Speichergröße eines µC-Bausteinsgeht ...  oder ... wer kennt sie nicht ... die Millionen von Seiten, wo es Formulare gibt, bei denen der Bauteilwert für Elektronik-Baugruppen eingetragen werden muß, _da_ ist meine Lösung natürlich schlecht.

              Ich bin von dem ungewöhnlichen und fast nicht anzunehmenden Einzelfall ausgegangen, dass es doch _vielleicht_ Formulare für nichttechnische Zwecke und normale Menschen gibt, wo einfach eine Zahl von 1 bis 1000 eingegeben werden muß.

              Verzeih!

              MfG

              Hugo Egon Balder

  2. Hi,

    intval(); bei einem String, der aus einer Kommazahl besteht, liefert den Wert _vor_ dem Komma als ganze Zahl (als Integer Typ)?

    das "Komma" (ich sage mal Dezimaltrennzeichen) bei PHP ist der "." (Punkt).

    Welche Funktion nehme ich, wenn ich für eine Weiterverarbeitung die Umwandlung eines Strings in einen Zahlenwert mit Komma erreichen möchte? Also dass aus "Hans" ein 0 wird, aus 2 ein 2 und aus 2,5 ein 2,5.

    Einfach(ste) Möglichkeit: du ersetzt Kommata durch Punkte, bevor du intval drauf loslässt.
    Das Problem mit unterschiedlichen Lokalisierungen wird dir aber noch öfter begegnen. Vielleicht widmest du etwas Zeit dem Studium dieses Themas.

    Bis die Tage,
    Matti

    1. hi,

      mit intval wird es immer ein int sein. Also immer eine Ganzzahl ohne nachkommastelle. Du müsstest das ganze also auf double/float ändern. Vor der Funktion übrigens das Prüfen (z.b. is_numeric) nicht vergessen ...

      Gruß Niklas

      --
      Man muss nicht alles wissen, man sollte aber wissen, wo das nicht gewusste zu finden ist.
  3. Ich warte ja insgeheim auf typsicheres php, in dem man Variablen mit ihrem Datentyp deklarieren muss um sie zu verwenden :-)

    Gibt es da noch keine Ansätze? Das wundert mich gerade wirklich, in der EDV Welt kommt doch immer wieder mal was neues raus.

    Wenn ich in der Doku lese "gibt false zurück (was man dann mit === prüfen muss) oder eine Zahl" und so weiter, da schüttelt es mich immer wieder.
    So eine Funktion wäre natürlich stark von einem Typenkonzept betroffen. Aber dafür könnte es zum Beispiel ein allgemeines object geben, um solche vorhandenen Schweinereien zuzulassen. Eigener Code wäre trotzdem sauberer.

    1. Tach!

      Ich warte ja insgeheim auf typsicheres php, in dem man Variablen mit ihrem Datentyp deklarieren muss um sie zu verwenden :-)
      Gibt es da noch keine Ansätze? Das wundert mich gerade wirklich, in der EDV Welt kommt doch immer wieder mal was neues raus.

      Nimm C#, dann hast du seit Version 4 beide Welten.

      Wenn du mit einer stark typisierten Sprache ähnlich flexibel sein willst, wie mit mit einer schwach typisierten, brauchst du eine Menge mehr syntaktische Elemente (mindestens die Typen und Dinge wie Generics, um nicht für jeden Typ extra dieselbe Funktionalität zu progammieren oder bei Programmierung mit einem allgemeinen Typ ständig typecasten zu müssen) und Library-Elemente (zum Beispiel Listen, Dictionarys und so weiter, die PHP alle mit dem Array erschlägt). Sowas macht eine Sprache ziemlich komplex und ist nicht mehr so einfach wie PHP zu erlernen.

      Wenn ich in der Doku lese "gibt false zurück (was man dann mit === prüfen muss) oder eine Zahl" und so weiter, da schüttelt es mich immer wieder.

      Bei C# muss ich auch ständig in die Dokumentation schauen, um herauszufinden, ob im Fehlerfall null zurückgegeben oder eine Exception (und wenn ja welche) geworden wird. Das ist im Prinzip auch nichts anderes.

      Insgesamt haben diese Argumente aber wenig mit dem eigentlichen Problem des OP zu tun, denn auch bei stark typisierten Spachen auf dem Webserver sendet der Browser nur Text, aus dem du in beiden Welten erstmal ordentliche Zahlen extrahieren musst.

      dedlfix.

      1. Insgesamt haben diese Argumente aber wenig mit dem eigentlichen Problem des OP zu tun

        In der Tat :-) Meine Frage hat halt grad dazu gepasst.

        Bei C# muss ich auch ständig in die Dokumentation schauen, um herauszufinden, ob im Fehlerfall null zurückgegeben oder eine Exception (und wenn ja welche) geworden wird.

        Das muss ich auch, daran würde mein Gedanke nichts ändern können.
        Aber ein bisschen mehr Typisierung wäre doch eigentlich einfacher zu erlernen. Man weiß dass man gerade eine Zahl definiert und da auch nur eine Zahl reinstecken kann.
        Bei PHP kann ich in jede Variable irgendwas rein tun und muss bei der Verwendung auch darauf gefasst sein dass ich irgendwas rauslese, manchmal ohne zu wissen was da genau drin steht. Ich als nur Hobby-PHPler habe mit den ständig passierenden impliziten Konvertierungen eher ein Problem als wenn ich selbst festlege was ich habe. Gehts euch nicht so?

        denn auch bei stark typisierten Spachen auf dem Webserver sendet der Browser nur Text, aus dem du in beiden Welten erstmal ordentliche Zahlen extrahieren musst.

        Stimmt, aber dann hab ich irgendwo ausdrücklich stehen: hier hab ich einen String, mach bitte eine Zahl draus und pack die in eine Variable, von der ich in Zukunft weiß dass eine Zahl drin steht und die ich auch überall etwas sorgloser als solche verwenden kann.

        1. Tach!

          denn auch bei stark typisierten Spachen auf dem Webserver sendet der Browser nur Text, aus dem du in beiden Welten erstmal ordentliche Zahlen extrahieren musst.
          Stimmt, aber dann hab ich irgendwo ausdrücklich stehen: hier hab ich einen String, mach bitte eine Zahl draus und pack die in eine Variable, von der ich in Zukunft weiß dass eine Zahl drin steht und die ich auch überall etwas sorgloser als solche verwenden kann.

          Wenn du unter PHP erst einmal die Zahl sichergestellt hast (ob Integer, Float oder String), bleibt sie auch eine solche, solange du keine Schreiboperationen an ihrer Variable vornimmst. Du darfst nicht den Fehler machen und annehmen, dass da nur eine Zahl vom Browser kommen kann. Also Filtern oder etwas vergleichbares musst du immer, wenn du Eingabewerte weiterverarbeiten willst. (Wenn du sie nur ohne Validierung (zur Datenbank) durchreichst, reicht jedoch die Kontextwechsel-Beachtung.)

          dedlfix.

    2. Hi,

      Ich warte ja insgeheim auf typsicheres php, in dem man Variablen mit ihrem Datentyp deklarieren muss um sie zu verwenden :-)

      hast du schon mit C Bekannschaft gemacht? C gilt als Vorbild vieler Sprachen wie beispielsweise PHP oder Javascript - nicht dass diese Sprachen C imitieren wollen, aber sie sind syntaktisch sehr ähnlich.
      Aber C verlangt genau, was du skizzierst: Variablen *müssen* deklariert werden, bevor sie verwendet werden, und sie müssen einen eindeutig definierten Typ haben.

      Wenn ich in der Doku lese "gibt false zurück (was man dann mit === prüfen muss) oder eine Zahl" und so weiter, da schüttelt es mich immer wieder.

      Wenn du in C eine Funktion als Ergebnistyp int deklarierst, gibt sie int zurück, auch wenn du dich auf den Kopf stellst und lachst. Ob der Wert 0 oder -1 eine besondere Bedeutung hat, liegt wiederum in der Verantwortung des Programmierers.
      Sauberer könnte es in solchen Fällen sein, als Funktionsergebnis generell nur einen Statuscode zurückzugeben (etwa als int), und das eigentliche Ergebnis der Funktion im Sinn des Programmflusses "by reference" zu übergeben. Das heißt, die aufrufende Funktion übergibt einen Zeiger auf das Objekt, das das Ergebnis aufnehmen soll.

      Ciao,
       Martin

      --
      Die letzten Worte des Systemadministrators:
      Nur gut, dass ich ein intaktes Backup habe.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    3. Hello,

      Wenn ich in der Doku lese "gibt false zurück (was man dann mit === prüfen muss) oder eine Zahl" und so weiter, da schüttelt es mich immer wieder.

      Das ist eine Erweiterung des Sprachumfanges einer "normalen" Compilersprache, die doch sehr an den Möglichkeiten der Maschine klebt. PHP hat als Interpretersprache erweiterte Möglichkeiten zur Verfügung, warum sollte es die nicht nutzen? Dazu gehört der "mehrschichtige" Rückgabewert von Funktion en genauso, wie die Möglichkeit Arrays (die ja eigentlich Baumstrukturen *höhö* [verschachtelte Listen] unterschiedlichster Datentypen sind) zurückzugeben.

      So eine Funktion wäre natürlich stark von einem Typenkonzept betroffen. Aber dafür könnte es zum Beispiel ein allgemeines object geben, um solche vorhandenen Schweinereien zuzulassen. Eigener Code wäre trotzdem sauberer.

      Mir fehlt eigentlich immer das Unit-Konzept von Turbo-Pascal, bei dem jede Funktion überdeckt werden kann, ohne sie damit unzugänglich zu machen. Will man das Original, oder diejenige aus einer speziellen eingebundenen Unit, muss man nur einen qualifizierten Bezeichner benutzen. Und die Möglichkeit der Schachtelung von Funktionen finde ich dort auch gut.

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
       ☻_
      /▌
      / \ Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      1. Tach!

        Mir fehlt eigentlich immer das Unit-Konzept von Turbo-Pascal, bei dem jede Funktion überdeckt werden kann, ohne sie damit unzugänglich zu machen. Will man das Original, oder diejenige aus einer speziellen eingebundenen Unit, muss man nur einen qualifizierten Bezeichner benutzen.

        Namensräume/Namespaces gibt es seit PHP 5.3.

        Und die Möglichkeit der Schachtelung von Funktionen finde ich dort auch gut.

        Mit anonymen Funktionen ist Ähnliches erreichbar.

        dedlfix.