|
|
Übungsaufgaben zu Kapitel 2. Die Sprache C#
- Sicherheit. Begründen Sie, warum C# eine sichere
Sprache ist. Welche Arten von Programmierfehlern oder
gefährlichen Situationen werden vom C#-Compiler oder
der CLR abgefangen?
- Enumerationen. Was sind die Vorteile eines
Enumerationstyps (z.B. enum Color {red, blue, green})
gegenüber int-Konstanten
(z.B. const int red = 0, blue = 1, green = 2;)?
- Enumerationen. Studieren Sie die Klasse Enum
aus der Online-Dokumentation des .NET-SDK und schreiben
Sie zwei Methoden zur Ein- und Ausgabe von Werten eines
von Ihnen gewählten Enumerationstyps in textueller Form.
Können Sie die Methoden so allgemein halten, dass Sie
damit Werte eines beliebigen Enumerationstyps lesen und
schreiben können?
- Arrays . Schreiben Sie eine Methode
double[,] MatrixMult(double[,] a, double[,] b)
die zwei Matrizen a und b multipliziert und das Ergebnis
als Funktionswert liefert. Wenn sich a und b auf Grund
ihrer Dimensionen nicht multiplizieren lassen, soll
die Methode eine Ausnahme liefern.
- Strings. Schreiben Sie eine Methode, die aus
einem Pfadnamen (z.B. c:\dotnet\samples\myFile.cs) den
Dateinamen ohne Verzeichnisse und Dateiendung
herausschält (z.B. myFile).
- Ausdrücke. Was ist der Ergebnistyp folgender Ausdrücke:
short s = 1; int i = 2; long x = 3; float f = 4f;
char c = 'a'; Color col = Color.red;
... s + 1 ...
... s + 100000000000 ...
... i + f ...
... c + 1 ...
... col + 1 ...
... 10 * x + (x - '0') ...
... s + 1.0 ...
- Kurzschlussauswertung. Warum ist die Kurzschlussauswertung
in der folgenden Schleifenbedingung wichtig?
while (p != null && p.name != "John") {...}
- Switch-Anweisung. Schreiben Sie eine switch-Anweisung,
die zu einem gegebenen Monat die Anzahl seiner Tage berechnet
(ohne Schaltjahre zu berücksichtigen). Implementieren Sie
eine Version, bei der das Monat durch eine Zahl gegeben ist
und eine andere, bei der es durch einen String gegeben ist.
Vergleichen Sie den erzeugten Code mittels ildasm (siehe
Kapitel 8).
- Ein-, Ausgabe. Schreiben Sie ein Programm, das aus
einem anderen C#-Programm alle Kommentare entfernt, indem
es das Quellprogramm zeichenweise liest und ohne Kommentare
wieder zeichenweise auf eine neue Datei schreibt.
- Formatierte Ausgabe. Erzeugen Sie eine Tabelle der
Quadrate und Wurzeln der ersten n natürlichen Zahlen.
Verwenden Sie dazu formatierte Ausgabe. Zur Berechnung der
Wurzel können Sie die Funktion Math.Sqrt verwenden. Übergeben
Sie n als Kommandozeilenparameter.
- Klassen und Structs. Für welche Aufgaben würden Sie
Klassen verwenden, für welche Structs?
- Structs. Implementieren Sie einen Struct Complex
zum Rechnen mit komplexen Zahlen. Sehen Sie geeignete
Konstruktoren vor sowie Properties, um auf dem reellen
und imaginären Teil einer komplexen Zahl zugreifen zu
können. Implementieren Sie mittels Operator Overloading
die Addition, Multiplikation und den Vergleich komplexer
Zahlen. Sehen Sie auch einen impliziten und einen
expliziten Konversionsoperator vor, mit dem man zwischen
komplexen Zahlen und double konvertieren kann. Überschreiben
Sie schließlich auch die von Object geerbten Methoden
Equals, ToString und GetHashCode.
- Klassen. Implementieren Sie eine Klasse GrowableArray,
die ein dynamisch wachsendes Array beliebiger Objekte
darstellt. Ein Indexer soll den Zugriff auf die einzelnen
Elemente erlauben. Wird über einen Index zugegriffen, der
größer als die bisherige Arraylänge ist, so soll das Array
dynamisch erweitert, d.h. durch ein längeres ersetzt werden,
wobei die Werte des alten Arrays den Anfang des neuen
Arrays bilden sollen.
- foreach, Interfaces. Erweitern Sie Ihre Klasse GrowableArray
so, dass die Elemente im Array mittels einer foreach-Schleife
durchlaufen werden können. Dazu muss GrowableArray das
Interface IEnumerable implementieren. Studieren Sie dieses
Interface in der Online-Dokumentation des .NET-SDK.
- Klassen. Schreiben Sie eine Klasse In mit Methoden
zum Lesen von Zahlen, Wörtern, Strings, Zeichen und
Booleschen Werten von der Tastatur. Bauen Sie dabei
auf die Klasse Console auf.
- Klassen. Erweitern Sie Ihre Klasse In so, dass
man mit ihr wahlweise von der Tastatur, von einer Datei
oder von einer Zeichenkette lesen kann.
- Statische Variablen und Methoden. Nehmen Sie an,
man möchte wissen, wieviele Objekte einer bestimmten Klasse
C im Laufe eines Programms erzeugt wurden. Implementieren
Sie eine solche Klasse und versehen Sie sie mit einer
statischen Zählervariablen sowie mit einer statischen
Methode, mit der die Zählervariable zurückgesetzt werden
kann. Wo muss die Zählervariable erhöht werden?
- Structs und Properties. Implementieren Sie ein Struct
Time zur Verwaltung von Uhrzeiten. Intern sollen Uhrzeiten
in Sekunden gespeichert werden. Es soll aber drei Properties
geben, die den Stunden-, Minuten-, und Sekundenanteil einer
Uhrzeit liefern. Sehen Sie auch überladene Operatoren und
Konstruktoren vor, um mit Uhrzeiten bequem rechnen zu können.
- Parameterarten. Diskutieren Sie Vor- und Nachteile von
Ref-Parametern, Out-Parametern und Parametern, die als
Funktionsergebnisse zurückgegeben werden.
- Variable Anzahl von Parametern. Implementieren Sie
eine Methode Clear, mit der eine beliebige Anzahl von
Elementen eines beliebigen int-Arrays auf 0 gesetzt werden
kann (z.B. Clear(arr, 3, 4, 9, 12);).
- Kreuzreferenzliste. Schreiben Sie ein Programm, das
aus einem anderen C#-Programm eine Kreuzreferenzliste erzeugt.
Eine Kreuzreferenzliste enthält zunächst das ursprüngliche
Programm mit Zeilennummern versehen und dann alle im Programm
vorkommenden Namen samt den Nummern der Zeilen, in denen sie
vorkommen. Schlüsselwörter sollen nicht als Namen gelten.
Hinweis: Verwenden Sie für die Namenliste eine sortierte
Liste (Klasse SortedList) und für die Zeilennummern ein
dynamisches Array (Klasse ArrayList) pro Name. Lesen Sie
die Benutzung dieser Klassen in Kapitel 4 des Buches oder
in der Online-Dokumentation des .NET-SDK nach.
- Objektorientierung. Modellieren Sie die Artikel eines
Web-Shops als Klassen und Unterklassen. Artikel können Bücher,
CDs oder Videos sein. Jeder Artikel hat eine Nummer und einen
Preis. Die einzelnen Artikelarten enthalten noch weitere
Daten, die Sie selbst festlegen können (z.B. Autor, Lieder,
etc.). Sehen Sie entsprechende Konstruktoren vor sowie ein
Property Price, um den Preis abzufragen und zu ändern. Eine
Methode Description, die in jeder der Artikelklassen
überschrieben wird, soll aus den Artikeldaten eine entsprechende
Beschreibung des Artikels zusammenstellen und als String liefern.
Implementieren Sie auch einen Warenkorb, der verschiedene
Artikel enthalten kann und der auf Wunsch eine Beschreibung
der darin enthaltenen Artikel samt Einzelpreis und Gesamtpreis
als String liefert.
- Objektorientierung, dynamische Bindung. Bauen Sie das
Beispiel mit den Klassen Animal und Dog aus Abschnitt 2.9.4 aus,
indem Sie weitere Unterklassen für Cat und Cow hinzufügen.
Implementieren Sie in jeder Klasse eine Methode <7i>Likes(string food),
die true liefert, wenn das Tier das Futter mag. Eine Methode
Speak() soll den für das Tier typischen Laut als String ausgeben.
Eine Tierfarm soll dann wie folgt benutzt werden können:
foreach (Animal a in animalArray)
if (a.Likes("fish")) a.Speak();
- Abstrakte Klassen. Was ist der Unterschied zwischen
einer abstrakten Klasse und einem Interface?
- Delegates. Gegeben sei ein Array von Objekten der
gleichen Art (z.B. Strings, Bruchzahlen oder sonstige Objekte).
Schreiben Sie eine Methode Sort(arr, compare), die das Array
arr sortiert und dazu eine Vergleichsmethode compare(x, y)
verwendet, die als Delegate übergeben wird und zwei Objekte
x und y des Arrays miteinander vergleicht, d.h. feststellt,
ob x größer, kleiner oder gleich y ist.
- Delegates. Implementieren Sie eine Zählerklasse
Counter mit einer Methode Add(x) zum Erhöhen des Zählerwerts
und einer Methode Clear() zum Löschen des Zählerwerts. Wenn
der Zählerwert eine bestimmte Bedingung erfüllt (z.B.
Zählerwert > n) sollen eine oder mehrere Aktionen ausgelöst
werden. Sowohl die Bedingung als auch die Aktionen sollen
als Delegates an die Zählerklasse übergeben werden können.
- Anonyme Methoden. Schreiben Sie eine Methode
static void Plot (Function f) { ... }
der man eine Funktion eine Delegate-Typs
delegate double Function(double x);
übergeben kann und die ein zweidimensionales Diagramm dieser Funktion zeichnet.
Verwenden Sie der Einfachheit halber als "Grafik" eine zweidimensionale char-Matrix.
- Ausnahmen. Die Methode Convert.ToInt32(s) konvertiert
eine im String s gespeicherte Zahlenfolge in eine int-Zahl.
Dabei können verschiedene Ausnahmen auftreten, wenn s nicht
das richtige Format hat oder keinen gültigen Wert enthält.
Studieren Sie die möglichen Ausnahmen in der .NET-SDK-Dokumentation
und schreiben Sie ein Programm, in dem diese Ausnahmen durch
eine try-catch-Anweisung abgefangen werden.
- Namensräume. Der Namensraum System.Drawing enthält
einen Typ namens Color. Implementieren Sie in einem eigenen
Namensraum Util ebenfalls einen Typ Color und verwenden Sie
beide in einem dritten Namensraum. Schlagen Sie in der
.NET-SDK-Dokumentation nach, was man alles mit
System.Drawing.Color machen kann.
- Namensräume, Assemblies, DLLs. Versuchen Sie, anhand
der .NET-SDK-Dokumentation herauszufinden, zu welchen Namensräumen
und zu welchen Assemblies die Typen Pen, Directory,
FieldInfo, StringBuilder, Stack und Page gehören. In welchen
DLLs sind sie gespeichert?
- Generische sortierte Liste. Implementieren Sie eine sortierte
verkettete Liste mit den Operationen Add(x) und Remove(x) sowie mit
einem Property Count, das die Anzahl der Elemente der Liste liefert. Außerdem
soll es einen Indexer geben, mit dem man auf jedes Listenelement zugreifen kann.
Der Typ der Listenelemente soll beliebig sein.
- Generischer binärer Suchbaum. Schreiben Sie einen generischen binären
Suchbaum BinaryTree<K, V>, der Werte vom Typ V unter ihrem Schlüssel
vom Typ K speichert. Sehen Sie eine Methode Insert vor, mit der man
ein Schlüssel/Wert-Paar in den Baum einfügen kann, sowie eine Methode Contains,
die prüft, ob ein bestimmter Schlüssel im Baum enthalten ist. Schreiben Sie auch
einen Indexer, der den Wert zu einem gegebenen Schlüssel liefert oder eine
Ausnahme auslöst, wenn der Schlüssel nicht gefunden wurde.
- Liste von Listen. Verwenden Sie den in der Online-Dokumentation von
.NET beschriebenen Typ List<T>, um eine Liste von Wortlisten anzulegen.
Lesen Sie einen Text aus mehreren Zeilen, wobei jede Zeile aus mehreren Wörtern
(Buchstabenfolgen) besteht. Alle Wörter einer Zeile sollen in einer Liste vom
Typ List<string> gespeichert werden. Bilden Sie dann aus den Wortlisten
der einzelnen Zeilen wiederum eine Liste vom Typ List<List<string>>.
- Generische Methode. Schreiben Sie eine generische Methode
list = Copy(array), die ein Array beliebigen Elementtyps in eine generische
Liste gleichen Elementtyps kopiert. Verwenden Sie als Listentyp List<T>
(siehe Online-Dokumentation von .NET).
- Iterieren über eine Liste. Implementieren Sie eine Klasse zur Verwaltung
einer verketteten Liste von Namen (Strings). Sehen Sie folgende Iteratoren vor:
- Eine allgemeine Iterator-Methode, die alle in der Liste gespeicherten Namen liefert.
- Eine spezifische Iterator-Methode, die nur jene Namen der Liste liefert, die mit
einem bestimmten String beginnen. Der String soll als Parameter mitgegeben werden.
- Ein Iterator-Property, das nur jene Namen der Liste liefert, die länger als 5
Buchstaben sind.
- Iterieren über Bestandteile eines Domainnamens. Implementieren Sie eine
Klasse Domain, in der ein Domainname (z.B.
www.ssw.uni-linz.ac.at )
gespeichert werden kann. Sehen Sie ein Iterator-Property vor, das die durch Punkte
getrennten Bestandteile des Domainnamens liefert.
- Iterieren über einen Binärbaum. Implementieren Sie eine Klasse zur Verwaltung
eines binären Suchbaums aus Zahlen. Sehen Sie einen allgemeinen Iterator vor, mit dem
man die im Baum gespeicherten Zahlen in Infix-Ordnung (d.h. linker Teilbaum, Wurzel,
rechter Teilbaum) durchlaufen kann.
- Attribute. Verwenden Sie das Attribut Conditional,
um Hilfsdruckmethoden zu definieren, die Sie bei Bedarf
abschalten können. Wenden Sie diese Hilfsdruckmethoden
bei der Implementierung einer Klasse Stack an.
- XML-Kommentare. Versehen Sie eine von Ihnen implementierte
Klasse mit XML-Kommentaren und sehen Sie sich an, was der
Compiler daraus erzeugt, wenn er mit der Option
/doc:myFile.xml aufgerufen wird.
|