© APSIS GmbH , Polling, 2000
in der ersten Auflage des Lehrbuchs Programmieren mit Java
Stand: 19. Oktober 1999
In der 15. Zeile des Programms soll die Ausnahme vom Typ VollAusn einen anderen Namen, z.B. a haben:
catch(VollAusn a) {
und nicht wie im Buch
catch(VollAusn ausnahme) {
Am Ende der 5. Zeile auf der Seite fehlt ein Strichpunkt. Somit ist die Anweisung richtig:
ActionListener lauscher11 = new ActionListener() { // anonyme Klasse public void actionPerformed(ActionEvent ereignis) { ... // Antwort auf die Menüauswahl } };
und nicht wie im Buch
ActionListener lauscher11 = new ActionListener() { // anonyme Klasse public void actionPerformed(ActionEvent ereignis) { ... // Antwort auf die Menüauswahl } }
Die vorletzte und drittvorletzte Zeile des Programms müssen vertauscht werden (die globale Variabe attrappe muß außerhalb der Methode inhalt vereinbart werden). Die letzten drei Zeilen der Klasse EinEimer sind somit
} private static Gefuellt attrappe; }
und nich wie im Buch:
private static Gefuellt attrappe; } }
Der Parametertyp des Konstruktors MengeGen (letzte Zeile auf der Seite 177) und der Methode fuellen (2. Zeile auf der Seite 178) ist nicht Element sondern Object. Somit sind die aufgeführten Zeilen der Klassenvereinbarung von MengeGen
class MengeGen implements Menge { // (8.8) public MengeGen(final Object element) { ... } // merkt Klasse von element public MengeGen(final MengeGen menge) { ... } // like menge public void fuellen(final Object element) { ... } // like element
und nich wie im Buch:
class MengeGen implements Menge { // (8.8) public MengeGen(final Element element) { ... } // merkt Klasse Element von element public MengeGen(final MengeGen menge) { ... } // like menge public void fuellen(final Element element) { ... } // like element
Im ersten Programmstück auf der Seite sollen die Indizes der Reihung zweiEimer nicht 1 und 2 sondern 0 und 1 heißen:
zweiEimer[0] = new Eimer(); zweiEimer[1] = new Eimer(); public void linksFuellen() throws VollAusn { zweiEimer[0].fuellen(); } public void rechtsFuellen() throws VollAusn { zweiEimer[1].fuellen(); }
und nicht wie im Buch
zweiEimer[1] = new Eimer(); zweiEimer[2] = new Eimer(); public void linksFuellen() throws VollAusn { zweiEimer[1].fuellen(); } public void rechtsFuellen() throws VollAusn { zweiEimer[2].fuellen(); }
In der Mitte der Seite steht der Konstruktor Reihung. In der zweiten Zeile des Rumpfs sollen die runden Klammern ( und ) auf eckige [ und ] ausgetauscht werden:
public void Reihung(int laenge) { reihung = new Element[laenge]; }
und nicht wie im Buch
public void Reihung(int laenge) { reihung = new Element(laenge); }
Im Hauptstrang des Methodenrumpfs eintragen fehlt die letzte Zeile:
juengste = neu;
Außerdem ist es überflüssig, den neuen Knoten zuerst mit einer verbindung-Komponente zu erzeugen, dann aber diese zurückzusetzen; es ist einfacher, die verbindung-Komponente gleich auf null zu setzen:
neu = new Knoten(element, null); // throws OutOfMemoryError
Die Methode ist also richtig:
public void eintragen (final Object element) throws VollAusn { try { neu = aelteste.verbindung; // throws NullPointerException im Sonderfall, wenn Warteschlange noch leer neu = new Knoten(element, null); // throws OutOfMemoryError juengste.verbindung = neu; // neuer jüngster Knoten wird eingefügt juengste = neu; } ...
und nicht wie im Buch
public void eintragen (final Object element) throws VollAusn { try { neu = aelteste.verbindung; // throws NullPointerException im Sonderfall, wenn Warteschlange noch leer neu = new Knoten(element, aelteste.verbindung); // throws OutOfMemoryError neu.verbindung = null; // zurücksetzen juengste.verbindung = neu; // neuer jüngster Knoten wird eingefügt } ...
Die Prozedur bruchzahlLesen wirft die Ausnahme java.io.IOException (vom System.in.read-Aufruf in der 4. Zeile) aus. Die Variable i in der viertletzten Zeile muß auch außerhalb der Schleife vereinbart werden. In der drittletzten Zeile heißt der Parameter des String-Konstruktors nicht buffer, sondern puffer. Somit ist die Methode richtig
public static float bruchzahlLesen() throws java.io.IOException { // liest float-Wert // (10.24) StringBuffer puffer = new StringBuffer(); // Puffer, Eingabe zu sammeln while (true) { int i = System.in.read(); // ein Zeichen lesen char c = (char)i; // Zeichen konvertieren if (c == '\n' || c == '\r') break; // Ende der Zeile? ¬ puffer.append(c); // neues Zeichen am Ende des Puffers hinzufügen } int i = System.in.read(); // Rest der Eingabe verwerfen Float f = new Float(0).valueOf(new String(puffer)); // konvertieren return f.floatValue(); // float-Wert herauslesen }
und nicht wie im Buch
public static float bruchzahlLesen() { // liest float-Wert // (10.24) StringBuffer puffer = new StringBuffer(); // Puffer, Eingabe zu sammeln while (true) { int i = System.in.read(); // ein Zeichen lesen char c = (char)i; // Zeichen konvertieren if (c == '\n' || c == '\r') break; // Ende der Zeile? ¬ puffer.append(c); // neues Zeichen am Ende des Puffers hinzufügen } i = System.in.read(); // Rest der Eingabe verwerfen Float f = new Float(0).valueOf(new String(buffer)); // konvertieren return f.floatValue(); // float-Wert herauslesen }
Beim 3. Parameter ausgabe der Methode mischen ist es sinnvoll, final wegzulassen, um anzudeuten, dass die Datei mit dem Namen ausgabe verändert wird:
final String eingabe1, final String eingabe2, String ausgabe) {
und nicht wie im Buch
final String eingabe1, final String eingabe2, final String ausgabe) {
In den 9., 10., 14., 18., 24 und 28. Zeilen des Programms soll für die Dateiobjekte band1 und band2 jeweils nicht die Methode write, sondern die Methode read aufgerufen werden. Somit lautet die Methode richtig
public void mischen( // vorsortierte Dateien werden gemischt // (10.28) final String eingabe1, final String eingabe2, String ausgabe) { IFile band1 = new IFile(), band2 = new IFile(); OFile band3 = new OFile(); Element puffer1 = new Element(), puffer2 = new Element(); // geordnet band1.open(eingabe1); band2.open(eingabe2); band3.open(ausgabe); band1.read(puffer1); band2.read(puffer2); while (!band1.eof() && !band2.eof()) { if (puffer1.kleiner(puffer2)) { // Operation für Element band3.write(puffer1); // den kleineren ausschreiben band1.read(puffer1); // und wieder einlesen } else { band3.write(puffer2); band2.read(puffer2); } } // band1 oder band2 ist zu Ende // Rest kopieren: while (!band1.eof()) { band3.write(puffer1); band1.read(puffer1); } while (!band2.eof()) { band3.write(puffer2); band2.read(puffer2); } }
und nicht wie im Buch
public void mischen( // vorsortierte Dateien werden gemischt // (10.28) final String eingabe1, final String eingabe2, final String ausgabe) { IFile band1 = new IFile(), band2 = new IFile(); OFile band3 = new OFile(); Element puffer1 = new Element(), puffer2 = new Element(); // geordnet band1.open(eingabe1); band2.open(eingabe2); band3.open(ausgabe); band1.write(puffer1); band2.write(puffer2); while (!band1.eof() && !band2.eof()) { if (puffer1.kleiner(puffer2)) { // Operation für Element band3.write(puffer1); // den kleineren ausschreiben band1.write(puffer1); // und wieder einlesen } else { band3.write(puffer2); band2.write(puffer2); } } // band1 oder band2 ist zu Ende // Rest kopieren: while (!band1.eof()) { band3.write(puffer1); band1.write(puffer1); } while (!band2.eof()) { band3.write(puffer2); band2.write(puffer2); } }
Noch besser ist es aber, die Methode mischen mit Hilfe der schon im Kapitel 8.3.8 auf Seite 189 eingeführten Multibehälter lehrbuch.kapitel8.SeqDatei vorzustellen.
In der dritten Zeile des Programms fehlt der Index:
for (int i = 0; i < gedaechtnis.length; i++) gedaechtnis[i] = 0; // vorbesetzen
und nicht wie im Buch
for (int i = 0; i < gedaechtnis.length; i++) gedaechtnis = 0; // vorbesetzen
In der ersten Zeile des Konstruktors ShellSort müssen Kommentarzeichen hinzugefügt werden.
Es heißt also richtig
public ShellSort(Element[] daten, int[] k) { // Schrittweiten in k
und nicht wie im Buch
public ShellSort(Element[] daten, int[] k) { Schrittweiten in k
In der 7. Zeile von unten soll nicht die Methode loesch, sondern die Methode loeschen (rekursiv) aufgerufen werden:
astGekuerzt = knoten.rechts.loeschen(kleinster.knoten.wert);
und nicht wie im Buch
astGekuerzt = knoten.rechts.loesch(kleinster.knoten.wert);
In der 10. Zeile der Methode loeschen soll die geschweifte Klammer gestrichen werden:
else if (knoten.zaehler > 1) // element.gleich(knoten.wert) // element gefunden
und nicht wie im Buch
else if (knoten.zaehler > 1) { // element.gleich(knoten.wert) // element gefunden
In der letzten Zeile des Programms soll void auf boolean ausgetauscht werden:
private boolean rechtsAusgleichen() { ... } // symmetrisch
und nicht wie im Buch
private void rechtsAusgleichen() { ... } // symmetrisch
In der zweiten Zeile des zweiten Programmabschnitt auf der Seite soll werkzeugkiste auf getToolkit() ausgetauscht werden:
try { Image meinBild = getToolkit().getImage( new URL("file:/laufwerk:/[Pfad]/balloons.gif")); grafik.drawImage(meinBild, 5,40, this); // y groß genug wählen, sonst unsichtbar } catch (MalformedURLException e) { System.err.println(e); }
und nicht wie im Buch
try { Image meinBild = werkzeugkiste.getImage( new URL("file:/laufwerk:/[Pfad]/balloons.gif")); grafik.drawImage(meinBild, 5,40, this); // y groß genug wählen, sonst unsichtbar } catch (MalformedURLException e) { System.err.println(e); }
© APSIS GmbH , Polling, 2000