5. Funzioni e procedure
5.1. Funzioni predefinite di VBScript
La ricchezza di un linguaggio deriva in gran parte dalla sua libreria di funzioni, poiché queste funzioni possono essere incapsulate in oggetti sotto il nome di metodi. A questo proposito, VBScript può essere considerato piuttosto limitato.
La tabella seguente elenca le funzioni VBScript al di fuori degli oggetti. Non entreremo nei dettagli al riguardo. I loro nomi indicano generalmente il loro scopo. I lettori dovrebbero consultare la documentazione per i dettagli su una funzione specifica.
Abs | Array | Asc | Atn |
CBool | CByte | CCur | CDate |
CDbl | Chr | CInt | CLng |
Conversioni | Cos | CreateObject | CSng |
Date | DateAdd | DateDiff | DatePart |
DataSeriale | Valore data | Giorno | Derivato Matematica |
Eval | Exp | Filtro | Formato valuta |
FormatoDataOra | Formato numero | Formato percentuale | GetLocale |
GetObject | GetRef | Esadecimale | Hour |
InputBox | InStr | InStrRev | Int, Fixs |
IsArray | IsDate | IsEmpty | IsNull |
IsNumeric | IsObject | Unire | LBound |
LCase | Left | Len | CaricaImmagine |
Log | LTrim; RTrim; e Trims | Matematica | Mid |
Minuto | Mese | NomeMese | Casella di messaggio |
Ora | Ott | Sostituisci | RGB |
Destra | Rnd | Rotonda | ScriptEngine |
ScriptEngineBuildVersion | ScriptEngineMajorVersion | ScriptEngineMinorVersion | Secondo |
Imposta lingua | Sgn | Peccato | Spazio |
Divisione | Sqr | StrComp | Stringa |
Tan | Time | Timer | TimeSerial |
TimeValue | NomeTipo | UBound | UCase |
VarType | Giorno della settimana | NomeGiorno | Anno |
5.2. Programmazione modulare
Descrivere la soluzione programmata a un problema significa descrivere la sequenza di operazioni di base che possono essere eseguite dal computer e che sono in grado di risolvere il problema. A seconda del linguaggio di programmazione, queste operazioni di base variano in termini di complessità. Alcuni esempi includono:
- lettura di dati dalla tastiera o dal disco
- scrittura di dati sullo schermo, su una stampante, su un disco, ecc.
- calcolo di espressioni
- navigazione all'interno di un file
- ...
La descrizione di un problema complesso può richiedere diverse migliaia di queste istruzioni di base o anche di più. È quindi molto difficile per la mente umana cogliere il quadro generale di un programma. Di fronte a questa difficoltà nel cogliere il problema nel suo insieme, lo scomponiamo in sotto-problemi più facili da risolvere. Consideriamo il seguente problema: ordinare una lista di valori numerici immessi tramite la tastiera e visualizzare la lista ordinata sullo schermo.
Inizialmente possiamo descrivere la soluzione nella forma seguente:
début
lire les valeurs et les mettre dans un tableau T
trier le tableau T
écrire les valeurs triées du tableau T à l'écran
fin
Abbiamo suddiviso il problema in 3 sotto-problemi, che sono più facili da risolvere. La notazione algoritmica è spesso più formalizzata rispetto alla precedente, e l'algoritmo verrebbe scritto come segue:
dove T rappresenta un array. Le operazioni
sono operazioni non elementari che devono a loro volta essere descritte da operazioni elementari. Ciò avviene in quelli che vengono chiamati moduli. Il dato T è chiamato parametro del modulo. Si tratta di informazioni che il programma chiamante passa al modulo chiamato (parametro di input) o riceve dal modulo chiamato (parametro di output). I parametri di un modulo sono quindi le informazioni scambiate tra il programma chiamante e il modulo chiamato.
modulo read_array(T) | ![]() |
modulo sort_array(T) | ![]() |
modulo read_array(T) | ![]() |
Il modulo read_array(T) potrebbe essere descritto come segue:
début
écrire "Tapez la suite de valeurs à trier sous la forme val1 val2 ... : "
lire valeurs
construire tableau T à partir de la chaîne valeurs
fin
A questo punto, abbiamo descritto in modo esauriente il modulo read_array. Infatti, le tre azioni necessarie trovano un'immediata traduzione in VBScript. L'ultima richiederà l'uso della funzione Split. Se VBScript non disponesse di questa funzione, l'azione 3 dovrebbe a sua volta essere scomposta in azioni elementari aventi un equivalente immediato in VBScript.
Il modulo write_array(T) potrebbe essere descritto come segue:
début
construire chaîne texte "valeur1,valeur2,...." à partir du tableau T
écrire texte
fin
Il modulo write_array(T) potrebbe essere descritto come segue (supponendo che gli indici degli elementi di T partano da 0):
début
N<-- indice dernier élément du tableau T
pour IFIN variant de N à 1
faire
//on recherche l'indice IMAX du plus gd élément de T
// IFIN est l'indice du dernier élément de T
chercher_max(T, IFIN, IMAX)
// on échange l'élément le plus grand de T avec le dernier élément de T
échanger (T, IMAX, IFIN)
finfaire
FIN
Qui, l'algoritmo utilizza nuovamente azioni non elementari:
. chercher_max(T, IFIN, IMAX)
. échanger(T, IMAX, IFIN)
find_max(T, IFIN, IMAX) restituisce l'indice IMAX dell'elemento più grande nell'array T il cui ultimo elemento ha indice IFIN.
![]() |
swap(T, IMAX, IFIN) scambia due elementi dell'array T, quelli agli indici IMAX e IFIN.
![]() |
Dobbiamo quindi descrivere le nuove operazioni non elementari.
modulo find_max(A, IFIN, IMAX) | |
modulo di scambio(T IMAX, IFIN) |
Il problema iniziale è stato descritto in modo completo utilizzando operazioni di base in VBScript e può quindi essere ora tradotto in questo linguaggio. Si noti che le operazioni di base possono variare da un linguaggio all'altro e che, pertanto, l'analisi di un problema deve a un certo punto tenere conto del linguaggio di programmazione utilizzato. Un oggetto che esiste in un linguaggio potrebbe non esistere in un altro, modificando così l'algoritmo utilizzato. Pertanto, se un linguaggio disponesse di una funzione di ordinamento, sarebbe assurdo non utilizzarla in questo caso.
Il principio qui applicato è noto come analisi top-down. Se delineiamo la struttura della soluzione, otteniamo quanto segue:
![]() |
Abbiamo una struttura ad albero.
5.3. Funzioni e procedure VBScript
Una volta eseguita l'analisi modulare, il programmatore può tradurre i moduli del proprio algoritmo in funzioni o procedure VBScript. Sia le funzioni che le procedure accettano parametri di input/output, ma una funzione restituisce un risultato che ne consente l'utilizzo nelle espressioni, mentre una procedura no.
5.3.1. Dichiarazione di funzioni e procedure VBScript
La dichiarazione di una procedura VBScript è la seguente
e quella di una funzione
Per restituire il proprio risultato, la funzione deve includere un'istruzione di assegnazione che assegni il risultato a una variabile con lo stesso nome della funzione:
nomeFunzione=risultato
L'esecuzione di una funzione o di una procedura termina in due modi:
- quando si incontra l'istruzione end function o end sub
- quando si incontra l'istruzione exit function o exit sub
Per una funzione, si noti che il risultato deve essere stato assegnato a una variabile con il nome della funzione prima che la funzione termini con un'istruzione end function o exit function.
5.3.2. Modalità di passaggio dei parametri per una funzione o una procedura
Nella dichiarazione dei parametri di input-output di una funzione o procedura, viene specificata la modalità (byRef, byVal) di passaggio dei parametri dal programma chiamante al programma chiamato:
sub nomProcédure([Byref/Byval] param1, [Byref/Byval] param2, ...)
function nomFonction([Byref/Byval] param1, [Byref/Byval] param2, ...)
Quando la modalità byRef o byVal non è specificata, viene utilizzata la modalità byRef.
Parametri effettivi, parametri formali
Si consideri una funzione VBScript definita come
I parametri paramForm1 utilizzati nella definizione della funzione o della procedura sono chiamati parametri formali. La funzione precedente può essere chiamata dal programma principale o da un altro modulo utilizzando un'istruzione del tipo:
I parametri paramEffi utilizzati nella chiamata alla funzione o alla procedura sono detti parametri effettivi. Quando ha inizio l'esecuzione della funzione functionName, i parametri formali ricevono i valori dei corrispondenti parametri effettivi. Le parole chiave byRef e byVal determinano la modalità di trasmissione di tali valori.
Modalità pass-by-value (byVal)
Quando un parametro formale specifica questa modalità di passaggio, il parametro formale e il parametro effettivo sono due variabili diverse. Il valore del parametro effettivo viene copiato nel parametro formale prima che la funzione o la procedura venga eseguita. Se la funzione o la procedura modifica il valore del parametro formale durante l'esecuzione, ciò non influisce sul valore del corrispondente parametro effettivo. Questo metodo di passaggio è particolarmente adatto per i parametri di input di una funzione o di una procedura.
![]() |
Modalità di passaggio per riferimento (byRef)
Questa modalità di passaggio è quella predefinita se non viene specificata alcuna modalità di passaggio dei parametri. Quando un parametro formale specifica questa modalità di passaggio, il parametro formale e il corrispondente parametro effettivo sono la stessa identica variabile. Pertanto, se la funzione modifica il parametro formale, viene modificato anche il parametro effettivo. Questa modalità di passaggio è particolarmente adatta per:
- parametri di output, poiché i loro valori devono essere restituiti al programma chiamante
- parametri di input la cui copia è dispendiosa, come gli array
![]() |
Il programma seguente mostra alcuni esempi di passaggio di parametri:
Programma
Sub proc1(byval i, ByRef j, k)
' i is passed by value (byval) - the effective parameter and the formal parameter are then different
' j is passed by value (byref) - the effective parameter and the formal parameter are then identical
' the k passage mode is not specified. The default is by reference
i=i+1
j=j+1
k=k+1
affiche "dans proc1",i,j,k
End Sub
Sub affiche(byval msg, ByVal i, ByVal j, ByVal k)
' displays the values of i and j and k
wscript.echo msg & " i=" & i & " j=" & j & " k=" & k
End Sub
' ------------- calls to functions and procedures
' init i and j
i=4:j=5 : k=6
' check
affiche "dans programme principal, avant l'appel à proc1 :",i,j,k
' call proc1 procedure
proc1 i,j,k
' check
affiche "dans programme principal, après l'appel à proc1 :",i,j,k
' end
wscript.quit 0
Risultati
dans programme principal, avant l'appel à proc1 : i=4 j=5 k=6
dans proc1 i=5 j=6 k=7
dans programme principal, après l'appel à proc1 : i=4 j=6 k=7
Commenti
- In uno script VBScript non esiste una posizione specifica per le funzioni e le procedure. Possono trovarsi in qualsiasi punto del codice sorgente. Generalmente sono raggruppate all'inizio o alla fine, mentre il programma principale è strutturato come un blocco continuo.
5.3.3. Sintassi per la chiamata di funzioni e procedure
Sia p una procedura che accetta i parametri formali pf1, pf2, ...
- la chiamata alla procedura p assume la forma
senza parentesi attorno ai parametri
- se la procedura p non accetta parametri, è possibile utilizzare sia la chiamata p che p() e la dichiarazione sub p o sub p()
Sia f una funzione che accetta i parametri formali pf1, pf2, ...
- La funzione f viene chiamata nella forma
Le parentesi attorno ai parametri sono obbligatorie. Se la funzione f non accetta parametri, è possibile utilizzare sia la chiamata f che f() e la dichiarazione function f o function f().
- Il risultato della funzione f può essere ignorato dal programma chiamante. La funzione f viene quindi considerata una procedura e segue le regole per la chiamata delle procedure. Si scrive quindi f pe1, pe2, ... (senza parentesi) per chiamare la funzione f.
Se la funzione o la procedura è un metodo di un oggetto, le regole sembrano essere in qualche modo diverse e incoerenti.
- Pertanto, possiamo scrivere MyFile.WriteLine "Questo è un test." oppure MyFile.WriteLine("Questo è un test.")
- ma mentre possiamo scrivere wscript.echo 4, non possiamo scrivere wscript.echo(4).
Ci atterremo alle seguenti regole:
- nessuna parentesi attorno ai parametri di una procedura o funzione utilizzata come procedura
- parentesi attorno ai parametri di una funzione
5.3.4. Alcuni esempi di funzioni
Di seguito sono riportati alcuni esempi di definizioni e utilizzi delle funzioni:
Programma
Function plusgrandque(byval i, ByVal j)
' returns boolean true if i>j, boolean false otherwise
' data verification
If isnumeric(i) And isnumeric(j) Then
If i>j Then
plusgrandque=true
Else
plusgrandque=false
End If
Else
wscript.echo "Arguments (" & i & "," & j & ") erronés"
plusgrandque=false
End If
Exit Function
End Function
Function rendUnTableau(byval n)
' makes an array of n elements
tableau=array()
' check validity of parameter n
If isnumeric(n) And n>=1 Then
ReDim Preserve tableau(n)
For i= 0 To n-1
tableau(i)=i
Next
Else
wscript.echo "Argument [" & n & "] erroné"
End If
' we return the result
rendUnTableau=tableau
End Function
Function argumentsVariables(byref arguments)
' arguments is an array of numbers whose sum is returned
somme=0
For i=0 To ubound(arguments)
somme=somme+arguments(i)
Next
argumentsVariables=somme
End Function
' two parameter-free functions declared in 2 different ways
Function sansParametres1
sansParametres=4
End Function
Function sansParametres2()
sansParametres=4
End Function
' ------------- calls to functions and procedures
' calls function plusgrandque
wscript.echo "plusgrandque(10,6)=" & plusgrandque(10,6)
wscript.echo "plusgrandque(6,10)=" & plusgrandque(6,10)
wscript.echo "plusgrandque(6,6)=" & plusgrandque(6,6)
wscript.echo "plusgrandque(6,'a')=" & plusgrandque(6,"a")
' calls to the rendUnTableau function
monTableau=rendUnTableau(10)
For i=0 To ubound(monTableau)
wscript.echo monTableau(i)
Next
monTableau=rendUnTableau(-6)
For i=0 To ubound(monTableau)
wscript.echo monTableau(i)
Next
' calls to the argumentsVariables function
wscript.echo "somme=" & argumentsVariables(array(-1,2,7,8))
wscript.echo "somme=" & argumentsVariables(array(-1,10,12))
' function calls without parameters
res=sansParametres1
res=sansParametres1()
sansParametres1
sansParametres1()
res=sansParametres2
res=sansParametres2()
sansParametres2
sansParametres2()
' end
wscript.quit 0
Risultati
plusgrandque(10,6)=Vrai
plusgrandque(6,10)=Faux
plusgrandque(6,6)=Faux
Arguments (6,a) erronés
plusgrandque(6,'a')=Faux
0
1
2
3
4
5
6
7
8
9
Argument [-6] erroné
somme=16
somme=21
somme=10
Commenti
- La funzione `rendUnTableau` dimostra che una funzione può restituire più risultati anziché uno solo. È sufficiente inserirli in una variante array e restituire tale variante come risultato.
- Al contrario, la funzione `argumentsVariables` dimostra che è possibile scrivere una funzione che accetta un numero variabile di argomenti. Anche in questo caso, è sufficiente inserirli in una variante array e rendere questa variante un parametro della funzione.
5.3.5. Parametro di output o risultato della funzione
Supponiamo che l'analisi di un'applicazione abbia evidenziato la necessità di un modulo M con parametri di input Ei e parametri di output Sj. Ricordiamo che i parametri di input sono informazioni che il programma chiamante fornisce al programma chiamato e, viceversa, i parametri di output sono informazioni che il programma chiamato fornisce al programma chiamante. In VBScript, esistono diverse soluzioni per i parametri di output:
- Se c'è un solo parametro di output, questo può essere reso il risultato di una funzione. In tal caso non si ha più un parametro di output, ma semplicemente un risultato della funzione.
- Se ci sono n parametri di output, uno di essi può fungere da risultato della funzione, mentre i restanti n-1 fungono da parametri di output. In alternativa, invece di una funzione, si può utilizzare una procedura con n parametri di output. Si può anche utilizzare una funzione che restituisce un array contenente i n valori da restituire al programma chiamante. Si ricordi che il programma chiamato restituisce i propri risultati al programma chiamante per valore. Questa copia viene evitata quando i parametri di output vengono passati per riferimento. Quest'ultima soluzione consente quindi di risparmiare tempo.
5.4. Il programma VBScript per l'ordinamento dei valori
Abbiamo iniziato la nostra discussione sulla programmazione modulare con uno studio algoritmico dell'ordinamento dei valori numerici immessi tramite la tastiera. Ecco l'implementazione VBScript che potrebbe essere utilizzata:
Programma
' main program
Option Explicit
Dim T ' the table of values to be sorted
' reading values
T=lire_tableau
' value sorting
trier_tableau T
' display of sorted values
ecrire_tableau T
' end
wscript.quit 0
' ---------- functions & procedures
' -------- lire_tableau
Function lire_tableau
' values are requested
wscript.stdout.write "Tapez les valeurs à trier sous la forme val1 val2 ... valn : "
' we read them
Dim valeurs
valeurs=wscript.stdin.readLine
' we put them in a table
lire_tableau=split(valeurs," ")
End Function
' -------- ecrire_tableau
Sub ecrire_tableau(byref T)
' displays the contents of table T
wscript.echo join(T," ")
End Sub
' -------- trier_tableau
Sub trier_tableau (byref T)
' sorts array T in ascending order
' find the imax index of the T[0..ifin] array
' to exchange T[imax] with the last element of array T[0..ifin]
' then start again with an array with 1 fewer element
Dim ifin, imax, temp
For ifin=ubound(T) To 1 Step -1
' find the imax index of the T[0..ifin] array
imax=chercher_max(T,ifin)
' we exchange the max with the last element of array T[0..ifin]
temp=T(ifin):T(ifin)=T(imax):T(imax)=temp
Next
End Sub
' -------- chercher_max
Function chercher_max(byRef T, ByVal ifin)
' find the imax index of the T[0..ifin] array
Dim i, imax
imax=0
For i=1 To ifin
If cdbl(T(i))>cdbl(T(imax)) Then imax=i
Next
' We return the result
chercher_max=imax
End Function
Risultati
Commenti:
- Il modulo swap identificato nell'algoritmo iniziale non è stato implementato qui come modulo VBScript perché ritenuto troppo semplice per giustificare un modulo separato.
5.5. Il programma TAX in forma modulare
Rivisitiamo il programma di calcolo delle imposte, questa volta scritto in forma modulare
Programma
' calculating a taxpayer's tax liability
' the program must be called with three parameters: married children salary
' married: character Y if married, N if unmarried
' children: number of children
' salary: annual salary without cents
' mandatory variable declaration
Option Explicit
Dim erreur
' retrieve arguments and check their validity
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' mistake?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)
' retrieve the data needed to calculate taxes
Dim limites, coeffR, coeffN
getData limites,coeffR,coeffN
' the result is displayed
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)
' leave without error
wscript.quit 0
' ------------ functions and procedures
' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
' must retrieve three values passed as arguments to the main program
' an argument is passed to the program without spaces in front and behind it
' use regular expressions to check data validity
' returns an error array variant with 2 values
' error(0): error code, 0 if no error
' error(1): error message if error otherwise empty string
Dim syntaxe
syntaxe= _
"Syntaxe : pg marié enfants salaire" & vbCRLF & _
"marié : caractère O si marié, N si non marié" & vbCRLF & _
"enfants : nombre d'enfants (entier >=0)" & vbCRLF & _
"salaire : salaire annuel sans les centimes (entier >=0)"
' we check that there are 3 arguments
Dim nbArguments
nbArguments=wscript.arguments.count
If nbArguments<>3 Then
' error msg
getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
' end
Exit Function
End If
Dim modele, correspondances
Set modele=new regexp
' marital status must be among the characters oOnN
modele.pattern="^[oOnN]$"
Set correspondances=modele.execute(wscript.arguments(0))
If correspondances.count=0 Then
' error msg
getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
' we leave
Exit Function
End If
' the value
If lcase(wscript.arguments(0)) = "o"Then
marie=true
Else
marie=false
End If
' children must be an integer >=0
modele.pattern="^\d{1,2}$"
Set correspondances=modele.execute(wscript.arguments(1))
If correspondances.count=0 Then
' error
getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
' we leave
Exit Function
End If
' the value
enfants=cint(wscript.arguments(1))
' salary must be an integer >=0
modele.pattern="^\d{1,9}$"
Set correspondances=modele.execute(wscript.arguments(2))
If correspondances.count=0 Then
' error
getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
' we leave
Exit Function
End If
' the value
salaire=clng(wscript.arguments(2))
' finished without error
getArguments=array(0,"")
End Function
' ----------- getData
Sub getData(byref limites, ByRef coeffR, ByRef coeffN)
' we define the data needed to calculate the tax in 3 tables
limites=array(12620,13190,15640,24740,31810,39970,48360, _
55790,92970,127860,151250,172040,195000,0)
coeffr=array(0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45, _
0.5,0.55,0.6,0.65)
coeffn=array(0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5, _
12106,16754.5,23147.5,30710,39312,49062)
End Sub
' ----------- calculerImpot
Function calculerImpot(byval marie,ByVal enfants,ByVal salaire, ByRef limites, ByRef coeffR, ByRef coeffN)
' the number of shares is calculated
Dim nbParts
If marie=true Then
nbParts=(enfants/2)+2
Else
nbParts=(enfants/2)+1
End If
If enfants>=3 Then nbParts=nbParts+0.5
' we calculate the family quotient and taxable income
Dim revenu, qf
revenu=0.72*salaire
qf=revenu/nbParts
' tax calculation
Dim i, impot
i=0
Do While i<ubound(limites) And qf>limites(i)
i=i+1
Loop
calculerImpot=int(revenu*coeffr(i)-nbParts*coeffn(i))
End Function
Commenti
- La funzione getArguments recupera le informazioni del contribuente (coniuge, figli, stipendio). Qui, vengono passate come argomenti al programma VBScript. Se ciò dovesse cambiare, ad esempio se questi argomenti provenissero da un'interfaccia utente grafica, sarebbe necessario riscrivere solo la procedura getArguments, non le altre.
- La funzione getArguments è in grado di rilevare errori negli argomenti. Quando ciò accade, si potrebbe decidere di interrompere l'esecuzione del programma all'interno della funzione getArguments utilizzando un'istruzione wscript.quit. Ciò non dovrebbe mai essere fatto all'interno di una funzione o di una procedura. Se una funzione o una procedura rileva un errore, deve segnalarlo in qualche modo al programma chiamante. Spetta al programma chiamante decidere se interrompere o meno l'esecuzione, non alla procedura. Nel nostro esempio, il programma chiamante potrebbe decidere di chiedere all'utente di reinserire i dati errati tramite la tastiera piuttosto che interrompere l'esecuzione.
- Qui, la funzione getArguments restituisce un array variant in cui il primo elemento è un codice di errore (0 se non c'è errore) e il secondo è un messaggio di errore se si è verificato un errore. Controllando il risultato restituito, il programma chiamante può determinare se si è verificato un errore o meno.
- La procedura getData recupera i dati necessari per calcolare l'imposta. In questo caso, questi dati sono definiti direttamente all'interno della procedura getData. Se questi dati provenissero da un'altra fonte, come un file o un database, sarebbe necessario riscrivere solo la procedura getData, non le altre.
- La funzione `calculerImpot` calcola l'imposta una volta ottenuti tutti i dati, indipendentemente da come sono stati ottenuti.
- Si noti, quindi, che la programmazione modulare consente il (ri)utilizzo di determinati moduli in contesti diversi. Questo concetto è stato ampiamente sviluppato negli ultimi vent'anni nell'ambito del concetto di oggetti.







