diff options
| author | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
|---|---|---|
| committer | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
| commit | 33613a85afc4b1481367fbe92a17ee59c240250b (patch) | |
| tree | 670b842326116b376b505ec2263878912fca97e2 /Bachelor/Prog2/Z-Uebung/Z-Uebung.htm | |
| download | Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.gz Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.bz2 | |
Diffstat (limited to 'Bachelor/Prog2/Z-Uebung/Z-Uebung.htm')
| -rw-r--r-- | Bachelor/Prog2/Z-Uebung/Z-Uebung.htm | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/Bachelor/Prog2/Z-Uebung/Z-Uebung.htm b/Bachelor/Prog2/Z-Uebung/Z-Uebung.htm new file mode 100644 index 0000000..0790d88 --- /dev/null +++ b/Bachelor/Prog2/Z-Uebung/Z-Uebung.htm @@ -0,0 +1,330 @@ +<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="Hans-Peter Weber">
+ <meta name="GENERATOR" content="Microsoft FrontPage 5.0">
+ <title>Klausur SS 04</title>
+</head>
+<body>
+
+<table BORDER WIDTH="100%" >
+<tr>
+<td WIDTH="25%" BGCOLOR="#EFEFDE">FH Darmstadt
+<br>FB Informatik
+<p>Prof.Dr.H.P.Weber</td>
+
+<td>
+<p align="center">
+<center><font size=+3>Programmieren II</font></center>
+<br>
+<center><font size="+3">Übung</font></center>
+</td>
+
+<td WIDTH="25%" BGCOLOR="#EFEFDE">
+<center>
+<p><font size="6"> </font><font size="5">Juni 2005</font></p>
+</center>
+</td>
+</tr>
+</table>
+
+<br>
+
+<table>
+<tr VALIGN=TOP>
+<td>Es soll die folgende Klassenhierarchie für zweidimensionale Figuren
+implementiert werden:<br>
+ Abstrakte Basisklasse <b><tt>Shape</tt></b>, davon direkt abgeleitet die
+ Klassen <b><tt>
+Polyline</tt></b> und <b><tt>Ellipse</tt></b>. Von <b><tt>
+Polyline</tt></b> direkt abgeleitet die Klassen <b><tt>L</tt></b><b><tt>ine</tt></b>
+ und <b><tt>Polygon</tt></b> und zusätzlich von <b><tt>Polygon</tt></b>
+ abgeleitet die Klasse <b><tt>Rectangle</tt></b>. Außerdem von <b><tt>Ellipse</tt></b>
+ abgeleitet die Klasse <b><tt>Circle</tt></b>.</td>
+</tr>
+</table>
+
+<br>
+
+<table WIDTH="100%" BGCOLOR="#EFEFDE" >
+<tr>
+<td>Teil 1:</td>
+</tr>
+</table>
+
+<p>Zunächst werden nur die grundlegenden Klassen <b> <tt>Shape</tt></b> und <b> <tt>
+Polyline</tt></b> entwickelt und getestet. Da die Klassen der <b> <tt>Shape</tt></b>-Hierarchie
+mit Punkten arbeiten, wird zur Darstellung eines Punktes auch eine Klasse <b> <tt>
+Point</tt></b> definiert:</p>
+<ul>
+<li>
+Die Klasse <b> <tt>Point</tt></b> besitzt die <b> <tt>public</tt></b>-Elemente <tt> <b>
+x</b></tt> und <b> <tt>y</tt></b> vom Typ <b><tt>double</tt></b> und einen
+entsprechenden Konstruktor mit zwei Parametern, die beide den Default-Wert <tt>
+<b> 0.0</b></tt> haben.<br>
+Die Methode <b> <tt>distance</tt></b> liefert den Abstand zu einem zweiten
+Punkt, der als Argument übergeben wird. Der Abstand von zwei Punkten (x1, y1)
+und (x2, y2) ist die Wurzel aus (x2 - x1)<sup>2</sup> + (y2 - y1)<sup>2</sup> .
+<br>
+Die Methode <b> <tt>toString</tt></b> liefert den Punkt als String in der Form <b> <tt>
+(x, y)</tt></b>.<br>
+Der Operator <b> <tt>*=</tt></b> multipliziert den Punkt mit einer
+Gleitpunktzahl.<br>
+Außerdem werden die folgenden globalen Operationen bereitgestellt:<br>
+<b> <tt>+</tt></b> und <b> <tt>-</tt></b>
+Liefert die Summe bzw. Differenz zweier Punkte.<br>
+<b> <tt>==</tt></b> und <b> <tt>!=</tt></b> Vergleicht zwei
+Punkte.<br>
+<b> <tt><<</tt></b>
+Gibt einen Punkt auf einen Stream aus.</li>
+<li>
+Die <b> <tt>Shape</tt></b>-Klasse enthält ein Attribut <b> <tt>anchor</tt></b> (Anker,
+Bezugspunkt), das die Lage der Figur festlegt. Durch Verschiebung des Ankers
+wird also die gesamte Figur verschoben. Der Anker wird in der <b> <tt>Shape</tt></b>-Klasse
+als <b> <tt>protected</tt></b>-Element gespeichert. Der Konstruktor
+initialisiert den Anker mit dem als Argument übergebenen Punkt oder mit dem
+Default-Wert <b><tt>Point(0,0)</tt></b>. Zugriffsmethoden erlauben das Lesen und
+Setzen des Ankers. Die Verschiebung erfolgt mit der Methode <b><tt>move</tt></b>,
+die zwei Parameter für die Verschiebung in x- und y-Richtung besitzt.</li>
+
+<li>
+Die Klasse <b><tt>Shape</tt></b> ist eine abstrakte Klasse. Neben dem virtuellen
+Destruktor stellt sie das folgende polymorphe Interface bereit: Die Methode <tt><b>toString</b></tt>
+liefert die Daten einer Figur als String. Für die Klasse <b><tt>Shape</tt></b>
+sind das die Koordinaten des Ankers. Außerdem enthält <b><tt>Shape</tt></b>
+die rein virtuellen Methoden <b><tt>scale</tt></b> und <b><tt>draw</tt></b>. <b><tt>scale</tt></b>
+verkleinert oder vergrößert die Figur um einen Faktor, der als Argumnet
+übergeben wird. Die Methode <b><tt>draw</tt></b> wird zum Zeichnen einer Figur
+bereitgestellt, aber nicht genutzt (d.h. leer implementiert).</li>
+
+<li>
+Die Klasse <b> <tt>Polyline</tt></b> stellt einen Linienzug dar. Beispielsweise
+besteht folgender Linienzug : Anker - E1 - E2 - E3 - E4 aus vier Linien mit den Endpunkten E1 bis E4. Die Endpunkte werden relativ zum
+Anker in einem dynamisch erzeugten Array gespeichert. Entsprechend besitzt die
+Klasse <b><tt>Polyline</tt></b> zwei Datenelemente: Ein dynamisches Element,
+nämlich einen Zeiger auf das Array mit <b> <tt>Point</tt></b>-Elementen, und
+eine Variable für die Anzahl der Linien. Definieren Sie verschiedene
+Konstruktoren: Einen Default-Konstruktor, einen Konstruktor mit einem <b> <tt>Point</tt></b>-Parameter
+zur Festlegung des Ankers, einen Konstruktor mit zwei <b> <tt>Point</tt></b>-Parametern
+für eine Linie und einen Konstruktor, dem ein Array mit den Punkten eines
+Linienzuges und die Anzahl der Punkte übergeben werden. Jeder Konstruktor setzt
+den Zeiger und die Anzahl der Linien auf <b><tt>0</tt></b>, wenn das Objekt noch
+keine Linie enthält. Andernfalls erzeugt der Konstruktor dynamisch das Array für
+die Endpunkte gemäß der aktuellen Anzahl Linien. Für jeden Endpunkt wird
+die Differenz zum Anker gespeichert. Das dynamische Array wird vom Destruktor
+wieder freigegeben. Da die Klasse <b><tt>Polyline</tt></b> ein dynamisches
+Element besitzt müssen auch Kopierkonstruktor und Zuweisungsoperator definiert
+werden.</li>
+
+<li>
+Redefinieren Sie für die Klasse <b><tt>Polyline</tt></b> alle rein virtuellen
+Methoden der Klasse <b><tt>Shape</tt></b> und die Methode <tt><b>toString</b></tt>, die
+die Koordinaten der Eckpunkte als String liefert.
+Stellen Sie ferner eine Methode bereit, die die Anzahl Linien im Polygon
+zurückgibt, und eine Methode, die die Gesamtlänge liefert.</li>
+
+<li>
+
+Überladen Sie schließlich zweimal den <b><tt>operator+=</tt></b>: Ist das
+Argument ein Punkt, soll eine weitere Linie zu diesem Punkt angehängt werden.
+Ist das Argument ein <b><tt>Polyline</tt></b>-Objekt, soll dessen gesamter
+Linienzug an den letzten Punkt angehängt werden.
+<ul>
+<li>
+Wenn eine Linie angehängt wird, muss das Array mit den Endpunkten vergrößert
+werden.
+</li>
+<li>
+Zu den relativen Koordinaten des anzuhängenden Linienzugs müssen die relativen
+Koordinaten des letzten Punktes addiert werde.
+</li>
+</ul>
+Testen Sie die Klasse <b><tt>Polyline</tt></b>, indem Sie mit jedem zur
+Verfügung stehenden Konstruktor ein Objekt erzeugen und sich anzeigen lassen.
+Rufen Sie dann jede Methode der Klasse mindestens einmal auf.</li>
+
+</ul>
+
+<table WIDTH="100%" BGCOLOR="#EFEFDE" >
+<tr>
+<td>Teil 2:</td>
+</tr>
+</table>
+
+<p>Ergänzen Sie die <b> <tt>Shape</tt></b>-Klassenhierarchie um die noch
+fehlenden Klassen <b><tt>Line</tt></b>, <b><tt>Polygon</tt></b>, <b><tt>Rectangle</tt></b>,
+<b><tt>Ellipse</tt></b> und <b><tt>Circle</tt></b>:</p>
+<ul>
+<li>
+Die Klasse <b><tt>Line</tt></b> besitzt mindestens zwei Konstruktoren: Die
+Endpunkte einer Linie sollen als zwei <b><tt>Point</tt></b>-Objekte oder direkt
+in x-, y-Koordinaten angegeben werden können. Die Redefinition von geerbten
+Methoden ist nicht notwendig. Allerdings soll es nicht möglich sein, an eine
+Linie einen weiteren Punkt oder einen Linienzug anzuhängen!</li>
+<li>
+Ein <b><tt>Polygon</tt></b> wird als geschlossener Linienzug betrachtet: Die Linie vom letzten
+Punkt zum ersten Punkt (=Anker) gehört logisch zur Figur. Entsprechend müssen
+die Methoden redefiniert werden, die die Anzahl Linien bzw. die Gesamtlänge
+zurückgeben. Stellen Sie zusätzlich Methoden bereit, die die Anzahl Ecken (=
+Anzahl Linien) und den Umfang (=Gesamtlänge) liefern:</li>
+<li>
+Die Klasse <b><tt>Rectangle</tt></b> beschreibt Vierecke mit der linken unteren
+Ecke als Anker, deren Seiten parallel zu den x- und y-Koordinaten verlaufen.
+Definieren Sie zuerst einen Konstruktor, dem der Anker sowie die Breite und
+Höhe des Rechtecks übergeben wird. Ein zweiter Konstruktor erzeugt ein
+Rechteck aus zwei Punkten, nämlich der linken unteren Ecke und der rechten
+oberen Ecke. Stellen Sie Methoden bereit, die die Höhe und Breite des Rechtecks
+liefern. Auch für Rechtecke soll es nicht möglich sein, einen weiteren Punkt
+oder einen Linienzug anzuhängen.</li>
+
+<li>
+Definieren Sie schließlich die Klassen <b><tt>Ellipse</tt></b> und <b><tt>Circle</tt></b>.
+Eine Ellipse wird durch den Mittelpunkt und die beiden Halbachsen a und b
+beschrieben. Der Mittelpunkt ist der Anker der Figur. Neben einem Konstruktor
+und den Zugriffsmethoden für die Halbachsen soll auch eine Methode definiert
+werden, die den Umfang der Ellipse liefert (Verwenden Sie zur Berechnung des
+Umfangs einer Ellipse die Näherungsformel U = PI * ( 3/2*(a+b) - sqrt(a*b) )
+wobei PI = 3.14159). Außerdem müssen die geerbten Methoden <b><tt>scale</tt></b>
+und <b><tt>toString</tt></b> redefiniert werden.</li>
+
+<li>
+Ein Kreis ist eine Ellipse, deren Halbachsen gleich lang sind und den Radius des
+Kreises bilden. Außer einem Konstruktor soll die Klasse <b><tt>Circle</tt></b>
+zusätzlich die Methoden <b><tt>getRadius</tt></b> und <b><tt>setRadius</tt></b>
+bereitstellen. Auch ist die Methode <b><tt>toString</tt></b> zu redefinieren.</li>
+
+<li>
+
+Erweitern Sie das Anwendungsprogramm aus Teil 1 so, dass auch die neuen Klassen
+getestet werden.
+</li>
+
+</ul>
+
+
+<table WIDTH="100%" BGCOLOR="#EFEFDE" >
+<tr>
+<td>Teil 3:</td>
+</tr>
+</table>
+
+<p>Die Figuren eines 'Bildes' bestehend aus Objekten der <b> <tt>Shape</tt></b>-Hierarchie
+werden in einer verketteten Liste verwaltet und in der Reihenfolge 'gezeichnet',
+wie sie in der Liste vorkommen. Dazu soll <b><tt>std::list</tt></b> aus der STL
+verwendet werden:</p>
+
+<ul>
+<li>
+Zur Realisierung einer inhomogenen Liste werden nicht die Objekte selbst sondern
+<tt><b>Shape</b></tt>-Zeiger in der Liste gespeichert. Dem Listentyp soll
+daher der Name <b><tt>ShapePtrList</tt></b> mittels <b><tt>typedef</tt></b>
+zugewiesen werden. Danach können Objekte dieses Typs angelegt und die in <b><tt>std::list</tt></b>
+vorhandenen Methoden aufgerufen werden, z.B. wird mit <b><tt>push_back</tt></b>
+ein <tt><b>Shape*</b></tt> auf ein zuvor erzeugtes Objekt der <tt><b>Shape</b></tt>-Hierarchie
+an die Liste angehängt.</li>
+<li>
+Schreiben Sie ein Anwendungsprogramm, das Zeiger auf verschiedene Objekte der <tt><b>Shape</b></tt>-Hierarchie
+in eine Liste vom Typ <b><tt>ShapePtrList</tt></b> einfügt. Die Objekte sollen
+mit <tt><b>new</b></tt> dynamisch erzeugt werden. Geben Sie die <tt><b>Shape</b></tt>-Objekte
+der Liste aus. Löschen Sie dann einige Elemente und zeigen Sie die Liste erneut
+an. Schreiben Sie zur Ausgabe der <tt><b>Shape</b></tt>-Objekte eine globale
+Funktion <b><tt>printShapeList</tt></b>, die als Argument eine Referenz auf die
+Liste erhält und mithilfe der Methoden <b><tt>t</tt></b><b><tt>oString</tt></b>
+die <tt><b>Shape</b></tt>-Objekte der Liste anzeigt. Geben Sie zusätzlich mit
+dem Operator <b><tt>type</tt></b><b><tt>id</tt></b> auch den Typ der Objekte
+aus.</li>
+</ul>
+
+<table WIDTH="100%" BGCOLOR="#EFEFDE" >
+<tr>
+<td>Teil 4:</td>
+</tr>
+</table>
+
+<p>Die Klasse <b><tt>ShapePtrList</tt></b> wird noch in zwei Schritten
+verbessert:</p>
+
+<ul>
+<li>
+Bisher speichert jedes Listenelement einen einfachen <tt><b>Shape</b></tt>-Zeiger.
+Deshalb wird beim Löschen eines Listenelements nur der Zeiger nicht aber das <tt><b>Shape</b></tt>-Objekt
+selbst gelöscht, was zu Speicherlecks führt. Ebenso werden beim Kopieren und
+Zuweisen ganzer Listen nur die Zeiger kopiert ('flache Kopie'), was gravierende
+Laufzeitfehler verursachen kann. Daher sollen die Zeiger durch 'intelligente
+Zeiger (smart pointer)' ersetzt werden, die z.B. das adressierte Objekt
+zerstören, wenn sie selbst zerstört werden. Gehen Sie dazu wie folgt vor:</li>
+<ul>
+<li>
+Ergänzen Sie zuerst die <tt><b>Shape</b></tt>-Klasse durch eine rein virtuelle
+Methode <tt><b>clone</b></tt>. Diese Methode muss in jeder abgeleiteten Klasse
+redefiniert werden, indem sie eine dynamisch erzeugte Kopie des aktuellen
+Objekts zurückgibt.</li>
+<li>
+Definieren Sie dann die Klasse <b><tt>ShapePtr</tt></b> zur Darstellung eines
+intelligenten Zeigers auf <tt><b>Shape</b></tt>-Objekte. Als Attribut besitzt
+die Klasse einen <tt><b>Shape</b></tt>-Zeiger, der vom Konstruktor mit dem
+Parameter vom Typ <tt><b>Shape*</b></tt> bzw. dem Default-Wert 0 initialisiert
+wird. Außerdem muss ein eigener Kopierkonstruktor definiert werden. Dieser
+erzeugt zunächst mithilfe der Methode <tt><b>clone</b></tt> eine Kopie des <tt><b>Shape</b></tt>-Objekts
+und läßt den <tt><b>Shape</b></tt>-Zeiger auf diese Kopie zeigen. Der
+Destruktor zerstört das <tt><b>Shape</b></tt>-Objekt, auf das der Zeiger
+verweist. Der Zuweisungsoperator wird zweifach überladen, so dass sowohl ein
+anderes <tt><b>ShapePtr</b></tt>-Objekt als auch ein einfacher <tt><b>Shape</b></tt>-Zeiger
+zugewiesen werden kann. In beiden Fällen wird das aktuelle <tt><b>Shape</b></tt>-Objekt
+zerstört und der Zeiger auf eine Kopie des <tt><b>Shape</b></tt>-Objekts
+gesetzt, auf das der übergebene Zeiger verweist. Die Operatoren <tt><b>*</b></tt>
+und <tt><b>-></b></tt> sind so zu überladen, dass ein <tt><b>ShapePtr</b></tt>-Objekt
+wie ein gewöhnlicher Zeiger verwendet werden kann. Der
+Dereferenzierungsoperator liefert eine Referenz auf das adressierte <tt><b>Shape</b></tt>-Objekt
+und der Pfeiloperator liefert den <tt><b>Shape</b></tt>-Zeiger selbst.
+Schließlich soll auch eine Konvertierung eines <tt><b>ShapePtr</b></tt>-Objekts
+in einen <tt><b>Shape</b></tt>-Zeiger möglich sein. Fügen Sie deshalb noch die
+entsprechende Konvertierungsfunktion hinzu.</li>
+</ul>
+Die Definition der Liste mit Zeiger auf <tt><b>Shape</b></tt>-Objekte lautet nun
+wie folgt:<br>
+<tt><b>typedef List< ShapePtr > ShapePtrList;<br>
+</b></tt>Stellen Sie die Definitionen der Klassen <tt><b>ShapePtr</b></tt> und <tt><b>ShapePtrList</b></tt>
+in eine neue Header-Datei <tt><b>ShapeList.h</b></tt>. Verwenden Sie zum Testen
+die Funktionen <tt><b>main</b></tt> und <tt><b>printShapeList</b></tt> aus Teil
+3. Diese sollten unverändert mit der neuen Definition der Liste lauffähig
+sein.
+<li>
+Um die Klasse <tt><b>ShapePtrList</b></tt> mit eigenen Methoden erweitern zu
+können, wird jetzt die Klasse <tt><b>ShapePtrList</b></tt> von der
+Standardklasse <tt><b>std::list</b></tt> abgeleitet:<br>
+<tt><b>class ShapePtrList : public list< ShapePtr ><br>
+</b></tt>Ergänzen Sie die Klasse <tt><b>ShapePtrList</b></tt> durch die
+Methoden <tt><b>scale</b></tt> und <tt><b>toString</b></tt>. Die Methode <tt><b>scale</b></tt>
+verkleinert oder vergrößert jede Figur der Liste um einen Faktor, der als
+Argument übergeben wird. Die Methode <tt><b>toString</b></tt> liefert einen
+String mit dem Inhalt der Liste: Für jede Figur der Liste wird in einer neuen
+Zeile zuerst der Typname der Figur in den String geschrieben und dann das
+Ergebnis der Aufrufes der <tt><b>toString</b></tt>-Methode für die jeweilige
+Figur.
+</li>
+</ul>
+Testen Sie die verbesserte Klasse
+<tt><b> ShapePtrList</b></tt>. Ändern Sie die <tt><b>main</b></tt>-Funktion
+aus Teil 3 wie folgt: Entfernen Sie die globale Funktion <tt><b>printShapeList</b></tt>
+und verwenden Sie zur Ausgabe der Liste die Methode <tt><b>toString</b></tt>.
+Erzeugen Sie eine Kopie der Liste und modifizieren Sie die Figuren der neuen
+Liste durch einen Aufruf der Methode <tt><b>scale</b></tt>. Nur die Figuren der
+neuen Liste dürfen sich dadurch verändern. Testen Sie auch die Zuweisung
+ganzer Listen. Den Aufruf der Destruktoren können Sie sichtbar machen,
+indem Sie im virtuellen Destruktor der Klasse <tt><b>Shape</b></tt> eine
+Meldung ausgeben.
+<br>
+
+<table>
+<tr>
+<td COLSPAN = 2>
+<hr width="100%">
+<font size=-1>Quelle: Prinz / Kirch-Prinz: C++ Das Übungsbuch</font>
+<br>
+</td>
+</tr>
+</table>
+
+</body>
\ No newline at end of file |
