Nico: taschenrechner

hi

nachdem ich in letzter zeit php-lerne und ein paar sachen mittlerweile kann, habe ich ne frage bei folgendem script, kann mir eine rhelfen ???

<?php

echo '<html><head></head><body>
<form action="#">
<input type="text" name="zahl1" />
<select name="verfahren">
<option>plus</option>
<option>minus</option>
<option>mal</option>
<option>durch</option>
</select>
<input type="text" name="zahl2" /><br><br>
<input type="submit" value="Ergebniss"><br><br>
<input type="text" name="ergeb" />';

if($verfahren == "plus" ){
$ergeb=$zahl1 + $zahl2;
}
if ($verfahren=="minus"){
$ergeb=  $zahl1 - $zahl2;
}
if ($verfahren=="mal"){
$ergeb=$zahl1 * $zahl2;
}
if ($verfahren=="durch"){
$ergeb=$zahl1 / $zahl2;
}

?>

dies soll ein taschenrechner werden, der auf einer seite ausrechnet. wer weiß meinen fehler ??? der script ist unter http://h20poloplayer.h2.funpic.de/rechner.php?zahl1=22&verfahren=plus&zahl2=22&ergeb=#

anschaubar...

vielen dank

nico

  1. Habe es mal kurz überflogen und erkenne keine sttelle, an der du $ergeb an dein Textfeld "ergeb" weitergibst.

    also da einfach value="<?=$ergeb;?>" noch eintragen und natürlich die berechnung davor ausführen.

    hoffe das war's

    mfg
    alex

    1. Lieber Alex,

      also da einfach value="<?=$ergeb;?>" noch eintragen und natürlich die berechnung davor ausführen.

      das war nicht gut! Es ist besser, "lange" PHP-Tags zu schreiben, also value="<?php echo $ergeb; ?>" und zweitens setzt ihr wohl beide auf register_globals=on, was nicht auf jedem Webspace gegeben sein muss, da es sicherheitsrisiken birgt! Man sollte im Gegenteil seine Scripte so schreiben, dass diese Option völlig unerheblich für das eigene Script ist!

      Liebe Grüße aus Ellwangen,

      Felix Riesterer.

      --
      ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
      1. Hi Felix,

        so geschult ist mein "PHP - Lehrer" blick noch nicht, dass ich da auch gleich draufkomm. Habe nur einen Fehler gesagt der mir gleich aufgefallen ist.

        Selbst arebeite ich natürlich mit register globals off.
        Wieso ich die kurze form aber lieber nicht nehmen sollte erschließt sich mir nicht ganz.
        NAja, wird vohl von Konfiguration zu Konfiguration unterschiedlich akzeptiert. Bei mir wurde es jedoch immer aktzeptiert bzw. zur Not könnte ich es anschalten lassen...

        Aber danke für deine Tipps :)

        mfg
        Alex

        1. echo $begrüßung;

          Wieso ich die kurze form aber lieber nicht nehmen sollte erschließt sich mir nicht ganz.
          NAja, wird vohl von Konfiguration zu Konfiguration unterschiedlich akzeptiert.

          Das ist einer der Gründe, die Langform <?php statt <? zu verwenden. Sie ist nicht überall erlaubt. Ein Grund, short_open_tag auf Off zu setzen, ist die Interferenz mit XML-Verarbeitungsanweisungen.

          <?xml version="1.0" ?>
          <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
          ...
          <? // PHP-Code

          Hier denkt PHP, bereits in der ersten Zeile anfangen zu müssen ... und wirft Syntax-Fehler.
          Natürlich kann man das mit einem Workaround umgehen, indem man die erste Zeile durch PHP ausgeben lässt:

          <? echo '<?xml version="1.0" ?>' ?>
          <!DOCTYPE html ...

          echo "$verabschiedung $name";

  2. Lieber Nico,

    if($verfahren == "plus" ){
    $ergeb=$zahl1 + $zahl2;
    }

    wo genau hast Du definiert, dass es die Variablen "verfahren" gibt und welchen Wert hast Du ihr dort zugewiesen?

    Liebe Grüße aus Ellwangen,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  3. echo $begrüßung;

    <?php
    echo '<html><head></head><body>

    Fehler im HTML-Teil: das title-Element ist Pflichtbestandteil,

    <form action="#">

    Wenn du das Formular auf sich selbst schicken möchtest, reicht ein "" im Action-Attribut. Der Anker # ohne Namen ist witzlos. Du hast außerdem das method-Attribut nicht angegeben. Das ist zwar kein Pflichtfeld, und bei dessen Abwesenheit wird GET als Default verwendet, trotzdem solltest du nicht darauf verzichten.

    <input type="text" name="zahl1" />
    <select name="verfahren">
    <option>plus</option>
    <option>minus</option>
    <option>mal</option>
    <option>durch</option>
    </select>
    <input type="text" name="zahl2" /><br><br>
    <input type="submit" value="Ergebniss"><br><br>
    <input type="text" name="ergeb" />';

    Den HTML-Teil kannst du komplett vor das PHP verlagern. Du hast darin keinerlei PHP-Funktionalität, also musst du es auch nicht davon bearbeiten lassen. Sinnvoll kann es auch sein, den Teil nach dem PHP-Teil anzusiedeln, nämlich dann, wenn darin Ausgaben erfolgen sollen, die durch das PHP erst errechnet werden. Bei kurzen Ausgaben in längeren HTML-Teilen empfiehlt es sich eher, darin

    <?php echo $variable ?>

    zu notieren, als den geamten Text in einen PHP-String zu stecken. (Nebenbei: Ergebnis mit nur einem s)

    Es scheint, als ob du das Eingabeelement <input type="text" name="ergeb" /> für eine Ausgabe missbrauchen möchtest. Das ist nicht unbedingt im Sinne des Erfinders, aber sei's drum: Ein Wert gelangt auf zwei Arten in solch ein Feld. 1. Der Benutzer gibt darin etwas ein. 2. Du weist ihm mit dem value-Attribut einen Wert zu.

    Beachte stets: Jegliche Ausgabe ist kontextgerecht zu behandeln! In einem HTML-Kontext müssen die HTML-eigenen Zeichen berücksichtigt werden. Berücksichtigst du das nicht, kann man unter Umständen mithilfe dieser HTML-eigenen Zeichen deinen HTML-Text verändern. Für den HTML-Kontext kennt PHP die Funktion htmlspecialchars().

    In deinem Fall möchtest du ein berechnetes Ergebnis ausgeben, bei dem vermutet werden kann, dass es keine HTML-eigenen Zeichen enthält. Die Behandlung des Ergebnisses mit htmlspecialchars() schadet diesem aber nicht. Vielmehr machst du dich mit dieser Funktion vertraut und verwendest sie dann hoffentlich auch in den Fällen, in denen sie unbedingt benötigt wird.

    if($verfahren == "plus" ){
    $ergeb=$zahl1 + $zahl2;
    }

    Beim PHP-Programmieren ist es stets von Vorteil, wenn man das error_reporting auf E_ALL (und display_errors auf on) stellt. In dieser Einstellung bekommt man die sonst unterdrückten Hinweismeldungen beim Zugriff auf nicht initialisierte Variablen angezeigt. Daran erkennt man Tippfehler im Variablennamen und wenn man auf etwas zuzugreifen versucht, von dem man fälschlicherweise annimmt, dass es existiere.

    Weiterhin gehört zu den Grundlagen einer erfolgreichen Fehlersuche, dass man sich die Inhalte der beteiligten Variablen anschaut. echo ist eine Möglichkeit. var_dump() eine andere, die auch noch den Inhalt präziser darstellt.

    Für dich bringen diese beiden Punkte zum einen einen Hinweis auf einen Zugriff auf etwas nicht Vorhandenes, denn dass die Werte von Eingabefeldern automatisch als PHP-Variablen zur Verfügung stehen ist ein schon seit Jahren auf der Abschussliste stehendes PHP-Feature. Zum anderen siehst du auch ohne die Hinweismeldung durch eine Kontrollausgabe, dass nicht das in der Variable drin steht, was du dir erhoffst. Damit weißt du zwar noch nicht, wie du an den Wert kommst, siehst aber erst einmal die Ursache, warum die anschließende Berechnung nicht erfolgreich sein kann.

    if ($verfahren=="minus"){
    $ergeb=  $zahl1 - $zahl2;
    }

    Ebenfalls von Vorteil ist es, wenn man Einrückungen des Codes vornimmt. Das erhöht zum einen die Übersichtlichkeit bei längeren Quelltexten, andererseites sieht man die gewünschte Hierarchie deutlicher und kommt Klammersetzungsfehlern besser auf die Spur. Auch schadet es nicht, mehr Leerzeichen zwischen den Elementen zu verwenden. Beispielsweise so:

    if ($verfahren == "mal") {  
      $ergeb = $zahl1 * $zahl2;  
    }  
      
    if ($verfahren == "durch") {  
      $ergeb = $zahl1 / $zahl2;  
    }
    

    Und dann gibt es das Kontrollstruktur-Element switch. Damit erspart man sich mehrfach vorkommende Vergleiche mit ein und der selben Variablen.

    dies soll ein taschenrechner werden, der auf einer seite ausrechnet. wer weiß meinen fehler ???

    Du hast das Ergebnis nicht ausgegeben. Das würde ich an deiner Stelle aber nicht in einem Eingabeelement machen sondern beispielsweise in einem Absatz:

    ?>  
    <p>Das Ergebnis lautet: <?php echo htmlspecialchars($ergeb) ?>.</p>
    

    Du könntest das Ganze auch noch erweitern, indem du beispielsweise:

    • bei der Division den zweiten Wert auf 0 prüfst, denn eine solche Division ist nicht zulässig. Das ist die mindeste Prüfung, die vorzunehmen ist. Für alle anderen ungültigen Eingabewerte (z.B. Buchstaben, Komma statt Dezimal-Punkt) evaluieren die beiden Operanden aufgrund von PHPs automatischer Typumwandlung höchstens zu 0, was zwar auch nicht gerade richtig ist, aber zu keinem PHP-Fehler führt.
    • die eingegebenen Werte z.B. mit is_numeric() auf gültige Zahlenwerte prüfst. (Diese Prüfung habe ich im nachfolgenden Beispielcode nicht mit eingebaut.)
    • nicht nur das Ergebnis ausgibst, sondern die komplette Rechnung. Beachte dabei die Behandlung der durch den Benutzer eingegebenen Werte bei der Ausgabe. Hier kommt nun ein Text vor, der viele variablen Teile enthält. Es ist vorteilhaft, zunächst den feststehenden Teil zusammen mit ein paar Platzhaltern zu definieren, und diese dann einsetzen zu lassen. Dafür eignet sich die printf()-Funktion.

    So sieht der PHP-Teil aus, wie er meiner Meinung nach sein sollte:

    <?php  
    // Prüfung ob alle benötigten Eingabewerte existieren.  
    if (isset($_GET['verfahren'], $_GET['zahl1'], $_GET['zahl2'])) {  
      switch ($_GET['verfahren') {  
        case 'plus':  
          $ergebnis = $_GET['zahl1'] + $_GET['zahl2'];  
          $operator = '+';  
          break;  
        case 'minus':  
          $ergebnis = $_GET['zahl1'] - $_GET['zahl2'];  
          $operator = '-';  
          break;  
        case 'mal':  
          $ergebnis = $_GET['zahl1'] * $_GET['zahl2'];  
          $operator = '*';  
          break;  
        case 'durch':  
          if ($_GET['zahl2'] == 0)  
            $ergebnis = 'undefiniert';  
          else  
            $ergebnis = $_GET['zahl1'] / $_GET['zahl2'];  
          $operator = '/';  
          break;  
        default:  
          $operator = 'unbekannter Operator';  
          $ergebnis = 'nicht ermittelbar';  
      }  
      
      printf('<p>Das Ergebnis der Berechnung von %s %s %s lautet: %s.</p>',  
        htmlspecialchars($_GET['zahl1']),  
        $operator,  // kein htmlspecialchars() erforderlich, weil der Wert definiert gesetzt wurde  
        htmlspecialchars($_GET['zahl2']),  
        htmlspecialchars($ergebnis));  
      
    } else {  
      echo '<p>Keine Berechnung möglich, es fehlen Eingabewerte.</p>';  
    }  
    ?>
    

    Für die printf()-Funktion verwendete ich in diesem Fall durchgehend den String-Platzhalter %s. Es bringt hier keinen großen Vorteil, für die Zahlenwerte einen Integer- oder Fließkomma-Platzhalter zu verwenden. Im Gegenteil, es müsste dann je nach Zahl der eine oder andere verwendet werden. PHPs Typumwandlung kümmert sich schon darum, dass der Wert in einen String umgewandelt wird.

    Weiterhin gibt es zu beachten, dass durch die Verwendung des default-Zweiges im switch-Konstrukt die Variablen $operator und $ergebnis auch dann einen Wert zugewiesen bekommen, wenn kein gültiges Verfahren angegeben wurde. Das ist ein weiterer wichtiger Punkt beim Programmieren: Variablen sollten unter allen Umständen (d.h. bedingten Abläufen) vor ihrer ersten lesenden Verwendung mit einem Wert versehen werden. Dann kann einem auch ein eingeschaltetes register_globals nicht gefährlich werden und die Variablen unerwünscht vorbelegen. (Dieses Anlegen mit einem definierten Wert hätte auch vor dem switch-Konstrukt erfolgen können, dann wäre das auf alle Fälle in einem unbedingten Kontext geschehen.)

    Wenn du dich nun gefragt hast, wie ein Verfahren anders als die von dir im <select>-Element festgelegten vier Verfahren zustande kommen kann, ...  nun, schick dein Formular einmal ab, dann siehst du in der Adresszeile des Browsers den Parameter verfahren=. Und den kannst du nun beliebig manipulieren. Das funktioniert auch beim POST-Verfahren, und ist nur um ein Weniges aufwendiger. Deshalb nun noch ein wichtiger Punkt: Verlass dich nie auf Werte, die vom Client kommen, auch wenn du dem klare Vorgaben gemacht hast. Rechne stets mit allem Möglichen, zumindest mit Abweichungen von den Vorgaben.

    echo "$verabschiedung $name";