Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[ Long ] Turbo Pascal & Eccezzioni

2 views
Skip to first unread message

Il Razziatore

unread,
Mar 8, 2008, 6:38:31 PM3/8/08
to
Salve a tutti,
Come tutti sapete il Turbo Pascal non supporta le eccezioni ( se si
esclude gli interrupt tipo il DIV BY ZERO e i controlli sullo stack o
simili ). Ma questo vuol dire che non è possibile mettere su un
meccanismo simile alle eccezioni? Assolutamente no. Le eccezioni sono
fondalmentemente una cosa molto semplice. Sono una trappola scritta dal
programmatore dove viene incanalato il flusso del programma in caso di
un determinato errore. Il delphi mette a disposizione due strutture:


try
...
except
...
end;

che fa appunto questo prova ad eseguire del codice potenzialmente
periocoloso ( dento il blocco try-except ) e se malaguratamente succede
qualcosa salta il resto del codice e va dentro a except e cattura
l'eccezione eseguendo un codice appropriato ( ad esempio visualizando un
messaggio all'utente ). Esiste, come abbiamo detto, un altra struttura:

try
...
finaly
...
end;

che funziona sostazialmente nello stesso modo, solo che le eccezioni non
vengono catturate ma viene comunque eseguito un codice ( quello
contenuto in finaly-end ) utile quando bisogna deallocare memoria o cose
del genere ( chiudere file che altrimenti rimarrebbero aperti ecc ).

Questa la teoria... e in turbo pascal come si puo' fare? Il pascal non
ci da gli strumenti per farlo in modo nativo, ma possiamo benissimo
impleementarlo a manina.

definiamo una classe TExcpetion in questo modo:

PException = ^TException;
TException = object
private
FMsg : String; (** Messaggio d'errore. *)
public
constructor Create( Msg_ : String );
function ClassName : String; virtual;
function IsClass( Name : String ) : Boolean; virtual;
function Msg : String;
end;


constructor TException.Create( Msg_ : String );
begin
FMsg := Msg_;
end;

function TException.ClassName : String;
begin
ClassName := 'TException';
end;

function TException.IsClass( Name : String ) : Boolean;
begin
IsClass := Name = 'TException';
end;

function TException.Msg : String;
begin
Msg := FMsg;
end;

tutte le nostre eccezzioni saranno figlie di questa. L'unica cosa che
dobbiamo fare per creare una nuova eccezione e ridefinire le due
funzioni ClassName e IsClass come in questo esempio:

PIllegalStateException = ^TIllegalStateException;
TIllegalStateException = object( TException )
function ClassName : String; virtual;
function IsClass( Name : String ) : Boolean; virtual;
end;

function TIllegalStateException.ClassName : String;
begin
ClassName := 'TIllegalStateException';
end;

function TIllegalStateException.IsClass( Name : String ) : Boolean;
begin
IsClass := ( Name = 'TIllegalStateException' ) or inherited isClass(
Name );
end;

da notare il inherited isClass( Name ) questo pezzo di codice è
fondamentale a un corretto funzionamento di tutto il sistema. L'unica
cosa che manca è una varibile dove memorizare l'eccezzione

var
LastException : PException;


Ora abbiamo tutti gli strumenti per crearci in casa le nostre eccezzioni
:) infatti tutto il codice che ho qui illustrato non è altro che il
codice che Delphi crea da solo quando facciamo qualcosa del tipo

Type TIllegalStateException = object( TException );

molto più comodo sicuramente ma che volete farci :) una volta che i
preparativi sono fatti ( si possono tranquillamente mettere dentro una
unit e riutilizare tutte le volte che volte ) passiamo all'atto pratico:
Lanciare e catturare un eccezione.

mettiamo il caso che vogliamo tradurre questo codice:


function allergicopari( N : Integer ) : Integer;
begin
if N Div 2 = 0 then reise TExcpetion.Create;
allergicopari := N;
end;

var X : Integer;

begin
try
X := 0;
X := AllergicoPari( X + 1 );
X := AllergicoPari( X + 1 );
X := AllergicoPari( X + 1 );
X := AllergicoPari( X + 1 );
except
on E : Exception do WriteLn( 'Doh!' );
end;
end;


questo è un semplice codice che alla seconda volta che viene chiamata la
funzione AllercioPari con il valore 2 lancera l'evocazione bloccando
il programma. In pascal questo codice può essere tradotto come


function allergicopari( N : Integer ) : Integer;
var E : PExcpetion;
begin
if N Div 2 = 0 then begin
New( E, Create );
LastExcpetion := E;
Exit;
end;
allergicopari := N;
end;


Infatti la procedura Exit non farà altro che uscire dal corrente blocco
proprio come un eccezzione. La prate più difficile è stata fatta, ora
viene la prate "noiosa" per incanalare l'eccezione dove vogliamo noi
dobbiamo usare le etichette ( label ) e l'istruzione goto. Ma sopratutto
dobbiamo evitare l'esecuzione del restate codice in presenza di
eccezione. Anche questo viene fatto per noi dal Delphi. Quindi per prima
cosa prepariamo 2 etichette "Except" che verra chiamata in caso di
eccezione e Skip in caso che non ci sia eccezione. Ovviamente nel caso
di un blocco Try-Finaly-End l'etichetta Skip non serve.


var X : Integer;

label
excpet, skip;

begin
{ try }
X := 0;

X := AllergicoPari( X + 1 );
if LastException <> nil then goto except;

X := AllergicoPari( X + 1 );
if LastException <> nil then goto except;

X := AllergicoPari( X + 1 );
if LastException <> nil then goto except;

X := AllergicoPari( X + 1 );
if LastException <> nil then goto except;

goto skip;
except:
if LastExcpet^.IsClass( 'TException' ) then begin
WriteLn( 'Doh!' );
LastException := Nil;
end;
skip:
{ end; }
end;

L'istruzione LastException := Nil; serve ad evitare la propagazione non
necessaria ( visto che è stata catturata ) della eccezione. La stesura
dei programmi, ovviamente diventa un po' più lunga ma questo non vuol
dire che bisogna rinunciare alle eccezioni solo perché all'epoca non
c'erano :)

Rento noto che sul CVS del PCF è disponibile una unit aggiornata per le
eccezioni ( da cui sono tratti questi esempi ). Continene sia le classi
che la varibile quindi basta fare riferimento a quelle.

http://razziatore.no-ip.com/PCF/Current/EXCEPTIO.PAS

Buon divertimento :)

--
Il Razziatore,
"Lo sviluppo di una nazione si misura anche dallo stato della sua rete
ferroviaria". Camillo Benso Conte di Cavour
"Per tutto quanto non previsto nel presente regolamento il capostazione
deve usare senno e ponderatezza." Regolamento d'esercizio FS
-----------------------------------------------
MSN : IlRazz...@netscape.net
ICQ : 67552596
Yhaoo : Razziatore82
-----------------------------------------------
Founder of MediaPlayer Project
http://mpp.iwebland.com

0 new messages