Ricorsione e Debug Fattoriale function fatt (n: integer): integer; begin if n=0 then fatt:=1 else fatt:= n* fatt (n-1); end; Begin readln(numero); writeln(’Il fattoriale e’’ ’, fatt(numero); Readln; End; Fattoriale di n=4 numero n Fatt(4) 4 4 4*fatt(3) function fatt (n: integer): integer; begin if n=0 then fatt:=1 else fatt:= n* fatt (n-1); end; Fatt(3) Fatt(2) Fatt(1) 3*fatt(2) 2*fatt(1) 1*fatt(0)=1 2*1=2 3*2=6 4*6=24 Risultato: 24 Esercizio Scrivere una funzione che data una stringa, restituisca la stringa invertita. Se x= abraca L’output è acarba Esercizio Scrivere una funzione che data una stringa, restituisca la stringa invertita. var n:integer; P:string; //Variabile globale function inverti(parola:string):string; var V:char; begin if length(parola)=1 then inverti:=parola else begin V:=parola[1]; delete(parola,1,1); inverti:=inverti(parola) + V; end; end; begin writeln('inserisci la parola'); readln(P); n:=length(p); writeln('La parola invertita e'' ', inverti(P)); readln; end. inverti(‘a’) Program stringaInversa; var P:string; function inverti(parola:string):string; var V:char; begin if length(parola)=1 then inverti:=parola else begin V:=parola[1]; delete(parola,1,1); inverti:=inverti(parola) + V; end; end; begin writeln('inserisci la parola'); readln(P); writeln('La parola invertita e'' ', inverti(P) ); readln; end. La parola invertita e’ acarba inverti:= ‘a’ inverti(‘ca’) v=‘c’ v=‘c’ parola=‘a’ inverti:=‘a’ + ‘c’ = ‘ac’‘c’ inverti:=inverti(‘a’)+ inverti(‘aca’) v=‘a’ parola=‘ca’ inverti:= ‘ac’ + ‘a’=‘aca’ inverti:=inverti(‘ca’)+ ‘a’ inverti(‘raca’) v=‘r’ parola=‘aca’ inverti:=‘aca’+ ‘r’=‘acar’ inverti:=inverti(‘aca’)+ ‘r’ inverti(‘braca’) v=‘b’ parola=‘raca’ inverti:=‘acar’ + ‘b’ = ‘acarb’ inverti:=inverti(‘raca’)+ ‘b’ inverti(‘abraca’) v=‘a’ parola=‘braca’ inverti:=‘acarb’ +’a’ = acarba inverti:=inverti(‘braca’)+ ’a’ stringaInversa P =‘abraca’ inverti(P) = acarba Che succede? var P:string; function inverti(parola:string;):string; var V:char; begin if length(parola) then inverti:=parola else begin V:=parola[1]; delete(parola,1,1); inverti:= v + inverti(parola); end; end; begin writeln('inserisci la parola'); readln(P); writeln('La parola invertita e'' ', inverti(P) ); readln; end. Debug Il debugger integrato dà al programmatore il controllo sull’esecuzione del codice. Utile soprattutto quando ci sono errori logici non facili da individuare. Durante il debug, una barra di esecuzione evidenzia la successiva istruzione del codice da eseguire. • Go TO CURSOR (F4): permette di interrompere momentaneamente il programma nel punto specificato dal cursore. • BREAKPOINT: punto prefissato in una riga del codice sorgente che interrompe momentaneamente l’esecuzione. I breakpoint vanno prefissati e rimangono finchè non vengono rimossi, mentre il Go to Cursor dipende dalla posizione corrente del cursore. Il breakpoint (o il cursore) deve essere posizionato su righe contenenti un’istruzione eseguibile, quindi non su righe vuote, righe di commento, direttive del compilatore, dichiarazioni dei dati o altre parti non eseguibili dal programma. Esecuzione passo per passo • TRACE INTO (F7): consente di eseguire un’istruzione alla volta. In particolare esegue quella evidenziata dalla barra di esecuzione, sposta la barra sull’istruzione successiva e restituisce il controllo al programmatore. Se la riga su cui si trova la barra è una procedura o una funzione, Trace into salta a quella parte del programma continuandone l’esecuzione passo per passo. • STEP OVER (F8): attiva l’esecuzione del programma una riga alla volta, ma a differenza di Trace Into tralascia le chiamate alle procedure e alle funzioni. In pratica esegue la procedura o la funzione in una singola istruzione (come se fosse una semplice istruzione), sposta la barra di esecuzione nell’istruzione successiva e restituisce il controllo al programmatore. Controllare variabili e stack • WATCH: è un riquadro che consente di controllare il contenuto di una o più variabili scelte dal programmatore. Può visualizzare solo il contenuto delle variabili dove esse sono visibili (regole di visibilità). • LOCAL VARIABLES: è un riquadro che contiene tutte e sole le variabili locali della procedura o funzione in cui si trova la barra dell’esecuzione. • CALL STACK: è un riquadro che permette di controllare il percorso effettuato dal programma fino al punto in esame. E’ un elenco in ordine discendente di tutte le precedenti chiamate alle procedure o alle funzioni. Debug - Esempi • • • • • • Procedura (Procedura annidata) Funzione (ParametriEglobale) Funzione (EC) Vettori e Record (elenco) Procedura ricorsiva (TrovaPosizioneMinimo) Funzione ricorsiva (stringaInversa) program EC; {$APPTYPE CONSOLE} uses SysUtils; var b, ris: integer; Function doppio(Var a: integer): integer; begin a:=2*a; doppio:=a; end; begin b:=3; ris:=2* doppio (b); writeln('Primo risultato: ', ris); Cosa stampa? writeln; b:=3; ris:= doppio (b) + doppio (b); writeln ('Secondo risultato: ', ris); readln; end. Cosa stampa? Primo risultato: ris:=2*doppio (B) B3 A B 6 A B3 Function doppio (Var a: integer): integer; begin a:=2*a; doppio:=a; end; La funzione doppio(b) = 2 ris = 2 * 6 = 12 Quindi writeln('Primo risultato: ', ris); stampa Primo risultato: 12 Secondo risultato: ris:=doppio(B)+doppio(B) B 3 A B 3 A B 6 La funzione doppio(B) = 6 B6 A B 6 La funzione doppio(B) = 12 Function doppio (Var a: integer): integer; begin a:=2*a; doppio:=a; end; Ris = 6 + doppio(B) A B 12 Risultato = 6 + 12 = 18