Home   Cover Cover Cover Cover
 

Übungsaufgaben zu Kapitel 2. Die Sprache C#

  1. 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?


  2. 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;)?


  3. 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?


  4. 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.


  5. 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).


  6. 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 ...


  7. Kurzschlussauswertung. Warum ist die Kurzschlussauswertung in der folgenden Schleifenbedingung wichtig?
    while (p != null && p.name != "John") {...}


  8. 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).


  9. 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.


  10. 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.


  11. Klassen und Structs. Für welche Aufgaben würden Sie Klassen verwenden, für welche Structs?


  12. 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.


  13. 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.


  14. 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.


  15. 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.


  16. Klassen. Erweitern Sie Ihre Klasse In so, dass man mit ihr wahlweise von der Tastatur, von einer Datei oder von einer Zeichenkette lesen kann.


  17. 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?


  18. 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.


  19. Parameterarten. Diskutieren Sie Vor- und Nachteile von Ref-Parametern, Out-Parametern und Parametern, die als Funktionsergebnisse zurückgegeben werden.


  20. 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);).


  21. 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.


  22. 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.


  23. 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();


  24. Abstrakte Klassen. Was ist der Unterschied zwischen einer abstrakten Klasse und einem Interface?


  25. 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.


  26. 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.


  27. 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.


  28. 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.


  29. 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.


  30. 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?


  31. 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.


  32. 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.


  33. 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>>.


  34. 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).


  35. 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.


  36. 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.


  37. 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.


  38. 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.


  39. 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.