La rappresentazione degli algoritmi Il nostro pseudolinguaggio

La rappresentazione degli algoritmi
Per indicare le azioni svolte in un determinato algoritmo si utilizzano spesso due formalismi: i
diagrammi di flusso (detti anche diagrammi a blocchi o Flow Chart) che sono quelli che voi
conoscete e la pseudocodifica. Tali formalismi possono essere usati insieme oppure in alternativa.
Per indicare le azioni presenti negli algoritmi si può utilizzare la lingua italiana che è un linguaggio
naturale. Questo linguaggio però pur essendo molto utile per chiarire le idee sul problema, non si
presta bene a una precisa descrizione dell'algoritmo. Il linguaggio naturale, infatti, contiene
sinonimi, ambiguità che violerebbero una delle regole degli algoritmi che devono essere non
ambigui.
Se dobbiamo affermare che uno studente è molto volenteroso possiamo anche utilizzare gli
aggettivi: zelante, operoso, attivo, alacre, sollecito, dinamico, solerte ecc. Inoltre, se proviamo a
leggere la frase:
"Ieri sera ho visto Giuseppe con un conoscente" vediamo che può essere interpretata in due modi
diversi. Vale a dire:
"Ieri sera ho visto Giuseppe che era in compagnia di un conoscente" oppure:
9
Cercare un altro bancomat
FINESE
FINE
Osservando le righe precedenti notiamo che vi è una descrizione formale dell'algoritmo detta
pseudocodice perché, pur essendo strutturata come un codice scritto in un linguaggio di
programmazione, si serve di un linguaggio molto vicino a quello naturale, detto pseudolinguaggio o
linguaggio di progetto. L'attività di scrittura in tale pseudolinguaggio prende il nome di
pseudocodifica. Tale attività è una fase intermedia che si pone tra la fase di analisi dei problema e
quella di codifica in un vero e proprio linguaggio di programmazione.
Scopo principale della pseudocodifica è di portare il risolutore a esprimere le proprie istruzioni in
una forma naturale, utilizzando frasi ed espressioni elementari della lingua italiana. Ciò permette di
concentrarsi sulla risoluzione logica del problema, invece che sulla forma e sui vincoli da rispettare
nella sua enunciazione in un linguaggio di programmazione (in pratica ci si concentra più sul
COSA fare piuttosto che sul COME fare, regola aurea del progettista)
Il nostro pseudolinguaggio
"Ieri sera ho visto Giuseppe mentre ero in compagnia di un conoscente".
Per evitare tali ambiguità, insite in un linguaggio naturale, per la descrizione degli algoritmi da
codificare si utilizzano dei particolari “pseudolinguaggi”, detti così in quanto non sono
direttamente comprensibili da un calcolatore (come lo sono invece i linguaggi di programmazione).
Il vantaggio principale di tali pseudolinguaggi è che possono essere facilmente trasformati, senza
ambiguità per un programmatore esperto, in un programma eseguibile mediante codifica in un
particolare linguaggio di programmazione.
Consideriamo il seguente algoritmo scritto in un possibile pseudolinguaggio (si parla anche di
pseudocodifica dell'algoritmo)
Algoritmo: PrelievoDalBancomat (in pseudocodice).
INIZIO
1
SE il bancomat è in servizio
ALLORA
2
Introdurre la carta nel lettore
3
Digitare il codice segreto
4
SE il codice è corretto
1 Le parole chiave, o parole riservate (keywords in inglese), saranno scritte in
MAIUSCOLO e non potranno essere usate come identificatori (ricordo che gli identificatori
sono i nomi delle variabili o funzioni scelti dal programmatore)
2 gli identificatori saranno scritti in generale in minuscolo e sempre senza spazi. Solo in
alcuni casi useremo le maiuscole e precisamente
2.1 quando usiamo identificatori costituiti da più parole unite (gli identificatori sempre
senza spazi) allora le parole dopo la prima potranno iniziare con la maiuscola come in
laMiaVariabile. L'alternativa a tale forma sarà la_mia_variabile. Tutto ciò per una
migliore leggibilità dell'algoritmo
2.2 Per le funzioni o procedure useremo l'iniziale maiuscola e poi saranno sempre seguite
dalle parentesi tonde aperte e chiuse (anche nel caso non vi siano parametri)
Quando invece dobbiamo descrivere la sintassi di una istruzione (cioè le regole per formare una
istruzione valida) procederemo in questo modo
ALLORA
5
Digitare l'importo da prelevare
6
Ritirare le banconote
7
Ritirare la carta dal bancomat
ALTRIMENTI
8
Per specificare gli algoritmi senza far riferimento a nessun linguaggio (di programmazione)
particolare utilizzeremo uno pseudolinguaggio che rispetta le seguenti regole
Operazione terminata
FINESE
1) le parole racchiuse tra parentesi angolari <> rappresentano le categorie sintattiche, ossia
elementi generali del linguaggio che devono essere ulteriormente specificati. Ad esempio
a←b
a←c+2*d
c← 0
<variabile> ← <espressione> può essere
2) le parentesi quadre [] indicano l'opzionalità, ossia i blocchi in esse racchiusi possono anche
essere non presenti
3) i blocchi separati da una | (carattere chiamato pipe si legge “paip”) possono essere usati in
alternativa (o si usa l'uno o l'altro ma mai insieme)
ALTRIMENTI
1
2
4) le parentesi graffe indicano possibilità di ripetizione, ossia i blocchi in essa racchiusi
possono essere ripetuti più volte
La progettazione di algoritmi complessi
L'approccio Top-Down
Prerequisiti specifici
CONOSCENZE
ABILITÀ
Algoritmi
Saper realizzare algoritmi strutturati
Conoscere le strutture di controllo (sequenza –
selezione - iterazione)
Saper utilizzare consapevolmente le variabili
esige attenzione ai minimi dettagli e l'adozione di opportune tecniche di analisi dei problemi da
risolvere. Per questo, una buona metodologia di progettazione è quella che risolve il problema per
passi: partendo da un'analisi generale, si focalizza l'attenzione su singoli punti fondamentali che lo
compongono, riducendo così le difficoltà.
Tale metodologia di natura gerarchica prende il nome di top-down, ossia "dall'alto verso i basso".
Gli aggettivi alto e basso si riferiscono al livello di dettaglio o astrazione. Il livello più alto (top) è
quello della procedura generale di risoluzione del problema, chiamata problema principale, in cui si
individuano i suoi passi fondamentali chiamati sottoproblemi.
Ciascun sottoproblema viene dettagliato a parte e, se complesso, può essere a sua volta scomposto
in ulteriori sottoproblemi più semplici. Si giunge così all'analisi e alla risoluzione di tanti problemi
elementari tramite algoritmi descritti a livello programmabile (il più basso è down), le cui relazioni
sono ricavate dalla descrizione a livello superiore. In sintesi, si scende dal generale al particolare
mediante affinamenti successivi.
La tecnica top-down, quindi, nasce come tecnica di analisi dei problemi e non come tecnica di
progettazione: il risolutore, infatti, utilizza tale metodologia per affrontare agevolmente il processo
risolutivo del problema.
All'atto dell'implementazione, poi, il programmatore deciderà se implementare singolarmente i vari
sottoproblemi, mediante i sottoprogrammi che vedremo a breve, o se accorparne alcuni e
scomporne altri
Obiettivi specifici
CONOSCENZE
ABILITÀ
Conoscere la definizione di programma e
sottoprogramma
Saper suddividere un problema in sottoproblemi
Conoscere le forme per dichiarare
e chiamare un sottoprogramma
Saper definire e riconoscere ambienti locali e
globali
Conoscere i concetti di top-down e bottom-up
Saper implementare procedure e funzioni
Problema
Sottoproblema1
Sottoproblema2
Sottoproblema3
Conoscere i parametri attuali e formali
Conoscere le procedure e funzioni
Conoscere l'ambiente e le regole di visibilità
delle variabili
Sottoproblema3.1
Sottoproblema3.2
Conoscere la definizione di ricorsione
1 II ruolo della metodologia top-down e e bottom-up
Finora abbiamo posto e risolto problemi privi di grosse difficoltà. Questo per acquisire una buona
padronanza nelle fasi di analisi del problema e nella ricerca del metodo risolutivo. Nella realtà,
però, i problemi non sono tutti così semplici. Quando un problema appare immediatamente
complesso, per risolverlo possiamo individuare e analizzare i sottoproblemi più semplici che lo
compongono, oltre alle loro interrelazioni. In questo modo, è possibile articolare la progettazione
dell'algoritmo complessivo in una serie di algoritmi più semplici, che verranno poi opportunamente
assemblati.
Sottoproblema3.1.1 Sottoproblema3.1.2
Sottoproblema3.2.1
Per scomporre un problema in tanti sottoproblemi funzionali ci si sofferma su COSA debba essere
fatto e NON SUL COME, che con tale metodologia viene affrontato è soltanto all'ultimo livello.
La programmazione, in effetti, non è solo un processo di ideazione e formulazione di algoritmi:
Questo modo di procedere è molto importante: all'inizio mi devo solo soffermare su COSA devo
fare senza preoccuparmi dei dettagli, che mi distraggono dal problema principale. Una volta che ho
3
4
capito bene che cosa devo fare mi posso concentrare sui singoli sottoproblemi uno alla volta.
Preparare la teglia
La metodologia bottom-up, ossia "dal basso verso l'alto", privilegia, invece, l'aspetto esecutivo
rispetto a quello funzionale, procedendo dal particolare verso il generale. Il metodo bottom-up è una
strategia induttiva e consente di concentrarsi subito sui punti cardine del problema che, però, sono
molto difficili da individuare inizialmente. Proprio per questo motivo è meno adatta per la
progettazione di software. I due approcci non sono comunque in contrasto tra loro e spesso
coesistono senza nessun problema.
Preparare il forno
I sottoprogrammi
Esiste una possibilità di cui non abbiamo ancora parlato:
si può realizzare un sottoprogramma per ogni sottoproblema non più scomponibile.
Unendo, alla fine, tutti i sottoprogrammi, si ottiene il programma che risolve il problema originale.
Il sottoprogramma, quindi, è una parte del programma che risolve un particolare sottoproblema.
Grazie a metodologie note con il nome di tecniche dei sottoprogrammi, è possibile suddividere il
procedimento generale che risolve un problema in:
Infornare
Sfornare
FINE
L'attività Preparare l'impasto è di interesse generale, in quanto lo stesso impasto potrà essere
utilizzato per molti altri tipi di torte: quindi si può descriverla, laddove fosse necessario, tramite un
sottoprogramma. Le altre (da Preparare la teglia a Sfornare) sono piuttosto semplici e pertanto
possono essere dettagliate immediatamente. Analogo ragionamento andrà fatto per le altre azioni
descritte nell'algoritmo principale.
NOTA:
E' interessante chiedersi: quando conviene usare un sottoprogramma e quando no? Ecco la risposta
Conviene descrivere un'attività per mezzo di un NON Conviene descrivere un'attività per mezzo
sottoprogramma quando
di un sottoprogramma quando
1) un sottoprogramma principale (main) che descrive globalmente il problema;
È di interesse generale
2) un insieme di sottoprogrammi che risolvono i singoli sottoproblemi.
Non è di interesse generale ma si presenta più Non permette una maggiore leggibilità del
volte nel programma
programma o addirittura la complica
Analizziamo il seguente problema: preparare una torta gelato al cioccolato. Realizziamo il
programma principale servendoci dello pseudolinquaggio
Non è di interesse generale
Pur essendo di scarso interesse generale Non garantisce un risparmio di tempo
permette una maggiore leggibilità del
programma
ALGORITMO Torta
SOTTOPROGRAMMA Principale
Riepilogando esistono ottimi motivi che spingono a utilizzare i sottoprogrammi. In particolare essi:
INIZIO
Preparare la base per la torta
➢ migliorano la leggibilità del programma in maniera considerevole;
Preparare un gelato al cioccolato
➢ permettono l'astrazione. Quando il programmatore inserisce un'istruzione di chiamata di
sottoprogramma, astrae dalla realtà del sottoproblema. Si disinteressa cioè, in quel momento, della
sua realizzazione, perché gli interessa solo cosa fare e non come farlo;
Farcire la torta con il gelato
FINE
Tutte e tre le azioni sono piuttosto complesse e anche di interesse generale: per questi motivi
conviene descriverle per mezzo di sottoprogrammi. Continuiamo l'affinamento, a partire dalla prima
azione, cioè Preparare la base per la torta. Avremo:
SOTTOPROGRAMMA Preparare la base per la torta
INIZIO
Preparare l'impasto
5
➢ consentono di scrivere meno codice e così occupano meno memoria. Si evita, infatti, di
riscrivere più volte sequenze di istruzioni identiche in punti diversi del programma;
➢ sono riutilizzabili. Molto spesso accade che il sottoproblema che stiamo per risolvere sia già
stato risolto in un altro programma. Abbiamo già il sottoprogramma risolutivo: possiamo
riutilizzarlo senza riscriverlo.
Per eseguire un sottoprogramma è necessario utilizzare un'apposita istruzione di chiamata del
sottoprogramma, che è prevista da tutti i linguaggi di programmazione (la chiamata al
sottoprogramma si chiama anche invocazione del sottoprogramma) . Nel nostro pseudocodice
identificheremo tale istruzione con il nome del sottoprogramma.
6
Quando la CPU incontra un'istruzione di chiamata ad un sottoprogramma, sospende
temporaneamente l'elaborazione del programma chiamante e comincia a eseguire il sottoprogramma
chiamato. Terminata l'esecuzione del sottoprogramma, la CPU riprende l'esecuzione del
programma, ripartendo dall'istruzione successiva a quella di chiamata.
Analizziamo lo schema riportato nella figura. Quando la CPU incontra l'istruzione SP1 passa
immediatamente a eseguire il sottoprogramma SP1 (freccia 1).
Questa particolare caratteristica permette l'estrazione dei dati nell'ordine inverso in cui sono stati
inseriti: cioè l'ultimo dato inserito nella pila sarà sarà il primo a uscire. Per questo motivo, la pila è
anche conosciuta come struttura LIFO (Last In First Out).
Pensate a una pila di piatti. Se dovete aggiungerne uno, lo farete appoggiandolo sull'ultimo in alto.
Se dovete toglierlo, lo prenderete dalla stessa posizione: ossia l'ultimo inserito è il primo ad uscire
(LIFO, Last In First Out).
In nessun caso farete una delle due azioni sulla parte bassa della fila o nel mezzo (a meno di non
aver deciso di combinare un pasticcio!).
Alla luce di questi nuovi concetti, rivediamo in dettaglio l'esempio riportato nelle seguenti. I punti
seguenti corrispondono a quelli dettagliati nelle figure seguenti :
Durante l'esecuzione, la CPU incontra una nuova chiamata di sottoprogramma: SP2. Sospende
nuovamente l'esecuzione (questa volta del sottoprogramma SP1) e passa a eseguire le istruzioni
contenute nel sottoprogramma SP2 (freccia 2). Quest'ultimo viene eseguito interamente: l'ultima
istruzione, ossia FINE, riporta la CPU a continuare l'esecuzione del sottoprogramma SP1 (freccia 3)
dal punto in cui era stato sospeso, cioè dall'istruzione immediatamente successiva (Ist. C) a quella di
chiamata (SP2). Continua, così, l'esecuzione di SP1. Alla fine, la CPU incontra l'istruzione FINE e
torna a eseguire il programma chiamante (freccia 4) dall'istruzione successiva alla chiamata (SP1)
partendo, quindi, dalla istruzione Ist. A. E così via.
È importante ricordare che il sottoprogramma viene caricato in memoria al momento della chiamata
e, terminata l'esecuzione, viene rilasciato, liberando la memoria occupata. Occorre precisare meglio
questo fatto: l'esecuzione di un sottoprogramma comporta la creazione delle variabili in esso
definite (e dei parametri quando presenti) e l'esecuzione di tutte le istruzioni in esso definite ed,
all'uscita del sottoprogramma tali variabili (chiamate variabili locali) verranno distrutte. Questo
vale anche per i parametri passati alla funzione o alla procedura che sono equivalenti alle variabili
locali da questo punto di vista.
Tale metodo di gestire la memoria da parte del sistema operativo viene detto allocazione dinamica.
Per ricordare da quale istruzione va ripresa l'esecuzione del programma chiamante dopo la fine
dell'esecuzione di un sottoprogramma, la CPU si serve di un'apposita struttura dati conservata in
memoria detta pila dei record di attivazione. In ogni record di attivazione vengono memorizzate
alcune importanti informazioni tra cui, fondamentale, l'indirizzo della cella di memoria contenente
l'istruzione che dovrà essere eseguita al rientro (cioè al termine) del sottoprogramma.
1. quando la CPU esegue l'istruzione SP1, prima di dedicarsi all'esecuzione del
sottoprogramma memorizza nella prima posizione libera della pila (nel nostro caso la prima)
l'indirizzo dell'istruzione Ist. A (oltre ad altre informazioni di cui non ci occupiamo), dalla
quale riprendere l'esecuzione al rientro da SP1;
2. compiuta la memorizzazione, la CPU passa a eseguire SP1. In questo sottoprogramma,
incontra una nuova chiamata di sottoprogramma, precisamente SP2. Prima di eseguirlo,
quindi, deve memorizzare l'indirizzo dell'istruzione Ist. C dalla quale riprendere dopo il
rientro. A memorizzazione avvenuta, la situazione della pila sarà quella n° 2;
3. procedendo con l'esecuzione di SP2, la CPU incontra l'istruzione FINE. Per conoscere
l'istruzione dalla quale riprendere l'esecuzione, la CPU analizza la pila delle attivazioni ed
estrae l'indirizzo contenuto in testa (nel nostro caso l'indirizzo dell'istruzione Ist. C). Dopo
l'estrazione, la situazione della pila sarà quella n° 3 e l'esecuzione riprende da Ist. C, ossia
dall'istruzione riportante l'indirizzo estratto;
4. l'esecuzione continua e, a questo punto, si incontra una nuova istruzione FINE. Come al
solito, la CPU estrae l'indirizzo posto in testa alla pila e riprende a eseguire dall'istruzione
contrassegnata da quell'indirizzo (nel nostro caso, Ist. A). Siamo rientrati nel programma
principale e lo vediamo anche dal fatto che la pila è vuota (situazione n° 4).
La pila, detta anche stack in inglese, è una particolare struttura dati, all'interno della quale i dati
possono essere inseriti o estratti solo da un'estremità che chiamiamo, solitamente, testa della pila
(vedi figura)
7
8
VB
In visual Basic le procedure sono dichiarate in questo modo
private | public Sub <nomeProcedura> ([ByRef | ByVal <Parametro1> As <TipoParametro1>,
ByRef | ByVal <Parametro2> As <TipoParametro2>,..., ByRef | ByVal<ParametroN> A As
<TipoParametroN>,])
quindi private o public in alternativa e così pure ByVal e ByRef che vedremo dopo cosa
significano; il tipo dei parametri è opzionale.
Esempi di definizioni di intestazioni di procedure valide in VB sono
private Sub StampaReport()
public Sub StampaDatiUtente(ByVal utente)
Private Sub Ordina(ByRef a, ByRef b)
la prima è senza parametri, la seconda con un parametro e l'ultima con due parametri.
Naturalmente mancano tutte le istruzioni che fanno parte delle relative procedure, cioè quello che è
chiamato il corpo delle procedure
Osserviamo che esse sono, a livello di intestazione, perfettamente identiche alle funzioni: la
differenza tra le due sarà all'interno del corpo della funzione: infatti nelle procedure non ci sarà
alcuna istruzione return (istruzione che restituisce un valore al programma chiamante) mentre nelle
funzioni ve ne sarà almeno una.
Le Procedure
La procedura è un sottoprogramma contenente le istruzioni che risolvono un determinato
problema. L'esecuzione della procedura viene attivata mediante l'apposita istruzione di chiamata
che in quasi tutti i linguaggi è costituita dal nome che diamo alla procedura stessa.
A differenza delle funzioni (che vedremo a breve) le procedure non restituiscono un valore ma
eseguono solo delle azioni.
Queste azioni possono essere per esempio delle stampe, dei calcoli, uno scambio di variabili
eccetera. Non tutti i linguaggi di programmazione prevedono espressamente le procedure, ma
queste possono sempre essere “imitate” con delle funzioni che non restituiscono nulla o il cui valore
di ritorno non è importante.
Vediamo ora un problema in cui possiamo utilizzare una procedura per risolverlo. Il problema è il
semplice problema di ordinamento crescente di due numeri interi, che utilizza, quando necessario
una procedura per lo scambio del contenuto di due variabili.
Problema n°1: Scrivere un algoritmo che, dati in input due numeri, li ordini in senso crescente
e poi li visualizzi.
ALGORITMO Ordinamento
PROCEDURA Scambia()
INIZIO
c←a
a←b
b←c
Per definire una procedura in pseudocodifica utilizzeremo la seguente sintassi
FINE
PROCEDURA <NomeProcedura> ([<Parametro1>,<Parametro2>,...,<ParametroN>,])
PROCEDURA Main() #questo è il programma principale
da tale sintassi si nota che essa è caratterizzata da
a, b As Intero
1) un nome che deve ricordare (possibilmente) ciò che la procedura fa e che serve per
richiamarla (ossia per richiedere la sua esecuzione)
2) una lista di parametri (cioè <Parametro1>,<Parametro2>,...,<ParametroN>) che è opzionale
(notate nella descrizione le [] che indicano l'opzionalità) e permette lo scambio di input e/o
output tra il programma chiamante e la procedura stessa. Nel caso non vi siano parametri
<NomeProcedura> va comunque seguita dalle ().
INIZIO
SCRIVI(“Inserisci il primo numero: “)
LEGGI(a)
SCRIVI(“Inserisci il secondo numero: “)
LEGGI(b)
SE a < b ALLORA
9
10
SCAMBIA(a,b)
informazioni con il programma chiamante. Come per le procedure, se la funzione non
dovesse contenere parametri, il <NomeFunzione> va comunque seguito da una parentesi
tonda aperta e da una chiusa ();
SCRIVI(“I due numeri ordinati sono: “, a,” “,b)
FINE
3) ByVal e ByRef si riferiscono alle modalità del passaggio dei parametri (Vedi più avanti)
Vediamo ora come realizzare tale programma in VB.
Public Class Procedure
'definiamo la procedura Scamba()
Private Sub Scambia()
'procedura per lo scambio due variabili, senza parametri
'è importante capire che questo funziona solo se a e b sono presenti nel main program
c=a
a=b
b=c
End Sub
'programma principale, al cui interno richiamiamo la procedura Scambia()
Private Sub cmdEsegui_click(...)...
dim a,b As Integer
a=inputBox("Inserisci il primo numero: "))
b=inputBox("Inserisci il secondo numero: "))
if a < b then
Scambia() 'chiamata alla procedura Scambia()
End If
msgBox ("i numeri ordinati sono:" & a & " " & b
End Sub
End Class
4) As <Tipo Restituito> indica il tipo del valore restituito dalla funzione
Problema n° 2 Scrivere un algoritmo che, data in input una sequenza di N numeri interi
chiusa dallo 0, calcoli, per ciascuno di essi, il fattoriale.
Dalla matematica sappiamo (se no ve lo sto dicendo adesso) che il fattoriale di un numero naturale
N maggiore o uguale a zero, indicato con il simbolo N! (che si legge “N fattoriale”), è dato dalla
seguente formula:
0! = 1
N! = N * (N - 1) * (N - 2) * ... * 2 * 1
il che significa: il fattoriale del numero 0 (zero) è pari a 1, mentre il fattoriale di un qualunque
numero maggiore di 0 (zero) è pari al prodotto del numero stesso per tutti i numeri interi che lo
precedono sino all'uno
Ad esempio, il fattoriale di 5 è 5! = 5 * 4 * 3 * 2 * 1= 120
il fattoriale di 4 è 4! = 4*3*2*1=24 e così via per gli altri numeri.
Passiamo all'algoritmo:
ALGORITMO CalcoloFattoriale
num As Intero Lungo
Le Funzioni
La funzione è un sottoprogramma contenente le istruzioni che risolvono un particolare
sottoproblema. Quando essa è attivata da una istruzione di chiamata essa esegue le operazioni e
restituisce un valore al programma chiamante. Il valore restituito dalla funzione è di solito
usato come elemento di una istruzione (per esempio in una stampa o a destra di una istruzione di
assegnazione sia esso solo o all'interno di una espressione)
INIZIO
SCRIVI("Inserisci un numero (0 per finire))
LEGGI(num)
MENTRE num !=0 ESEGUI
SCRIVI('Il fattoriale di ", num,” e' ”, Fattoríale()) # Viene chiamata la funzione#Fattoriale, senza parametri
A differenza delle procedure, quindi, le funzioni restituiscono un risultato, oltre a svolgere delle
azioni; per questo motivo la funzione può essere richiamata in un'assegnazione a una variabile
oppure all'interno di una generica espressione.
Per questi motivi, e anche per evitare confusione, nell'implementazione dei nostri pseudocodici
utilizzeremo la nuova pseudoistruzione RITORNO <NomeVariabile> | <espressione> | <valore>.
Almeno una di tali istruzioni deve essere sempre presente in una funzione.
L'intestazione della funzione che utilizzeremo nella pseudocodifica si rifà al codice VB in cui è
necessario definire il tipo del valore restituito dalla funzione stessa. Differisce un po' da quella della
procedura:
FUNZIONE <NomeFunzione> ([ByVal | ByRef <Par1 >, ByVal | ByRef <Par2>, ... , ByVal | ByRef
<ParN>]) As <Tipo Restituito>
dove:
1) <NomeFunzione> è il nome a essa associato;
2) <Par1>, <Par2>, ... <ParN> costituiscono la lista di parametri necessari per lo scambio delle
11
SCRIVI("Inserisci un numero (0 per finire)")
LEGGI(num)
FINEMENTRE
FINE
FUNZIONE Fattoriale() As Reale Lungo
f As Reale Lungo 'qui memorizzeremo il fattoriale
i As intero 'questa è solo una variabile locale
INIZIO
f =1
i=num 'i è locale mentre Num è globale
MENTRE i >= 1 ESEGUI
12
f← f*i
Ambiente locale e globale e visibilità (scope) delle variabili
i=i-1
Durante la realizzazione di un sottoprogramma occorre definire tutte le risorse necessarie al suo
funzionamento, vale a dire il suo ambiente.
FINEMENTRE
Con il termine ambiente di un sottoprogramma definiamo l'insieme delle risorse (variabili,
costanti, sottoprogrammi, costanti) alle quali esso può accedere.
RITORNO (f)
FINE
Abbiamo utilizzato una funzione di nome Fattoriale che, per ogni numero intero inserito, restituisce
il suo fattoriale (anch'esso ovviamente intero, ma poiché può essere molto grande lo abbiamo
indicato come reale lungo). II risultato viene restituito dalla funzione per mezzo dell'istruzione:
RITORNO(f)
dove f è la variabile reale lunga che è stata utilizzata per calcolare il fattoriale del singolo numero
intero inserito. Ribadiamo che, grazie a questa pseudoistruzione, viene restituito al programma
chiamante il valore della variabile f in essa calcolato.
La funzione, inoltre, può essere utilizzata nelle espressioni come una semplice variabile, ma non
può mai comparire a sinistra di una istruzione di assegnazione o in un'istruzione di lettura. Ad
esempio, se in un programma è stata definita la funzione di nome Prod(), l'istruzione:
Tot ← Prod() * N
risulta valida e viene interpretata come: assegna alla variabile Tot il prodotto che si ottiene dal
risultato fornito dalla funzione Prod() per il valore della variabile N.
Vediamo ora di realizzare la nostra funzione in VB.
Public class Fattoriali
'Definiamo la funzione Fattoriale
Private Function Fattoriale() As Double
'Funzione che restituisce il fattoriale di un numero
Dim f As double
Dim i As Integer
f=1
i=num
do while i>=1
f = f *i
i=i-1
Loop
Per il momento, diciamo che l'ambiente è costituito:
1) Dall'ambiente locale, cioè dalle risorse dichiarate all'interno del sottoprogramma (risorse
locali);
2) dall'ambiente globale, ossia dalle risorse utilizzabili da tutti i sottoprogrammi (risorse
globali).
Un corretto stile di programmazione impone di minimizzare l'uso dell'ambiente globale e di
privilegiare quello locale.
Programma Esempio
(Y1,Y2,Y3)
Sottoprogramma A
(Z1,Z2,Z3)
Sottoprogramma B
(X1,X2)
Sottoprogramma A
(K1,K2)
Nel programma principale abbiamo accesso
alle variabili Y1,Y2,Y3 ed ai sottoprogrammi
A(), B() e C() ma non alle variabili locali a tali
sottoprogrammi
il sottoprogramma A VEDE (cioè ha accesso a) le sue
variabili Z1, Z2, Z3 e le variabili globali Y1, Y2, Y3.
NON VEDE le variabili dichiarate nei sottoprogrammi B e
C.
II sottoprogramma B VEDE (cioè ha accesso a) le sue
variabili X1, X2 e le variabili globali Y1, Y2, Y3.
NON VEDE le variabili dichiarate nei sottoprogrammi A e
C.
Il sottoprogramma C VEDE (cioè ha accesso a) le sue
variabili K1, K2 e le variabili globali Y1, Y2, Y3.
NON VEDE le variabili dichiarate nei sottoprogrammi A
e B.
return f
End Function
'fine funzione Fattoriale()
Quindi
'Programma principale
Private Sub cmdCalcola_click(...) …
Dim Num As Integer
num=inputBox("Inserisci un numero intero positivo (0 per terminare): "))
do while num <> 0
msgBox ("Il fattoriale di" & num & " è " & Fattoriale())
num=inputBox("Inserisci un numero intero positivo (0 per terminare): "))
Problema n°3: Visualizzare il prodotto di due numeri interi utilizzando la sola operazione di
somma.
Implementare un sottoprogramma significa descrivere le istruzioni contenute nel suo corpo e
dichiarare (nei LDP1 che prevedono dichiarazione di variabili) o utilizzare (nei LDP tipizzati
dinamicamente come python, PHP) le risorse che compongono il suo ambiente locale.
Supponiamo di voler svolgere il prodotto di 5*3: si tratterà di sommare 3 volte 5 (ossia eseguire
5+5+5). Generalizzando, dati due numeri in input a e b, si tratterà di sommare b volte il numero a.
loop
End Sub
Anche questa funzione è molto semplice e, come potete vedere, è stata utilizzata all'interno di una
msgBox. Per ogni numero che inseriamo essa calcola il valore del del fattoriale di quel numero.
1 LDP: Linguaggi Di Programmazione
13
14
ALGORITMO Moltiplicazione
È pertanto necessario definire delle regole per determinare il campo di visibilità degli oggetti
globali e locali di un programma. Si parte dai seguenti principi:
FUNZIONE Moltiplica()
'funzione che esegue la moltiplicazione di a per b usando solo somme
1) gli oggetti globali sono accessibili a (visibili in) tutto il programma;
INIZIO
prod ← 0 'variabile locale accumulatore che conterrà il prodotto di a per b
j=1 'variabile locale di controllo del ciclo
MENTRE j <= b ESEGUI
2) un oggetto dichiarato in un sottoprogramma ha significato solo in quel sottoprogramma e in
tutti quelli in esso dichiarati. L'ambiente di un sottoprogramma, quindi, include anche tutte
le risorse dei sottoprogrammi che contengono il sottoprogramma stesso (ambiente non
locale)
prod ← prod + a
OSCURAMENTO (SHADOWING)
j←j+1
FINEMENTRE
RITORNO prod # restituiamo il valore di prodotto al programma chiamante ed anche il
# controllo all'istruzione successiva del programma chiamante
FINE
FUNZIONE MAIN() #d'ora in poi il programma principale lo chiamiamo così
Nella descrizione di un algoritmo, può succedere che si dia lo stesso nome ad una variabile locale
ed ad una globale. Esse sono due variabili diverse senza alcuna relazione fra loro. Se per esempio
la variabile A viene dichiarata nel programma principale e nel sottoprogramma SP1 e se, all'interno
del sottoprogramma SP1 eseguo l'istruzione A ← 3 a quale variabile sarà assegnato il valore 3?
La risposta è alla variabile A locale al sottoprogramma SP1 in quanto essa “oscura” l'omonima
variabile globale
INIZIO
SCRIVI(“Inserire il primo fattore: “)
I parametri
LEGGI(a)
SCRIVI(“Inserire il secondo fattore: “)
LEGGI(b)
SCRIVI(“Il prodotto di “,a, “ e “, b, ” e' “, Moltiplica()) #si attiva la funzione Moltiplica()
FINE
Le variabili a e b sono variabili globali e possono essere utilizzate da tutti i sottoprogrammi
dichiarati nello stesso programma.
Un sottoprogramma è più utile se è funzionalmente indipendente dal programma principale.
Un sottoprogramma, infatti, può essere utilizzato più volte all'interno di un programma e può anche
essere trasportato, cioè, utilizzato con successo in altri programmi. Spesso accade di dover
riscrivere interi sottoprogrammi che, pur essendo uguali nella logica e nelle istruzioni, operano su
dati diversi.
Ciò comporta notevoli inconvenienti:
1) l'algoritmo appare pesante nella sua struttura e molto ripetitivo;
Le variabili prod e I, invece, sono definite all'interno della funzione Moltiplica() e possono essere
utilizzate solo da essa. Vengono quindi utilizzate solo durante l'esecuzione del sottoprogramma:
sono, pertanto, variabili locali.
2) esiste un elevato rischio di commettere errori in fase di copiatura;
SCELTA DELLE VARIABILI LOCALI
4) eventuali analoghe modifiche dell'algoritmo potrebbero dover essere apportate in più punti.
La scelta delle variabili locali non deve essere affidata al caso. Nel nostro esempio, infatti, abbiamo
deciso di definire variabili locali prod e j perché vengono utilizzate esclusivamente dal
sottoprogramma e anche perché l'utilizzo di tali variabili permette di:
1) agevolare la lettura del programma, in quanto mette in evidenza in quale ambito hanno
significato le risorse (le variabili);
2) individuare facilmente errori commessi, in quanto ci si sofferma solo sulle risorse (variabili)
locali nell'ambito di quel sottoprogramma.
3) durante la fase di test, occorre necessariamente ricontrollare parti di algoritmo praticamente
uguali;
Con le attuali conoscenze, purtroppo, non possiamo fare altrimenti. Analizziamo il seguente
pseudocodice che visualizza un messaggio di saluto per tre differenti nominativi forniti in input:
ALGORITMO VisualizzaNomi
PROCEDURA Visualizza1()
INIZIO
SCRIVI("Ciao" , 'Mario")
FINE
Le regole di visibilità
È ormai chiaro che all'interno di un programma ogni oggetto ha un suo campo di validità (scope,
in inglese), ossia un ambito in cui può essere usato e riconosciuto.
15
PROCEDURA Visualizza2()
INIZIO
16
SCRIVI("Ciao" , "Paolo")
FINE
PROCEDURA Visualizza3()
INIZIO
SCRIVI("Ciao" , "Fabio")
FINE
FUNZIONE Main():
INIZIO
Visualizza1()
Visualizza2()
Visualizza3()
FINE
Come dicevamo, non abbiamo ancora preso in esame alcuno strumento che permetta di riutilizzare
lo stesso sottoprogramma. In questo esercizio l'utilizzo dei sottoprogrammi perde il suo alto valore
metodologico: le tre procedure sono identiche, ma operano su dati diversi. Siamo stati per questo
costretti a riscrivere più volte il sottoprogramma, cambiando il suo nome e i dati su cui opera.
Si rende necessario, quindi, uno strumento che renda i sottoprogrammi autonomi e indipendenti dai
dati del programma principale.
Per far questo, i linguaggi di programmazione mettono a disposizione i parametri.
I parametri sono oggetti caratterizzati da:
1) un identificatore;
2) un tipo;
Un sottoprogramma parametrizzato lavora con variabili fittizie (nel nostro caso i parametri formali
X e Y), che vengono collegate al programma principale solo al momento della chiamata del
sottoprogramma.
È per questo motivo che tali parametri vengono detti formali. Dei parametri attuali (quindi al
momento della chiamata da parte del programma chiamante) occorre indicare solo il nome; dei
parametri formali, invece, è necessario indicare il nome e il tipo (il tipo è necessario solo nei
linguaggi statici come Pascal, C, C++, in python, php, VB ed altri non è necessario).
E importante dire che il numero, il tipo e l'ordine dei parametri attuali devono essere sempre uguali
a quelli dei corrispondenti parametri formali. Nel nostro esempio, infatti, la chiamata della
procedura Proc1() associa il parametro attuale A di tipo intero al parametro formale X (anch'esso,
ovviamente, di tipo intero) e il parametro attuale B di tipo intero al parametro formale Y di tipo
intero.
I parametri attuali e i parametri formali possono anche avere casualmente lo stesso nome, ma si
consiglia di utilizzare nomi diversi (per evitare inutili confusioni).
3) un valore;
4) una posizione;
Spesso, all'atto della dichiarazione di un sottoprogramma, nasce il problema della scelta dei
parametri. Suggeriamo di rispettare le seguenti regole:
5) una direzione.
Grazie a essi si stabilisce attraverso quali oggetti debba avvenire l'input dei dati (al sottoprogramma
chiamato) e l'output dei risultati (al programma o sottoprogramma chiamante).
L'identificatore e il tipo dei parametri sono noti al momento della dichiarazione del sottoprogramma
(nei linguaggi statici quali C, C++, Pascal, è necessario conoscere il tipo al momento della
dichiarazione, nei linguaggi dinamici quali python, perl non è necessario e tale fatto può essere un
grande vantaggio) ma il valore è noto solo all'atto della chiamata.
I parametri permettono, quindi, di gestire la comunicazione del sottoprogramma con
l'esterno.
All'atto della chiamata del sottoprogramma, occorrerà specificare i parametri attuali (chiamati
anche argomenti o parametri effettivi), ossia le informazioni reali che devono essere trasmesse a
esso. I valori di tali parametri saranno accolti dal sottoprogramma per mezzo dei parametri
formali dichiarati nell'intestazione del sottoprogramma (vedi figura).
1) dovrà essere gestito come parametro un oggetto necessario allo svolgimento delle
operazioni/elaborazioni del sottoprogramma (oggetto di input) o che dovrà essere
comunicato al programma chiamante (oggetto di output);
2) non dovrà essere gestito come parametro un oggetto il cui significato è limitato all'interno di
un sottoprogramma.
E ora, a conclusione di questo paragrafo, vediamo come può essere trasformato il nostro algoritmo:
ALGORITMO VisualizzaNomi
PROCEDURA Visualizza (name):
INIZIO
SCRIVI("Ciao" , name)
17
18
FINE
Per capire ancora meglio può essere interessante fare un disegno che rappresenti la memoria del
calcolatore. Supponiamo che A e B valgano 3 e 8 rispettivamente: la situazione di memoria prima
della chiamata alla procedura scambia è la seguente: abbiamo le due locazioni di memoria A e B
che contengono 3 e 8
FUNZIONE Main():
INIZIO
SCRIVI(“Inserisci il primo nome: “)
A
3
LEGGI(nome)
Visualizza(nome)
Al momento della chiamata al sottoprogramma, la prima cosa che avviene è che vengono create due
variabili temporanee e locali che si chiamano X e Y e in esse viene copiato il contenuto di A e B (in
base all'ordine con cui sono state scritte, ossia la situazione è la seguente
SCRIVI(“Inserisci il secondo nome: “)
LEGGI(nome)
A
3
Visualizza(nome)
SCRIVI(“Inserisci il terzo nome: “)
Visualizza(nome)
FINE
Qui si incomincia ad intravedere l'utilità dei sottoprogrammi che sta principalmente nel riutilizzo
del codice: ho scritto una sola volta il codice per risolvere un particolare problema e poi l'ho
riutilizzato tre volte (ricordi che nel caso senza parametri ho dovuto scriverlo tre volte?)
I parametri formali vengono considerati come variabili locali il cui valore, al ritorno dal
sottoprogramma, perde il suo significato;
PROCEDURA Esempio ()
.....
Con passaggio o trasmissione dei parametri intendiamo l'operazione con la quale valore dei
parametri attuali viene associato (trasmesso) a quello dei parametri formali
Il passaggio dei parametri può avvenire principalmente secondo due distinte modalità, ognuna
rispondente a esigenze diverse: passaggio per valore (by value) e passaggio per indirizzo o
referenza (by reference).
Scambia(A,B)
......
PROCEDURA Scambia(Ref: X,Y)
INIZIO
......
Copia dei
valori
PROCEDURA Scambia(X,Y)
INIZIO
....
nel passaggio dei parametri per indirizzo (by
reference) invece i parametri formali
contengono l'indirizzo di memoria dei
parametri attuali. Di conseguenza non si ha
soltanto una copia dei valori dei parametri
attuali nei rispettivi parametri formali ma una
modifica dei parametri formali comporta una
eguale e contemporanea modifica dei
parametri attuali).
....
....
PROCEDURA Esempio ()
FINE
Coincidono
FINE
Vediamo in dettaglio queste due modalità. Consideriamo la procedura Scambia() che dovrà
scambiare i valori dei due parametri attivati.
Scambia(A,B)
Y
8
INIZIO
Il passaggio dei parametri
.....
X
3
B
8
Le celle X e Y verranno usate dal sottoprogramma e poi alla fine verranno distrutte (tecnicamente si
parla di allocazione della memoria al momento della creazione delle due variabili temporanee e
locali e di deallocazione o rilascio della memoria al momento dell'uscita dal sottoprogramma.
LEGGI(nome)
INIZIO
B
8
nel passaggio dei parametri per valore (by
value) si ha soltanto una copia dei valori dei
parametri attuali nei rispettivi parametri formali.
Durante l'esecuzione del sottoprogramma,
qualsiasi modifica apportata ai parametri formali
sarà visibile solo all'interno del sottoprogramma
e non verrà riportata sui parametri attuali (che
continueranno, così, a conservare il valore
inizialmente trasmesso).
....
FINE
19
FINE
Anche in questo caso facciamo un disegno che rappresenti la memoria del calcolatore. Supponiamo
che A e B valgano 8 e 2 rispettivamente: la situazione di memoria prima della chiamata alla
procedura scambia è la seguente: abbiamo le due locazioni di memoria A e B che contengono 8 e 2
A
8
B
2
Al momento della chiamata al sottoprogramma, la prima cosa che avviene è che vengono creati due
nuovi nomi temporaneei e locali che si chiamano X e Y ma nessuna zona nuova di memoria è
associata ad essi: questi nomi faranno riferimento il primo X alla locazione A e il secondo Y alla
locazione B (questo in base all'ordine con cui sono stati scritti parametri stessi) ossia la situazione è
20
la seguente
A
8
FINE SE
B
2
X
SCRIVI(“I due numeri ordinati sono: “,primo,secondo)
Y
FINE
In questo caso quindi non c'è alcuna memoria locale associata ai parametri ma solo dei nomi locali e
temporanei (cioè che esistono solo per il tempo di esecuzione della procedura e che sono visibili
solo in ambiente locale) che però, fanno riferimento alle locazioni di memoria dei parametri attuali
e quindi possono modificarli: in realtà ciascuna operazione eseguita su X è come se fosse fatta su A
e lo stesso si può dire per la copia Y e B.
Con questo tipo di passaggio, quindi, si può perdere il contenuto originale dei parametri attuali.
Secondo il nostro formalismo, il passaggio per indirizzo viene indicato anteponendo la parola
chiave REF (referenza) al parametro o alla lista di parametri formali interessati.
Non tutti i linguaggi prevedono ambedue i tipi di passaggio di parametri. Il Pascal, il Visual Basic li
gestisce entrambi, mentre nel linguaggio C è ammesso soltanto il passaggio per valore, anche se il
passaggio per referenza può essere imitato. In python il discorso è ancora diverso.
N.B. Nel passaggio dei parametri per valore, all'atto della chiamata del sottoprogramma, viene
allocata un'area di memoria utilizzata per contenere i parametri formali. Si ha, così, una
duplicazione dello spazio di memoria riservato ai parametri. Al passaggio, i parametri formali
verranno inizializzati con il valore dei rispettivi parametri attuali. In questo modo, il processore
opera su questa nuova area di memoria lasciando inalterato il valore dei parametri attuali.
Al rientro dal sottoprogramma, quest'area viene rilasciata, proprio come avviene per le variabili
locali.
Servendoci delle nuove conoscenze acquisite sul passaggio dei parametri vogliamo rendere più
generale l'algoritmo di ordinamento di due numeri visto in precedenza.
ALGORITMO Ordinamento
Il passaggio dei parametri è per valore per cui l'algoritmo così come è strutturato non funziona (cioè
non fa ciò che vorremmo facesse): questo è dovuto al fatto che al momento della chiamata della
procedura scambia vengono create le variabili x e y (e anche temp che è sempre una variabile
locale) che sono solo una copia dei valori di primo e secondo ma, come abbiamo appena imparato,
le modifiche effettuate su x e y non hanno alcuna influenza sui parametri attuali primo e secondo.
Per convincerci di ciò implementiamo tale problema in VB e vediamo che succede
Public Class frmScambiaErrato
Private Sub cmdEsegui_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles cmdEsegui.Click
Dim primo, secondo As Integer
primo = txtPrimo.Text
secondo = txtSecondo.Text
If primo > secondo Then
scambia(primo, secondo)
End If
lblPrimoScambiato.Text = lblPrimoScambiato.Text & "
" & primo
lblSecondoScambiato.Text = lblSecondoScambiato.Text & "
" & secondo
End Sub
Private Sub scambia(ByVal x, ByVal y)
'dovrebbe scambiare x con y ma è sbagliata in quanto i parametri sono
'solo passati per valore e non hanno effetto sulle variabili del programma chiamante
Dim temp As Integer
temp = x
x=y
y = temp
End Sub
Private Sub cmdEsci_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
cmdEsci.Click
PROCEDURA Scambia(x,y)
End
End Sub
End Class
INIZIO
temp ← x
L'esecuzione di questo programma porta ad esempio a questo risultato
x←y
y ← tmp
FINE
PROCEDURA Main()
INIZIO
SCRIVI(“Inserisci il primo numero: “)
LEGGI(primo)
come vedete i numeri e le variabili non sono state affatto scambiate
SCRIVI(“Inserisci il secondo numero: “)
Come vedete all'interno della procedura i dati sono stati ordinati ma non all'esterno.
LEGGI(secondo)
Vediamo di risolvere subito il problema sia in pseudocodifica che in VB.
SE primo > secondo ALLORA
L'unica modifica nel pseudocodice è l'introduzione del passaggio per referenza evidenziato dalla
parola chiave REF nella definizione della procedura Scambia
Scambia(primo, secondo)
21
22
ALGORITMO Ordinamento
Precisazioni riguardo visual Basic.
PROCEDURA Scambia(REF: x,y)
Il modello di programmazione di VB è chiamato programmazione ad eventi: infatti il programma va
in esecuzione e poi aspetta gli eventi che possono accadere, generalmente causati dall'utente umano
ma non necessariamente, che possono essere il click di un mouse, lo spostamento del mouse, l'inizio
della scrittura etc.; a questi eventi, se previsto dal codice, il VB esegue le cosiddette procedure di
gestione degli eventi, che sono quelle che abbiamo sempre eseguito ed associato al click del
pulsante esegui per esempio.
INIZIO
temp ← x
x←y
y ← tmp
Le procedure e funzioni che stiamo vedendo qui vengono invece chiamate procedure generali e, a
differenza delle altre non sono associate ad eventi, ma sono associate a del codice mediante le
famose istruzioni di chiamata al sottoprogramma.
FINE
PROCEDURA Main()
Per quanto riguarda la visibilità delle risorse (variabili e sottoprogrammi stessi) in VB abbiamo le
seguenti possibilità. Si possono creare sottoprogrammi generali di due tipi diversi:
INIZIO
SCRIVI(“Inserisci il primo numero: “)
1) ci sono i sottoprogrammi contenuti all'interno di un form (sono quelli visti sinora e le cui
definizioni sono scritte all'interno di public class...end class. Queste procedure sono note
all'interno del form stesso, ossia possono essere richiamate da qualunque sottoprogramma
presente all'interno del forma. Stessa cosa dicasi per le variabili: le variabili dichiarate nella
sezione generale di un form sono note a tutti i sottoprogrammi del form stesso
LEGGI(primo)
SCRIVI(“Inserisci il secondo numero: “)
LEGGI(secondo)
SE primo > secondo ALLORA
2)
Scambia(primo, secondo)
FINE SE
ci sono poi i sottoprogrammi a livello di modulo (questi non li abbiamo ancora visti).
Questo tipo di sottoprogrammi possono essere usati da tutti i form del programma. In
qualche modo sono sottoprogrammi più globali dei precedenti
SCRIVI(“I due numeri ordinati sono: “,primo,secondo)
FINE
In Visual Basic le modifiche sono dello stesso tipo: occorre cambiare il tipo di passaggio di
parametri da “passaggio per valore” a “passaggio per riferimento”.
Public Class frmScambiaCorretto
Private Sub cmdEsegui_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles cmdEsegui.Click
Dim primo, secondo As Integer
primo = txtPrimo.Text
secondo = txtSecondo.Text
If primo > secondo Then
scambia(primo, secondo)
End If
lblPrimoScambiato.Text = lblPrimoScambiato.Text & "
" & primo
lblSecondoScambiato.Text = lblSecondoScambiato.Text & "
" & secondo
End Sub
Private Sub scambia(ByRef x, ByRef y)
'scambia x con y ossia i rispettivi parametri attuali con cui viene chiamata
Dim temp As Integer
temp = x
x=y
y = temp
End Sub
Private Sub cmdEsci_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
cmdEsci.Click
End
End Sub
End Class
23
24