* * * *
15 Visitatori, 0 Utenti

22 Ott 2011 - Procedure e funzioni

Fino ad ora tutto il codice che abbiamo scritto era in un blocco solo, ovvero abbiamo scritto tutte le righe una dietro l'altra, ma solo perché gli esempi visti erano semplici, ma capita e anche sovente di dover scrivere pezzi di codice che serve riutilizzare. Le motivazioni possono essere molteplici, ma sovente conviene utilizzare le procedure e le funzioni piuttosto che scrivere un monoblocco di codice. Ipotizziamo di dover invertire il valore di due variabili di nome Valore1 e Valore2 e di dover effettuare questa operazione sovente all'interno del nostro programma, per poter fare questa operazione abbiamo bisogno anche della variabile di nome Valore3. Vediamo ora come andrebbe scritto il codice che effettua l'inversione dei valori:

Valore3:=Valore1;

Valore1:=Valore2;

Valore2:=Valore3;

Bene ora immaginiamo di doverlo scrivere 10, 100, 1000 volte all'interno del codice, possiamo facilmente capire che il codice in questione diverrà molto lungo, quindi difficile da gestire in un secondo momento, e in più il programma diverrebbe molto grosso senza tenere conto che la variabile di nome Valore3 rimarrebbe allocata in memoria per tutta l'esecuzione del programma. Mentre ora immaginiamo di immettere questo codice scritto in una procedura, le migliorie sono diverse, ad esempio quando la procedura ha finito la sua vita la variabile Valore3 viene deallocata, il programma occupa meno spazio e se bisogna fare manutenzione il codice diventa più leggibile.

Bene fino ad ora abbiamo parlato di procedure e funzioni come se fossero la stessa cosa, ma fondamentalmente c'è una differenza tra le due cose, ovvero che le funzioni restituiscono un valore, mentre le procedure no. Vediamo ora come si dichiara una procedura e come si dichiara una funzione. Procedura:

procedure NomeProcedura();

begin

.

.

.

end;

Funzione:

function NomeFunzione(): tiporestituito;

begin

.

.

NomeFunzione:=valorerestituito;

end;

La prima cosa che bisogna notare è che sia le funzioni che le procedure hanno un nome che le contraddistingue, per seconda cosa bisogna notare che entrambe terminano con le parentesi e con il punto e virgola. Ma le due cose più importanti da notare sono che la funzione per restituire un valore deve specificare di che tipo è, e per effettuare la restituzione bisogna attribuire il valore da restituire al nome della funzione stessa.

Un altra cosa da apprendere quando si tratta l'argomento procedure e funzioni è il passaggio di parametri. Per passaggio di parametri si intende il passare delle informazioni alla procedura o alla funzione. Vediamo un esempio concreto:

procedure StampaParametrizzato(valore1:integer; valore2:integer; valore3:integer);

begin

if (Valore1<=5) then

writeln(valore2)

else

writeln(valore3);

end;

Bene come si può notare, all'interno delle parentesi tonde subito dopo il nome della procedura, è presente la dichiarazione di tre variabili intervallate da dei punti e virgola. In questo modo definisco quanti parametri passare alla funzione/procedura specificando il tipo del dato che gli passo.

I parametri possono essere passati in due modi, per valore o per referenza. La differenza tra le due è che se sono passati per valore, il valore stesso non può essere modificato all'esterno della procedura, se invece il parametro è passato per referenza allora il valore se viene modificato verrà modificato sempre nel programma. In pratica i due tipi si differenziano grazie alla parola riservata var all'interno delle parentesi tonde. Vediamo un esempio di passaggio di parametri per valore:

procedure Inverti( Valore1: integer; Valore2: integer);

e ora lo stesso ma per referenza:

procedure Inverti(var Valore1: integer; var Valore2: integer);

Ora per capire bene cosa si intende con passaggio di parametri per valore andate a compilare e ad eseguire il seguente sorgente:


program project2;


{$mode objfpc}{$H+}


uses

{$IFDEF UNIX}{$IFDEF UseCThreads}

cthreads,

{$ENDIF}{$ENDIF}

Classes, SysUtils, CustApp

{ you can add units after this };


type


{ TMyApplication }


TMyApplication = class(TCustomApplication)

protected

procedure DoRun; override;

public

constructor Create(TheOwner: TComponent); override;

destructor Destroy; override;

procedure WriteHelp; virtual;

end;


procedure Inverti(Valore1: integer; Valore2: integer);

var

appoggio: integer;

begin

appoggio:=Valore1;

Valore1:=Valore2;

Valore2:=appoggio;

writeln('All''interno della procedura valore1 vale: ', valore1,' e valore2 vale: ', valore2);

end;


{ TMyApplication }


procedure TMyApplication.DoRun;

var

ErrorMsg: String;

valore1: integer;

valore2: integer;

begin

// quick check parameters

ErrorMsg:=CheckOptions('h','help');

if ErrorMsg<>'' then begin

ShowException(Exception.Create(ErrorMsg));

Terminate;

Exit;

end;


// parse parameters

if HasOption('h','help') then begin

WriteHelp;

Terminate;

Exit;

