Lernpfad:Einführung in Git/8
In Gitea findest du ein Projekt mit dem Namen "oop2". Erstelle dir einen Fork und klone das Repository.
Systematische Fehlersuche
Bei der Suche nach Fehlern in deinem Programmcode gibt es verschiedene Vorgehensweisen. Wichtig ist es, dabei systematisch vorzugehen und nicht einfach nur "Trial and Error" - also "Versuch und Irrtum" - anzuwenden.
Die Fehlersuche ist besonders schwierig, wenn das Programm kompiliert und startet - also syntaktisch korrekt ist, aber nicht die gewünschten Ergebnisse liefert - also einen semantischen Fehler enthält.
Überleg dir erst einen Plan, wie du vorgehen möchtest. Dazu musst du Vermutungen anstellen, wo im Programm der Fehler liegen könnte.
- Öffne die Klasse
Calculator
und analysiere ihren Quelltext. - Suche die Methode
int addEvenNumbers(int)
und lies ihre Beschreibung im Methoden-Kommentar. Die Methode enthält zwei Fehler. Probiere sie aus. (Nicht wundern, wenn das Programm nicht mehr reagiert. Lies unten weiter.)
Die Methode bleibt in einer Endlosschleife hängen. Du kannst sie mit einem Klick auf den Pfeil unten rechts beenden.
Den Debugger benutzen
Für die systematische Fehlersuche steht dir ein mächtiges Werkzeug zur Verfügung: Der Debugger. Mit ihm kannst du das Programm zu beliebigen Zeitpunkten anhalten und dir seinen Zustand - also die Werte der Variablen - anzeigen lassen.
- Suche Zeile 18 und klicke einmal links auf die Zeilennummer. Ein rotes Stoppschild erscheint.
- Starte die Methode erneut und beobachte, was passiert. Analysiere das Debugger-Fenster und seine Funktion.
- Probiere die Buttons am unteren Rand des Debugger-Fensters aus. Behalte dabei auch den Editor mit dem Programmcode im Auge. Notiere dir Stichpunkte zu deinen Vermutungen, wie der Debugger funktioniert.
- Versuche die Endlosschleife zu beheben und die Methode zu korrigieren. Du kannst die Korrektheit mit der entsprechenden Testmethode prüfen.
Das Stoppschild visualisiert einen Breakpoint. Also einen Unterbrechungspunkt, an dem der Debugger das Programm anhalten soll. Du kannst beliebig viele Breakpoints setzen. Durch einen erneuten Klick auf das Schild kannst du den Breakpoint wieder löschen.
public int addEvenNumbers( int pUpperBound ) {
int sum = 0, i = 1;
while( i <= pUpperBound ) {
// Nur gerade Zahlen addieren
if( i%2 == 0 ) {
sum += i;
}
i++;
}
return sum;
}
Benutze bei den Aufgaben jeweils den Debugger zur Fehlersuche, die Testmethoden zur Überprüfung und committe deine Änderungen.
- Suche den Fehler in der Methode
int ggT(int, int)
und korrigiere ihn. - Implementiere die Methode
int kgV(int, int)
nach der Vorgabe.
/**
* Ein einfacher Rechner.
*/
public class Calculator {
/**
* Bildet die Summe aller gerader Zahlen, die kleiner oder gleich
* <var>pUpperBound</var> sind. Die Eingabe <code>addEvenNumbers(4)</code>
* ergibt also <code>2 + 4 = 6</code>.
*
* TODO: Benutze den Debugger, um die beiden Fehler in der Methode zu finden.
*
* @param pUpperBound Obere Grenze der Summe
* @return
*/
public int addEvenNumbers( int pUpperBound ) {
int sum = 0, i = 1;
while( i <= pUpperBound ) {
// Nur gerade Zahlen addieren
if( i%2 == 0 ) {
sum += i;
}
i++;
}
return sum;
}
/**
* Wendet den euklidischen Algorithmus zur Suche des größten gemeinsamen
* Teilers bei zwei positiven ganzen Zahlen an.
*
* TODO: Benutze den Debugger, um den Fehler in der Methode zu finden.
*
* @link https://de.wikipedia.org/wiki/Euklidischer_Algorithmus
* @param pNumberA
* @param pNumberB
* @return
*/
public int ggT( int pNumberA, int pNumberB ) {
if( pNumberA < 0 || pNumberB < 0 ) {
return 0;
} else if( pNumberA == 0 ) {
return pNumberB;
} else {
while( pNumberB > 0 ) {
if( pNumberA > pNumberB ) {
pNumberA -= pNumberB;
} else {
pNumberB -= pNumberA;
}
}
return pNumberA;
}
}
/**
* Berechnet das kleinste gemeinsame Vielfache zweier positiver Ganzzahlen.
* @link https://de.wikipedia.org/wiki/Kleinstes_gemeinsames_Vielfaches#Berechnung_über_den_größten_gemeinsamen_Teiler_(ggT)
* @param pNumberA
* @param pNumberB
* @return
*/
public int kgV( int pNumberA, int pNumberB ) {
if( pNumberA < 0 || pNumberB < 0 ) {
return 0;
} else {
return (int) (pNumberA / this.ggT(pNumberA, pNumberB) * pNumberB);
}
}
}