Programmiersprachen
LVA 185.208, VL 2.0, 2005 S
1. Übungsaufgabe
NEU:
Aufgrund einer Unvollständigkeit in der ursprünglichen
Aufgabenstellung musste diese ergänzt werden. Insbesondere wurde der
Operator @ neu eingeführt. Zum leichteren Auffinden sind alle
hinzugekommenen Textstellen mit (NEU) gekennzeichnet.
Aufgabe:
Entwickeln Sie in Java oder C++ einen Taschenrechner entsprechend folgenden
Spezifikationen:
Alle Eingaben erfolgen in Prefix-Notation (zuerst wird die Operation
eingegeben, danach folgen die Argumente), wobei die Anzahl der benötigten
Argumente von der Operation abhängt. Argumente können ganze Zahlen,
Operationen mit vorangestelltem einfachem Hochkomma (z.B. '+
), oder
Anwendungen von Operationen auf ganze Argumente (z.B. + 1 2
) sein.
Ergebnisse sind ganze Zahlen oder Operationen. Explizite Klammern werden
nicht benoetigt, da die Anzahl der Argumente, die eine Operation nimmt,
eindeutig ist. Zum Beispiel entspricht + * 2 + 3 4 5
dem Ausdruck
(2*(3+4))+5 in der üblichen Infix-Notation. In den Taschenrechner sollen
Ausdruecke direkt eingegeben werden koennen, und Ergebnisse sollen berechnet
und ausgegeben werden, sobald ein Ausdruck komplett ist (ohne spezielle Taste
mit der Bedeutung jetzt bitte berechnen
). Zwischen je zwei
Teilausdrücken kann white space
(also Leerzeichen, Return oder
Tabulator) stehen, und zwischen zwei Zahlen sowie zwischen -
als Operator
und einer nichtnegativen Zahl muss white space stehen (zur Unterscheidung von
-
als Operator und dem Vorzeichen von Zahlen). Zum Beispiel wird der
Ausdruck --2 1
zu -3 ausgewertet, während -- 2 1
ein
unvollständiger Ausdruck ist, dem ein Argument für den ersten
Minus-Operator fehlt.
Der Rechner soll folgende Eingaben verstehen:
- Ganze Zahlen (ohne Vorzeichen oder mit - als Vorzeichen)
- ergeben eben diese Zahlen (= nullstellige Operationen).
- +, -, *, /, %, &, |, =, <, >
- Diese zweistelligen Operationen entsprechen den Grundrechnungsarten und
einfachen Vergleichen, wobei % für die Modulo-Operation steht und & bzw.
| sowohl als logisches als auch als bitweises UND bzw. ODER verwendbar sein
sollen. Wenn ein Argument eine Operationen mit vorangestelltem Hochkomma ist,
soll ein Fehler gemeldet werden. Ausgenommen hiervon ist nur =: Wenn = auf
zwei gleiche Operationen mit Hochkomma oder zwei gleiche Zahlen angewandt
wird, soll als Ergebnis
wahr
zurückgegeben werden, sonst
falsch
. Dabei wird wahr
durch die Zahl -1 dargestellt und
falsch
durch 0. Bei nichtassoziativen Operationen ist auf die
Reihenfolge der Argumente zu achten: - 4 2
, / 4 2
und
% 6 4
soll jeweils 2 ergeben, und > 4 2
und < 2 4
sollen -1 liefern. Das Ergebnis einer Modulo-Operation soll dasselbe
Vorzeichen wie das zweite Argument haben und betragsmäßig
(also ohne Berücksichtigung von Vorzeichen) kleiner als das zweite
Argument sein. Ein Fehler soll gemeldet werden, wenn das zweite Argument
von / oder % gleich 0 ist.
- ~
- Diese einstellige Operation angewandt auf eine Zahl negiert die Zahl
bitweise (z.B: ist ~0 gleich -1, entspricht also der logischen Negation).
- ?
- Diese dreistellige Operation entspricht einem bedingten Ausdruck. Das
erste Argument darf nur -1 oder 0 sein (alles andere ist ein Fehler) und wird
als Boolescher Wert interpretiert. Ist das erste Argument gleich -1, so wird
das ausgewertete zweite Argument als Ergebnis zurück gegeben, sonst das
ausgewertete dritte Argument. Das jeweils andere Argument soll nicht
ausgewertet werden.
- $
- Diese zweistellige Operation dient zur Definition einer neuen Operation.
Das erste Argument soll eine Zahl größer 0 sein und die Anzahl der
Argumente der neuen Operation angeben, das zweite Argument ist ein beliebiger
Ausdruck, der erst bei Anwendung der neuen Operation ausgewertet wird. Das
Ergebnis einer Auswertung des zweiten Arguments ist auch das Ergebnis eines
Aufrufs der neuen Operation. Eine Anwendung von $ liefert die neue Operation
zurueck, die sofort angewendet wird, falls kein einfaches Hochkomma davor
steht. Zum Beispiel liefert
$1 2 3
als Ergebnis 2, da die erzeugte
einstellige Operation mit dem Argument 3 aufgerufen wird und unabhängig
vom Argument 2 zurück gibt. Andererseits liefert '$1 2
eine
neue Operation, die nicht gleich ausgewertet wird.
- #
- Diese einstellige Operation soll nur im zweiten Argument einer Anwendung
von $ vorkommen und als Argument eine Zahl zwischen 1 und dem ersten Argument
von $ haben. Das Ergebnis ist das durch die Zahl bestimmte Argument, mit
welchem die durch $ erzeugte Operation aufgerufen wurde. In allen anderen
Fällen soll # eine Fehlermeldung liefern. Zum Beispiel liefert
$1 * #1 #1 3
als Ergebnis 9, und '$1 * #1 #1
eine Operation
zum Quadrieren des einzigen Arguments.
(NEU) Ist das Argument, das durch die #-Operation angesprochen wird, eine
Operation mit vorangestelltem Hochkomma, so wird diese Operation nicht
gleich angwendet, sondern bleibt weiterhin eine mit Hochkomma versehene
Operation.
- @ (NEU)
- Wie # soll diese zweistellige Operation nur im zweiten Argument einer
Anwendung von $ vorkommen und als erstes Argument eine Zahl zwischen 1 und
dem ersten Argument von $ haben. Das zweite Argument soll eine Zahl
größer oder gleich 1 sein. Das Ergebnis ist das durch die erste
Zahl bestimmte Argument, mit welchem die durch $ erzeugte Operation
aufgerufen wurde (wie bei #). Dieses Argument muss jedoch eine Operation
(mit vorangestelltem Hochkomma) sein, welches eine durch das zweite Argument
von @ bestimmte Anzahl von Argumenten nimmt und gleich aufgerufen wird.
Es soll ein Fehler gemeldet werden, wenn die Argumente von @ keine passenden
Zahlen sind, oder das angesprochene Argument von $ keine Operation der
erwarteten Stelligkeit ist. Zum Beispiel soll
$2 * @1 2 #2 - #2 1 #2 '+ 3
als Ergebnis 15 (das ist in üblicher Infix-Notation (3+(3-1))*3) liefern.
- '
- Das Hochkomma wertet den Ausdruck im einzigen Argument nicht gleich aus,
sondern betrachtet ihn als primitiven Wert (ähnlich den Zahlen,
nullstellige Operation). Eine Anwendung von ' auf eine bereits nullstellige
Operation hat jedoch keine Auswirkungen. Daher ist '1 gleich 1 (z.B. für
Vergleiche) und
'$1 2
gleich ' '$1 2
. Vor # und (NEU) @ soll
kein ' stehen. Vor $ stehend bewirkt ', dass zwar eine neue Operation
erzeugt, aber nicht gleich ausgeführt wird.
Neben diesen eigentlichen Operationen des Taschenrechners gibt es einige
Steuerbefehle, die alle mit : beginnen. Solche Steuerbefehle werden sofort
ausgeführt, sobald sie eingetippt sind. Sie werden nicht als Teil von
Ausdrücken betrachtet.
- :q
- beendet die Ausführung des Taschenrechners.
- :a
- beendet die aktuelle Eingabe eines Ausdrucks, ohne ein Ergebnis zu
berechnen. Danach kann ein weiterer Ausdruck eingegeben werden.
- :i direkt gefolgt von Ziffer oder Buchstabe
- liest einen Teilausdruck aus dem Speicher des Taschenrechners mit dem
angegebenen Namen (Ziffer oder Buchstabe). Dieser Teilausdruck wird textuell
an den bereits eingetippten Teilausdruck angehängt. Sofern der Inhalt
eines Speichers nach dem Programmstart nicht verändert wurde,
enthält er die Zahl 0.
- :s direkt gefolgt von Ziffer oder Buchstabe
- schreibt den bereits eingetippten Teilausdruck in den Speicher des
Taschenrechners mit dem angegebenen Namen. Danach kann mit dem Eintippen des
Ausdrucks fortgesetzt werden. Falls vor Ausfuehrung des Befehls noch kein
Teilausdruck eingegeben war (der zuletzt eingegebene Ausdruck wurde bereits
ausgewertet), so wird das Ergebnis der letzten Auswertung eines Ausdrucks
gespeichert. Wird dieser Steuerbefehl gleich nach Programmaufruf eingetippt,
dann wird der Wert 0 gespeichert (ohne Auswirkungen).
Weitere Steuerbefehle können nach Bedarf implementiert werden (z.B.
eine Backspace-Taste, etc.), gehen aber nicht in die Beurteilung ein.
Gestalten Sie Ihre Lösung möglichst einfach. Eines der Ziele ist es,
ein Gefühl für einen rein funktionalen Programmierstil zu bekommen.
Achten Sie auch auf einen guten objektorientierten Programmierstil bei der
Erstellung des Taschenrechners. Vermeiden Sie wenn immer möglich die
Verwendung von switch- bzw. geschachtelten if-Anweisungen, und bevorzugen Sie
dynamisches Binden.
Entwerfen Sie (zum Testen des Taschenrechners) einen möglichst kurzen und
effizienten Ausdruck (selbstdefinierte Operation) der entscheidet, ob eine
Zahl eine Primzahl ist oder nicht, und testen Sie mit mehreren, auch
längeren Zahlen.