Fachhochschule Regensburg Algorithmen und Datenstrukturen Name: ________________________ Aufgabensteller: Prof. Sauer Vorname: _____________________ April 1999 1. Aufgabe Schreibe für die in der Vorlesung entwickelte Klassenschablone „Stapel“ eine Anwendung zur Auswertung voll geklammerter arithmetischer Ausdrücke. Das Ergebnis der Auswertung ist ein Zahlenwert vom Typ „double“. Zur Auswertung arithmetischer Ausdrücke beachte und analysiere das folgende Bsp.: (((6 + 9)/3)*(6 – 4)). Durch Einlesen der Zeichen bzw. Zahlen in einen Stapel, der Operations-Zeichen aufnimmt bzw. in einen Stapel, der Zahlen jeweils bis zur ersten schließenden Klammer aufnimmt, kann die Auswertung direkt vorgenommen werden: (((6 + 9)/3)*(6 – 4)) erste schließende rechte Klammer 9 6 zahlen + operationen Abb. 1: Stapel unmittelbar vor Erreichen der ersten rechten Klammer 15 zahlen operationen Abb. 2: Stapel unmittelbar nach dem Einlesen der ersten rechten Klammer Nach der zweiten rechten Klammer liegt folgende Verarbeitung vor: 3 15 zahlen / operationen 5 zahlen operationen Abb. 3: Stapel unmittelbar nach Erreichen bzw. Verarbeitung der zweiten rechten Klammer Nach der letzten umschließenden Klammer ergeben sich die folgenden weiteren Verarbeitungsschritte: 4 6 5 zahlen * operationen 6-4 = 2 2 5 zahlen 5*2=10 * operationen 10 zahlen operationen 2. Aufgabe Schreibe ein Programm, das einen arithmetischen Ausdruck in „Infix“-Schreibweise aufnimmt und einen äquivalenten Ausdruck in „Postfix“-Schreibweise ausgibt. Es sollen generell Zahlen vom Typ „double“ verarbeitet werden. Bsp.: Konvertierung des Ausducks 3*X+(Y – 12) – Z in die Postfix-Schreibweise (a) 3 * X + (Y – 12) - Z Eingabe Ausgabe: 3 (b) 3 * X + (Y – 12) - Z Eingabe „*“ kommt in den Stapel Ausgabe: 3 (c) 3 * X + (Y – 12) - Z Eingabe Ausgabe: 3X (d) 3 * X + (Y – 12) - Z Eingabe „*“ kommt aus dem Stapel in die Ausgabe, „+“ kommt in den Stapel Ausgabe: 3X* (e) 3 * X + (Y – 12) - Z Eingabe Die öffnende Klammer kommt in den Stapel: (+ (f) 3 * X + (Y – 12) - Z Eingabe Ausgabe: 3X*Y (g) 3 * X + (Y – 12) - Z Eingabe „-„ kommt in den Stapel: -(+ (h) 3 * X + (Y – 12) - Z Eingabe Ausgabe: 3X*Y12 (i) 3 * X + (Y – 12) - Z Eingabe Alles bis zur linken Klammer wird aus dem Stapel entnommen und kommt in die Ausgabe Stapel: + Ausgabe: 3X*Y12(j) 3 * X + (Y – 12) - Z Eingabe Alles bis zur linken Klammer wird aus dem Stapel entnommen und kommt in die Ausgabe Stapel: Ausgabe: 3X*Y12-+ (k) 3 * X + (Y – 12) - Z Eingabe Alles bis zur linken Klammer wird aus dem Stapel entnommen und kommt in die Ausgabe Stapel: Ausgabe: 3X*Y12-+Z (l) Die noch im Stapel liegenden Operationen werden aus dem Stapel entfernt und in die Ausgabe gebracht. Ausgabe: 3X*Y12-+ZDie folgende Beschreibung (in Pseudocode) zeigt, wie der Algorithmus in einem Programmablauf eingebettet werden kann: 1. Initialisiere einen Stapel zur Speicherung von Zeichen für die Aufnahme von Operationssymbolen und Klammern. 2. do if (die nächste Eingabe ist eine linke Klammer) Lies die linke Klammer und lege sie auf dem Stapel ab. else if (die nächste Eingabe ist eine Zahl oder ein anderer Operand) Lies den Operand und schreibe ihn in die Ausgabe. else if (die nächste Eingabe ist eines der Operations-Symbole) { Kellere aus und gib aus, bis drei Dinge auftreten: (1) Der Stapel ist leer. (2) Das nächste Symbol auf dem Stapel ist eine linke Klammer (3) Das nächste Symbol ist eine Operation von geringerem Rang als die vom nachsten Eingabesymbol Falls eine dieser Situationen auftritt, beende das Kellern, lies das nächste Eingabesymol und lege es auf dem Stapel ab } else { Lies und lege das nächste Eingabe-Symbol ab (,das eine rechte Klammer sein sollte). Kellere aus und gib die Operation aus aus dem Stapel aus, bis das nächste Symbol eine linke Klammer ist. Falls keine linke Klammer gefunden wird, dann gib die Fehlermeldung aus: "Keine ausgeglichene Anzahl von Klammern“ und halte an. } while (es gibt noch etwas zum Einlesen). 3. Kellere aus und gib aus die noch vorhandenen Operationen auf dem Stapel. (Es sollte keine linke Klammer übrig sein, anderenfalls hatte der Ausdruck der Eingabe nicht eine ausgeglichene Zahl von Klammern. Gib das zu diesem Algorithmus zugehörige C++-Programm an. Das Programm soll die Klassenschablone Stapel aus der verwenden. 3. Aufgabe Gegeben ist die folgende Beschreibung eines Programmablaufs zur Stapelverarbeitung: 1. Initialisiere einen Stapel zur Aufnahme von Zeichen. 2. do if (die nächste Eingabe ist eine linke Klammer) Lies die linke Klammer und lege sie auf dem Stapel ab. else if (die nächste Eingabe ist eine Zahl oder ein anderer Operand) Lies den Operand und schreibe ihn in die Ausgabe. else if (die nächste Eingabe ist eines der Operations-Symbole) Lies das Operations-Symol und lege es auf dem Stapel ab. else { Lies und lege das nächste Eingabe-Symbol ab (,das eine rechte Klammer sein sollte). Es sollte dann noch ein Operations-Symbol auf den Stapel geben. Kellere es aus und schreibe es in die Ausgabe. Falls es eine solches Symbol nicht gibt, gibt es eine Fehlermeldung: „Zu wenig Operationen im Infix-Ausdruck“ und halte das Programm an. Nach dem Auskellern des Operationssymbols, sollte noch eine linke Klammer auf dem Stapel sein. Kellere sie aus und lege sie ab. Gibt es keine linke Klammer, gib die Fehlermeldung aus: Keine ausgeglichene Anzahl von Klammern“ und halte sie an. } while (es gibt noch etwas zum Einlesen). 3. Der Stapel sollte jetzt leer sein. Andernfalls gibt es eine Fehlermeldung: „Der Ausdruck war nicht voll geklammert“. Ein total geklammerter arithmetischer Ausdruck in Infix-Schreibweise, z.B. (((A+7)*(B/C)-(2*D)) ergibt nach einer in dem vorliegenden Programmablauf beschriebenen Verarbeitung den PostfixAusdruck: A7+BC/*2D*Realisiere diesen Programmablauf für total geklammerte arithmetische Ausdrücke in einem vollständigen C++-Programm, das die Klassenschablone für einen Stapel benutzt.