lunedì 16 giugno 2014

Programmazione Capitolo 6, Parte 3

Usare un debugger
§ Un debugger è un programma che potete usare per eseguire un altro
programma e analizzare il suo comportamento durante l’esecuzione.
§ Potete interrompere e far proseguire il vostro programma, vedere il contenuto
delle variabili quando arrestate temporaneamente l’esecuzione, scegliere
quanti passi di programma eseguire prima dell’interruzione successiva.
§ Più grandi sono i vostri programmi, più difficile sarà correggerli inserendo
semplicemente enunciati di stampa.
§ I debugger possono far parte di ambienti di sviluppo integrato (es. BlueJ,
Eclipse) o essere programmi a se stanti (es. Jswat).
§ Tre concetti chiave:
§ punti di arresto (breakpoints)
§ esecuzione del programma una riga alla volta (single-stepping)
§ ispezione del valore di singole variabili (inspecting variables)

Il debugger fermo a un punto di arresto
                                                 

Il debugger fermo a un punto di arresto

Ispezionare variabili
Ispezionare variabili
Debugging
§ L’esecuzione viene sospesa al raggiungimento del breakpoint
§ Quando fate partire il debugger, il programma viene eseguito a piena
velocità fino al raggiungimento di un punto di arresto
§ Quando il programma si è fermato è possibile:
§ Ispezionare le variabili
§ Eseguire il programma una riga alla volta
§ Oppure continuare l’esecuzione del programma a velocità piena fino al
raggiungimento del breakpoint successivo
§ Quando il programma termina, termina anche l’esecuzione del debugger
§ I punti di arresto rimangono attivi finché non vengono esplicitamente
rimossi
§ Due tipi di comando single-step:
§ step into (fai un passo all’interno)
§ step over (fai un passo scavalcando)



Attività di debugging
§ Riprodurre l'errore
§ Semplificare l'errore
§ Divide and conquer / Top-down
§ Sapere cosa dovrebbe fare il programma / metodo
§ Controllare tutti i dettagli
§ Capire bene l'errore prima di correggerlo


Esempio di single step
Linea attuale:

String input = in.next();
Word w = new Word(input);
int syllables = w.countSyllables();
System.out.println("Syllables in " + input + ": " +
syllables);

Quando eseguite un comando di tipo step over, procedete fino alla riga
successiva:
String input = in.next();
Word w = new Word(input);
int syllables = w.countSyllables();
System.out.println("Syllables in " + input + ": " +
syllables);

Esempio di single step

Tuttavia se eseguite un comando di tipo step into vi trovate nella prima
linea del metodo countSyllables:
public int countSyllables()
{
int count = 0;
int end = text.length() - 1;
. . .
}

Un esempio di sessione di debugging
§ La classe word ha il compito di contare le sillabe in una parola
§ Ogni gruppo di vocali adiacenti (a, e, i, o, u, y) fa parte di una sillaba
§ Tuttavia, una “e” alla fine di una parola non forma una sillaba
§ Ogni parola ha almeno una sillaba anche se le regole precedenti
forniscono un conteggio nullo
§ Eventuali caratteri all’inizio o alla fine della stringa che non siano
lettere vengono eliminati.

File Word.java
01: /**
02: Classe che descrive una parola in un documento.
03: */
04: public class Word
05: {
06: /**
07: Costruisce una parola eliminando caratteri iniziali e
08: finali che non siano lettere, come i segni di punteggiatura.
09: @param s la stringa da analizzare
10: */
11: public Word(String s)
12: {
13: int i = 0;
14: while (i < s.length() && !Character.isLetter(s.charAt(i)))
15: i++;
16: int j = s.length() - 1;
17: while (j > i && !Character.isLetter(s.charAt(j)))
18: j--;
19: text = s.substring(i, j);
20: }
21:
22: /**
23: Restituisce il testo della parola dopo aver rimosso
24: caratteri iniziali e finali che non siano lettere.
25: @return il testo della parola
26: */
27: public String getText()
28: {
29: return text;
30: }
31:
32: /**
33: Conta le sillabe presenti nella parola.
34: @return il numero di sillabe
35: */
36: public int countSyllables()
37: {
38: int count = 0;
39: int end = text.length() - 1;
40: if (end < 0) return 0; // La stringa vuota non ha sillabe
41:
42: // Una e alla fine della parola non conta come vocale
43: char ch = Character.toLowerCase(text.charAt(end));
44: if (ch == 'e') end--;
46: boolean insideVowelGroup = false;
47: for (int i = 0; i <= end; i++)
48: {
49: ch = Character.toLowerCase(text.charAt(i));
50: String vowels = "aeiouy";
51: if (vowels.indexOf(ch) >= 0)
52: {
53: // ch è una vocale
54: if (!insideVowelGroup)
55: {
56: // inizia un nuovo gruppo di vocali
57: count++;
58: insideVowelGroup = true;
59: }
60: }
61: }
62:
63: // Ogni parola ha almeno una sillaba
64: if (count == 0)
65: count = 1;
66:
67: return count;
68: }
69:
70: private String text;
71: }

