Ubungsblatt 4 - FIUS | Universität Stuttgart

Übungsblatt 4
Java Vorkurs (WS 2015)
Aufgabe 1 Übungsblock
In dieser Aufgabe soll ein kleines Programm zur verwaltung von Studenten erstellt werden. Gehe
davon aus, dass nicht mehr 100 Studenten durch das Programm zu verwalten sind. In dem Programm soll es zwei Klassen geben: Student und StudentManager, wobei nur in StudentManager die
main-Methode sein soll.
Ein Student zeichnet sich durch die Eigenschften name, vorname, matrikelNummer, studiengang
und istTutor aus. Wähle für alle Eigenschften einen passenden Typ und beachte die Datenkapselung.
Nur die Eigenschaften studiengang und istTutor sollen geändert werden können. Implementieren sie
dafür entsprechende Schnittstellen. Die anderen Eigenschaften sollen jeweils nur beim Anlegen des
Studendten angegeben werden können.
In der Klasse StudentManager (statische Klasse) sollen die Studenten in einem Array gespeichert
werden. Beachte, dass du vermutlich ein weiteres Attribut benötigst, um die Anzahl der vorhandenen Studenten zu speichern. Außerdem soll die Klasse die Möglichkeit bieten, Studenten über die
Konsole anlegen, bearbeiten und löschen zu können, sowie alle Studenten aufzulisten. Überlegen sie
sich dazu eine sinnvolle Menüstruktur für die Konsole, sowie eine Möglichkeit die Eingabe (Auswahl
aus dem Menü) zu verarbeiten. Sobald ein Auftrag (z.B. Student erstellen) erfolgreich abgeschlossen
wurde, soll wieder das Hauptmenü gezeigt werden. Schütze dein Programm mittels Abfragen vor
möglichen Falscheingaben. Das Erstellen von zusätzlichen Methoden könnte hier sehr sinnvoll sein,
um das Programm zu strukturieren.
In dem Programm werden zwei Klassen benutzt, die wir nach und nch erweitern werden:
(a) Erstelle eine Klasse StudentManager, welche die main-Methode enthält. Erstelle nun eine zweite
Klasse im selben Paket und nenne sie Student. Diese Klasse soll ein privates Attribut vom Typ
String mit dem Namen ’Name’ haben. Implementiere in der Klasse Student zunächst zwei Methoden: den Konstruktor und eine get-Methode. Dem Konstruktor soll als Parameter der Name
des neuen Studenten übergeben werden. Beachte, dass der Konstruktor keinen Rückgabewert
hat. Die Konstruktor-Methode sieht dann etwa so aus:
1
2
3
p u b l i c S t u d e n t ( S t r i n g pName) {
t h i s . name = pName ;
}
Die get-Methode soll den Namen getName() haben und keine Parameter besitzen. Die Methode
soll public sein und den Rückgabetyp String besitzen. Gebe in der Methode lediglich das Attribut
name mit dem return-Befahl zurück. Diese Methode sieht dann so aus:
1
2
3
p u b l i c S t r i n g getName ( ) {
r e t u r n t h i s . name ;
}
Anmerkung: Das this. vor dem Attribut sagt lediglich aus, dass hier das Attribut der eigenen
Klasse gemeint ist. Dies soll Verwirrung zwischen Klassen-Attributen und Variablen vermeiden.
Gehe nun zurück in die Klasse StudentManager. Lege dort ein privates Attribut namens ’student’ an. Dieses Attribut soll vom Typ Student sein und muss als static deklariert werden, da
wir von der StudentManager-Klasse kein Objekt anlegen werden. Lege nun in der main-Methode
Java Vorkurs (WS 2015) – Übungsblatt 4
Seite 2 von 5
einen neuen Studenten an, indem du den new-Operator verwendest. Du musst hier dann auch
das Parameter für den Konstruktor angeben, dh. den Namen, den dein Student haben soll.
Mache danach eine Konsolenausgabe und gebe den Namen des Studenten aus, indem du dir den
Namen mit der getName-Methode holst. Tipp: Du kannst den Methodenaufruf auch direrkt in
den Klammern der Konsolenausgabe machen. Dies erspart dir ein unötiges Zwischenspeichern.
Deine StudentManager-Klasse sollte dann ungefähr so aussehen:
1 p u b l i c c l a s s StudentManager {
2
p r i v a t e s t a t i c Student student ;
3
4
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
5
s t u d e n t = new S t u d e n t ( ”Hans Mü l l e r ” ) ;
6
System . out . p r i n t l n ( s t u d e n t . getName ( ) ) ;
7
}
8
9 }
Teste nun das bisherige Programm. Es sollte auf der Konsole nur der Name des Studenten
ausgegeben werden.
(b) Da wir mehr als nur einen Studenten verwalten wollen, müssen wir eine Möglichkeit finden,
mehrere Studenten zu speichern. Hierfür bietet sich ein Array an. Ändere also das Attribut
student in der Klasse StudentManager auf ein Array vom Typ Student mit der maximalne
Größe 100. Erstelle zudem ein privates, statisches Attribut countOfElements vom Typ int.
Dieses Attribut soll speichern, wieviele Studenten momentan im Array gespeichert werden. Erstelle in der Klasse StudentManager eine private, statische Methode void addStudent(String
pName). Nun soll in dieser Methode ein neuer Student erzeugt, zum Array hinzugefügt und der
Zähler erhöht werden. Lösche dann die Zeile zum Erstellen des Studneten aus der main-Methode
und rufe stattdessen die addStudent-Methode auf. Auch solltest du nun die Konsolenausgabe
in eine For-Schleife packen, die genau so oft wie countOfElements durchläuft. Erzeuge vor der
For-Schleife insgesammt drei Stdenten mit unterschiedlichen Namen. Nach dieser Teilaufgabe
sollte die StudentManager-Klasse sollte dann so aussehen:
1 p u b l i c c l a s s StudentManager {
2
p r i v a t e s t a t i c S t u d e n t [ ] s t u d e n t = new S t u d e n t [ 1 0 0 ] ;
3
p r i v a t e s t a t i c i n t countOfElements = 0 ;
4
5
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
6
addStudent ( ”Hans Mü l l e r ” ) ;
7
addStudent ( ” D a n i e l a Maurer ” ) ;
8
addStudent ( ”Max Mustermann” ) ;
9
f o r ( i n t i =0; i <countOfElements ; i ++){
10
System . out . p r i n t l n ( s t u d e n t [ i ] . getName ( ) ) ;
11
}
12
}
13
14
p r i v a t e s t a t i c v o i d addStudent ( S t r i n g pName) {
15
s t u d e n t [ countOfElements ] = new S t u d e n t (pName) ;
16
countOfElements++;
17
}
18 }
(c) Wir wollen nun die Klasse Student um weitere Eigenschaften und Methoden erweitern. Außer
dem Namen des Studenten wollen wir nun auch die Matrikelnummer (int matrikelnummer),
den Studiengang (String studiengang) und die Eigenschaft istTutor vom Typ boolean speichern. Füge diese Eigenschaften als private Attribute ein. Die Matrikelnummer soll auch dem
Konstruktor übergeben werden. Die anderen beiden Attribute sollen mittles einer set-Methode
verändert werden können. Füge für alle Attribute eine get-Methode ein, die jeweils nur das
Attribut zurück geben. Beachte, dass du auch in der Klasse StdentManager ein paar Zeilen
ändern musst, nachdem du die Parameter des Konstruktors geändert hast.
Wenn du dies alles gemacht hast, sollte die Student-Klasse so aussehen:
1 p u b l i c c l a s s Student {
2
p r i v a t e S t r i n g name ;
Java Vorkurs (WS 2015) – Übungsblatt 4
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 }
Seite 3 von 5
p r i v a t e i n t matrikelnummer ;
private String studiengang ;
private boolean istTutor ;
p u b l i c S t u d e n t ( S t r i n g pName , i n t pMatrikelnummer ) {
t h i s . name = pName ;
t h i s . matrikelnummer = pMatrikelnummer ;
}
p u b l i c S t r i n g getName ( ) {
r e t u r n t h i s . name ;
}
p u b l i c i n t getMatrikelnummer ( ) {
r e t u r n t h i s . matrikelnummer ;
}
p u b l i c void setStudiengang ( S t r i n g pStudiengang ) {
t h i s . studiengang = pStudiengang ;
}
public String getStudiengang () {
return t h i s . studiengang ;
}
public void s etIstTutor ( boolean pIstTutor ) {
t h i s . i s t T u t o r=p I s t T u t o r ;
}
public boolean getIstTutor () {
return this . istTutor ;
}
(d) In dieser Teilaufgabe wollen wir nun ein kleines Menü für die Steuerung des StudentManager auf
der Konsole ausgeben. Erstelle daher eine Methode private static void outputMainMenu(),
die mittels mehrerer System.out.println()-Befehlen ein Hauptmenü mit Überschrift und folgenden Auswahlmöglichkeiten ausgibt: 1: Student hinzufügen 2: Student bearbeiten 3: Student
löschen 4: Alle Studenten anzeigen
(e) Erstelle drei weitere Methoden um Eingaben vom Benutzer abzufragen. Wir machen für jeden Typen, den wir benötigen (String, int und boolean), eine eigene Methode mit entspechendem Rückgabewert. Benenne die Methoden nach dem Schema private static String
readString(). Erstelle in jeder Methode einen Scanner, der den Eingabestrom System.in entgegen nimmt. Den Scanner musst du ganz oben in deiner Quellcode-Datei mit der Zeile
1 i mp ort j a v a . u t i l . S c a n n e r ;
importieren, damit du ihn verwenden kannst. Die Methoden sollen jeweis die eingegebene Zeile
zurückgeben. Die Methoden sehen dann alle etwa so aus:
1
2
3
4
private s t a t i c int readInt () {
S c a n n e r s c a n n e r = new S c a n n e r ( System . i n ) ;
return scanner . nextInt () ;
}
(f) Wir wollen nun das Menü zusammenbauen und die Optionen 1: Student anlegen sowie 4:
Alle Studenten ausgeben implementieren.
Erstelle eine Methode textttprivate static void addStudentDialog(), die den Benutzer Schritt
für Schritt durch den Anlege-Vorgang begleitet und von ihm die nötigen Eingaben abfragt und
schließlich die addStudent(String pName, int pMatrikelnummer)-Methode aufruft. Rufe für
die Abfragen deine selbst geschriebenen readString()- und readInt()-Methoden.
Die Methode, die alle Studenten ausgibt soll private static void outputAllStudents() heißen. Sie besteht im Wesentlichen aus der For-Schleife, die wir bereits in der main-Methode implementiert haben. Nun soll die Methode jedoch zusätzlich eine Überschrift anzeigen und für jeden
Studenten nicht nur den Name anzeigen, sondern auch Matrikelnummer und den Studiengang.
Java Vorkurs (WS 2015) – Übungsblatt 4
Seite 4 von 5
Du musst hierfür den Ausgabe-Text in den Klammern der System.out.println()-Methode
zusammensetzten. Am Ende dieser Teilaufgabe siehst du, eine beispielhafte Implementierung
dafür.
Mache nun die Main-Methode zunächst ganz leer. In sie komment jetzt das Hauptprogramm.
Erstelle dafür in der Main-Methode eine Endlos-Schleife, damit nach jedem abgearbeiteten Auftrag wieder das Hauptmenü angezeigt wird und der Benutzer einen neuen Auftrag auswählen
kann. Füge in die Endlos-Schleife eine Do-While-Schleife ein, die dem Benitzer so lange das
Hauptmenü anzeigt, bis er eine gültige Zahl (von eins bis vier, entsprchend der nummerierten
Optionen) eingegen hat. Danach soll die Eingabe mittels einer Switch-Case-Verzeigung ausgewertet werden. In den jeweiligen Fällen werden lediglich die Dialog-Methoden aufgerufen (z.B.
textttaddStudentDialog(). Die anderen Dialog-Methoden schreiben wir gleich). Unter Option
4. wird die outputAllStudents()-Methode aufgerufen. Wenn du dein Programm startest solltest du nun bereits Studenten anlegen und alle ausgeben können. So könnte die Main-Methode
dann aussehen: (Hier werden zu Beginn noch drei Studenten angelegt, damit man sofort auch
Studenten bearbeiten und löschen kann.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
addStudent ( ”Hans Mü l l e r ” , 2 9 6 7 8 0 4 ) ;
addStudent ( ” D a n i e l a Maurer ” , 2 9 4 5 9 8 0 ) ;
addStudent ( ”Max Mustermann” , 2 9 7 2 3 5 9 ) ;
while ( true ) {
i n t s e l e c t e d O p t i o n = −1;
do {
outputMainMenu ( ) ;
selectedOption = readInt () ;
} w h i l e ( s e l e c t e d O p t i o n <= 1 && s e l e c t e d O p t i o n >= 4 ) ;
switch ( selectedOption ) {
case 1:
addStudentDialog ( ) ;
break ;
case 2:
editStudentDialog () ;
break ;
case 3:
deleteStudentDialog () ;
break ;
case 4:
outputAllStudents () ;
break ;
}
}
}
Die Methode zur Ausgabe aller Student sieht dann in etwa so aus:
1
2
3
4
5
6
7
8
9
pr ivate s t a t i c void outputAllStudents ( ) {
System . out . p r i n t l n ( ) ;
System . out . p r i n t l n ( ”=== Üb e r s i c h t ü b e r a l l e S t u d e n t e n ===” ) ;
f o r ( i n t i = 0 ; i < countOfElements ; i ++) {
System . out . p r i n t l n ( s t u d e n t [ i ] . getName ( ) + ” ( Matrnr . : ”
+ s t u d e n t [ i ] . getMatrikelnummer ( ) + ” , S t u d i e n g a n g : ”
+ student [ i ] . getStudiengang () + ” ) ” ) ;
}
}
(g) Nun fehlen noch die Methoden zum Bearbeiten und Löschen. Kümmern wir uns erst um die Methode zum Bearbeiten. Erstelle eine neue Methode private static void editStudentDialog().
Sie soll zunächst die gewählte Option anzeigen (also dass man jetzt im Bearbeiten-Modus ist),
dann nach dem Index des zu bearbeitenden Studenten fragen (es muss kontrolliert werden, ob
dieser Student überhaupt existiert), dann sollen alle aktuellen Eigenschaften des Studenten ausgegeben und schließlich alle Eigenschaften mit Hilfe der read()-Methoden neu eingelesen und
gespeichert werden.
(h) Als nächstes wollen wir einen Studenten auch noch Löschen können. Erstelle dazu eine neue Methode private static boolean deleteStudent(int pIndex), der der Index des zu löschenden
Java Vorkurs (WS 2015) – Übungsblatt 4
Seite 5 von 5
Studenten übergeben wird. Hier muss dann geprüft werden, ob es den Studenten mit dem angegebenen Index überhaupt gibt. Nun wollen wir im Prinzip dem Studenten an der entsperchenen
Stelle sagen, dass er nicht existiert. Dies können wir machen, indem wir ihm dem Wert null
zuweisen. Der Wert null heißt so viel wie ”Hier ist nichts”, ähnlich wie void bei Methoden.
Wenn wir jedoch einfach mitten aus unserem Array Studenten löschen und den Zähler dekrementieren würden, würde ein ”Lochëntstehen und wir könnten auf den etzen Studenten nicht
mehr zugreifen, weil wir ja immer prüfen ob Index < countOfElements ist. Wir müssen also das
entstandene Loch irgendwie füllen. Damit wir nich alle nachfolgenen Studenten um ein Feld verschieben müssen werden wir der Einfachheit halber nur den letzten (dh. den mit dem höchsten
Index) Studenten in die Lücke verschieben und dann diesen letzten löschen. Wenn der Student
erfolgreich gelöscht wurde soll true zurück gegeben werden, anderen Falles false. Bitte beachte unbedingt, dass sich der Index und der Wert des Attributs countOfElements immer um 1
unterscheiden, da die Index-Zählung bei 0 beginnt. Die deleteStudent(int pIndex)-Methode
könnte dann so aussehen:
1
2
3
4
5
6
7
8
9
10
p r i v a t e s t a t i c b o o l e a n d e l e t e S t u d e n t ( i n t pIndex ) {
i f ( pIndex < countOfElements && pIndex >= 0 ) {
s t u d e n t [ pIndex ] = s t u d e n t [ countOfElements − 1 ] ;
s t u d e n t [ countOfElements −1] = n u l l ;
countOfElements −−;
return true ;
} else {
return f a l s e ;
}
}
(i) Wir brauchen nun noch einen Dialog, der den Benutzer durch den Vorgang leitet und dann
schließlich die deleteStudent()-Methode aufruft. Für diesen Dialog erstellen wir die Methode
deleteStudentDialog(). Auch hier soll am Anfang erst mal angezeigt werden, welche Option
gewählt wurde. Dann soll der Index des zu löschenden Studenten erfragt werden. Nachdem sich
der Benuter dann den Lösch-Vorgang bestätigt hat (hier muss die Methode readBoolean()
eingesetzt werden), wird die deleteStudent(int pIndex)-Methode aufgerufen.
Nun sind alle Funktionen implementiert und das Programm fertig. Teste alle Fuktionen gut
durch und behebe vielleicht auftretende Fehler. Sichere dein Programm ab, indem du immer
prüfst, ob eine Eingabe gültigen Wert hat oder nicht.