end;


{ add your program here }

valore1:=5;

valore2:=7;

Inverti(valore1,valore2);

writeln('Dopo l''esecuzione della procedura valore1 vale: ', valore1,' e valore2 vale: ', valore2);

// stop program loop

Terminate;

end;


constructor TMyApplication.Create(TheOwner: TComponent);

begin

inherited Create(TheOwner);

StopOnException:=True;

end;


destructor TMyApplication.Destroy;

begin

inherited Destroy;

end;


procedure TMyApplication.WriteHelp;

begin

{ add your help code here }

writeln('Usage: ',ExeName,' -h');

end;


var

Application: TMyApplication;


{$IFDEF WINDOWS}{$R project2.rc}{$ENDIF}


begin

Application:=TMyApplication.Create(nil);

Application.Title:='My Application';

Application.Run;

Application.Free;

end.


Per capire come funziona il passaggio per referenza basta sostituire la riga:

procedure Inverti(Valore1: integer; Valore2: integer);

con la riga:

procedure Inverti(var Valore1: integer; var Valore2: integer);

e ricompilare. Una volta eseguite entrambe le versioni è evidente la differenza tra le due.


N.B.: se per caso si immettesse la riga procedure Inverti(Valore1: integer; var Valore2: integer); allora Valore1 sarebbe passato per valore e Valore2 per referenza.


Share on Twitter! Digg this story! Del.icio.us Share on Facebook! Technorati Reddit StumbleUpon

Articles in « PROGRAMMATORE ALZATI E CAMMINA CON LAZARUS »

Comments *

Commenting option has been turned off for this article.

Recenti

How To

Trascinare un file nel programma da xinyiman
DB concetti fondamentali e ZeosLib da xinyiman
Recuperare codice HTML da pagina web da xinyiman
Mandare mail con Lazarus da xinyiman
Stabilire il sistema operativo da xinyiman
Esempio lista in pascal da xinyiman
File INI da xinyiman
Codice di attivazione da xinyiman
Realizzare programmi multilingua da xinyiman
Lavorare con le directory da xinyiman
Utilizzare Unità esterne da Loryea
TTreeView da xinyiman
TTreeview e Menu da xinyiman
Generare controlli RUN-TIME da xinyiman
LazReport, PDF ed immagini da xinyiman
Intercettare tasti premuti da xinyiman
Ampliare Lazarus da xinyiman
Lazarus e la crittografia da xinyiman
System Tray con Lazarus da xinyiman
UIB: Unified Interbase da Microges2000
Il file: questo sconosciuto da Microges2000
Conferma di chiusura di un applicazione da xinyiman
Liste e puntatori da Microges2000
Overload di funzioni da Microges2000
Funzioni a parametri variabili da Microges2000
Proprietà da Microges2000
Conversione numerica da Microges2000
TImage su Form e Panel da Maverich
Indy gestiore server FTP lato Client da Maverich
PopUpMenu sotto Pulsante (TSpeedButton) da Maverich
Direttiva $macro da Microges2000
Toolbar da xinyiman
Evidenziare voci TreeView da Maverich
Visualizzare un file Html esterno da Maverich
StatusBar - aggirare l'errore variabile duplicata da Maverich
Da DataSource a Excel da xinyiman
Le permutazioni da xinyiman
Brute force da xinyiman
Indy 10 - Invio email con allegati da Maverich
La gestione degli errori in Lazarus da xinyiman
Pascal Script da xinyiman
Linux + Zeos + Firebird da xinyiman
Dataset virtuale da xinyiman
Overload di operatori da Microges2000
Lavorare con file in formato JSON con Lazarus da nomorelogic
Zeos ... dietro le quinte (prima parte) da Stilgar
Disporre le finestre in un blocco unico (come Delphi) da Maverich
Aspetto retrò (Cmd Line) da xinyiman
Come interfacciare periferica twain da Narciso
Ubuntu - aggiornare free pascal e lazarus da xinyiman
fpcup: installazioni parallele di lazarus e fpc da nomorelogic
Free Pascal e Lazarus sul Raspberry Pi da nomorelogic
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal. da nomorelogic
Creare un server multithread da xinyiman
guida all'installazione di fpc trunk da subversion in linux gentoo da nomorelogic
Indice da nomorelogic
DB concetti fondamentali e connessioni standard da xinyiman
Advanced Record Syntax da nomorelogic
DB concetti fondamentali e DBGrid da xinyiman
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText da xinyiman
Advanced Record Syntax: un esempio pratico da nomorelogic
Superclasse form base per programmi gestionali (e non) da nomorelogic
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox da nomorelogic
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form da nomorelogic
Superclasse form base per programmi gestionali (e non) #4 - wait animation da nomorelogic
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog da nomorelogic
Installare lazarus su mac osx sierra da xinyiman
Utenti
  • Utenti in totale: 549
  • Latest: suh
Stats
  • Post in totale: 11010
  • Topic in totale: 1366
  • Online Today: 27
  • Online Ever: 74
  • (Luglio 09, 2012, 11:05:53 am)
Utenti Online
Users: 0
Guests: 15
Total: 15

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.