File SyllableCounter.java
01: import java.util.Scanner;
02:
03: /**
04: Questo programma conta le sillabe di tutte le parole di una frase.
05: */
06: public class SyllableCounter
07: {
08: public static void main(String[] args)
09: {
10: Scanner in = new Scanner(System.in);
11:
12: System.out.println("Enter a sentence ending in a period.");
13:
14: String input;
15: do
16: {
17: input = in.next();
18: Word w = new Word(input);
19: int syllables = w.countSyllables();
20: System.out.println("Syllables in " + input + ": "
21: + syllables);
22: }
23: while (!input.endsWith("."));
24: }
25: }







Il programma di debug                   
§ Fornendo questi dati in ingresso: "hello yellow peach. " viene
visualizzato quanto segue (che non è molto promettente):
Syllables in hello: 1
Syllables in yellow: 1
Syllables in peach.: 1
§ Impostare un punto di arresto nella prima linea del metodo del
countSyllables della classe word
§ Fate partire il programma che chiederà i dati in ingresso, ricevuti i quali
si arresterà al breakpoint impostato
§ Il metodo controlla l’ultimo carattere della parola per vedere se è una
“e”



Il programma di debug
Collaudare il metodo countSyllables con il debugger

§ Vediamo se questo funziona correttamente: eseguite il programma fino
alla linea in cui viene fatto il controllo. Ora ispezionate la variabile ch.
§ Potete verificare che ch contiene il valore “l”


Collaudare il costruttore di word con il
debugger
§ Fornire di nuovo i dati in ingresso
§ Impostare un breakpoint dopo la fine del secondo ciclo
§ Ispezionare i valori i e j
§ i vale 0 e j vale 4. Ciò ha senso perché non ci sono segni di
punteggiatura da ignorare
§ Perché text viene impostato a “hell”?
§ Tipico errore “per scarto di uno”: il metodo substring considera le
posizioni fino al secondo parametro senza includerlo
text = substring(i, j);
dovrebbe essere:
text = s.substring(i, j + 1);


Collaudare il costruttore di word con il
Debugger

Collaudare il costruttore di Word con il debugger

Un altro errore
§ Correggete questo errore
§ Compilate nuovamente il programma
§ Provate di nuovo i tre casi di prova
Syllables in hello: 1
Syllables in yellow: 1
Syllables in peach.: 1
§ C’è ancora un problema
§ Eliminate tutti i punti di arresto e impostate un nuovo breakpoint
nel metodo countSyllables
§ Fornite in ingresso la stringa “hello”

Collaudare di nuovo con il debugger
countSyllables
§ Iniziate a eseguire il programma passo dopo passo, in modalità single
step, all’interno del metodo
boolean insideVowelGroup = false;
for (int i = 0; i <= end; i++)
{
ch = Character.toLowerCase(text.charAt(i));
if ("aeiouy".indexOf(ch) >= 0)
{
// ch è una vocale
if (!insideVowelGroup)
{
// Inizia un nuovo gruppo di vocali
count++;
insideVowelGroup = true;
}
}
}
Collaudare di nuovo con il debugger
countSyllables
§ Nella prima iterazione del ciclo, il debugger non esegue l’enunciato if.
Ciò è corretto perché la prima lettera “h” non è una vocale.
§ Nella seconda iterazione il debugger entra nell’enunciato if come
dovrebbe perché la seconda lettera “e” è una vocale. La variabile count
viene incrementata.
§ Nella terza iterazione l’enunciato if viene ignorato nuovamente perché
la lettera “l” non è una vocale.
§ Nella quinta interazione succede qualcosa di strano: la lettera “o” è una
vocale e l’enunciato if viene eseguito, ma il secondo enunciato if viene
ignorato e la variabile count non viene nuovamente incrementata.

Correggere l’errore
§ La lettura di una consonante dovrebbe riportare insideVowelGroup al
valore false
§ Per correggerlo:
if ("aeiouy".indexOf(ch) >= 0)
{
. . .
}
else insideVowelGroup = false;
§ Ora compilate nuovamente ed eseguite di nuovo il collaudo, ottenendo:
Syllables in hello: 2
Syllables in yellow: 2
Syllables in peach.: 1
§ Il debugger è ora privo di errori? Questa non è una domanda alla quale il
debugger possa rispondere.




Nessun commento:

Posta un commento