Zum Warmwerden mit Lazarus/FP baue ich gerade einen Taschenrechner zusammen. In 'Ich-lerne-jetzt-xyz'-Büchern kommt das kurz nach "Hallo Welt" und meist mit zwei Eingabefeldern und einem Button. Das war mir zu billig, ich code schon eine Weile. Also habe ich mir vorgenommen, einen richtigen Taschenrechner zu simulieren. Das klappt auch schon soweit ganz gut, ich habe eine Form mit den ganzen Tasten (0-9, die Grundrechenarten, Komma und gleich). Diese habe ich bewusst dumm gehalten. Sie gibt die Eingabe schlichtweg an ein Rechnerobjekt weiter, dass die ganze Logik macht und lauscht darauf, dass dieses Objekt meldet, dass sich die Ausgabe bei den Lauschern ändern soll (hurra, ich habe ein Observerpattern hinbekommen!). Dann holt es sich bei dem Rechnerobjekt den neuen Output ab und zeigt ihn an.
Soweit so grün, wie wir hier auf dem roten Planeten sagen.
Mein Rechnerobjekt sammelt also die ganzen gemeldeten Eingaben in einem dynamischen Array ein und muss ja nu irgendwas damit machen. Dazu muss ich zuerst prüfen, ob die Eingaben mathematisch überhaupt Sinn machen, bzw. Fehleingaben möglichst abwenden. Daher habe ich mich vor der Implementation der Semantikprüfung hingesetzt und mir überlegt, wie ich überhaupt mit den User-Eingaben umgehen muss. Dabei ist eine Logik-Beschreibung rausgekommen, die dann natürlich in Code gegossen werden muss.
Meine Frage: Würdet ihr mal drüber blicken und mir sagen, ob ich was Wichtiges vergessen habe oder irgendwo ein Brett vor dem Kopf hatte? Falls ihr einen Tipp habt, wie man vor der konkreten Implementation an komplexe Logiksachen besser rangehen kann, bin ich auch dankbar!!!
Meine Überlegungen waren wie folgt:
Falls euch das zu blöd ist und ich keine Antwort erhalte: okay. Ansonsten schon mal danke im Voraus. Um ein wenig optische Hilfe zu geben, füge ich mal ein Bild meines Taschenrechners (bisheriger Stand) bei. Code kann auf Wunsch nachgeliefert werden, fängt aber an, schon einige Zeilen zu füllen (deswegen verzichte ich erstmal drauf).Die Logik von Usereingaben
-Der Rechner akzeptiert als Eingabe nur solche Zeichen, mit denen er was anfangen kann (0..9, die Operatoren (+, -, *, /, =) usw.). Zuerst wird also geprüft, ob überhaupt ein akzeptables Zeichen eingegeben wurde, sonst wird es ignoriert. Danach wird geprüft, ob das Zeichen im mathematischen Kontext des Rechners Sinn macht.
-Die Eingabe hat mit einem Ausdruck zu beginnen. Mit dem Begriff 'Ausdruck' meine ich eine Zahl oder eine Rechenoperation in Klammern
-Dann abwechselnd Operator und Ausdruck.
-Zum Schluss (vor dem Gleich) kommt wieder ein Ausdruck
-Sieht also wie folgt aus: Ausdruck – Operator – Ausdruck – Operator… - Ausdruck = → Dann Ergebnis berechnen
Zu den Klammern
-Ausdrücke dürfen beliebig mehrfach geklammert werden. Dabei gelten aber folgende Regeln:
-Der Gesamtausdruck muss dann geklammert sein
-Für alle öffnenden Klammern muss es auch schließende Klammern geben.
-Soll eine Klammer geschlossen werden, so wird geprüft, ob sie einen semantisch korrekten Ausdruck enthält (Ausdruck -Operator-Ausdruck). Ist das nicht der Fall, wird das Schließen verweigert. Negativbeispiel: (1+1*) geht nicht. Es fehlt der abschließende Ausdruck. Es gilt bei Klammern: Nach Außen muss ein Operator stehen, nach Innen muss eine Zahl stehen, sofern nicht eine weitere Klammer voransteht/folgt!
Zum Komma
-Der Rechner hat zu wissen, ob bereits ein Komma in eine Zahl eingefügt worden ist. Wenn das der Fall ist, verhindert er die Eingabe weiterer Kommata.
Bei Löschen (Drücken von Backspace):
-Es wird immer das zuletzt eingegebene Zeichen gelöscht (logisch)
-Wenn die Ausgabe (die ja immer nur den aktuellen Ausdruck zeigt) dadurch leer wird, gibt es zwei Möglichkeiten:
a) der Eingabestapel ist komplett leer, dann erscheint eine Null
b) Der Eingabestapel ist nicht leer, dann holt der Rechner den letzten Ausdruck (samt dem letzten Operator) und zeigt ihn an. Der Benutzer hat dann die Möglichkeit, weiter zu löschen oder einen neuen Ausdruck zu beginnen.
Eingabe von Operatoren
-Wird ein Operator eingegeben, so bestehen folgende zwei Möglichkeiten:
a) es wurde gerade schon ein Operator eingegeben (ist zuoberst im Eingabestapel): In diesem Fall geht der Rechner davon aus, dass der User den alten Operator ändern möchte und überschreibt ihn mit dem neuen Operator.
b) bisher wurde nur ein Ausdruck eingegeben. In diesem Fall wird der Operator einfach akzeptiert. Der Rechner erwartet im folgenden einen neuen Ausdruck oder einen Operator (siehe a)
Die Logik von Rechnerausgaben (auf dem Display des Taschenrechners)
-Ein Ausdruck wird Ziffer für Ziffer angezeigt.
-Wird ein Operator angegeben, so wird er hinter dem Ausdruck angezeigt
-Folgt danach ein neuer Ausdruck, wird die bisherige Ausgabe gelöscht und der Beginn des neuen Ausdrucks erscheint
-Wird das '=' gedrückt, gibt die Ausgabe selbstverständlich das Ergebnis aus.