Skip to content

5. Funkcje i procedury

5.1. Wbudowane funkcje języka VBScript

Bogactwo języka wynika w dużej mierze z biblioteki funkcji, które mogą być enkapsulowane w obiektach pod nazwą metod. Pod tym względem można uznać, że VBScript jest raczej ubogi.

Poniższa tabela przedstawia funkcje VBScript poza obiektami. Nie będziemy ich szczegółowo omawiać. Ich nazwy zazwyczaj wskazują na ich przeznaczenie. Czytelnik powinien zapoznać się z dokumentacją, aby uzyskać szczegółowe informacje na temat konkretnej funkcji.

Abs
Array
Asc
Atn
CBool
CByte
CCur
CDate
CDbl
Chr
CInt
CLng
Konwersje
Cos
CreateObject
CSng
Data
DateAdd
DateDiff
DatePart
DateSerial
DateValue
Dzień
Matematyka pochodna
Ocena
Wykładnik
Filtr
FormatCurrency
FormatDateTime
FormatNumber
FormatPercent
GetLocale
GetObject
GetRef
Hex
Godzina
InputBox
InStr
InStrRev
Międzynarodowe, Stałe
IsArray
IsDate
IsEmpty
IsNull
IsNumeric
IsObject
Dołącz
LBound
LCase
W lewo
Len
LoadPicture
Log
LTrim; RTrim; oraz wykończenia
Matematyka
Średnia
Minuta
Miesiąc
MonthName
MsgBox
Teraz
Październik
Zastąp
RGB
Right
Rnd
Okrągły
ScriptEngine
ScriptEngineBuildVersion
ScriptEngineMajorVersion
ScriptEngineMinorVersion
Drugi
SetLocale
Sgn
Sin
Spacja
Split
Sqr
StrComp
String
Tan
Czas
Timer
TimeSerial
TimeValue
TypeName
UBound
UCase
VarType
Dzień tygodnia
WeekdayName
Rok

5.2. Programowanie modułowe

Opisanie zaprogramowanego rozwiązania problemu oznacza opisanie sekwencji podstawowych czynności, które może wykonać komputer i które pozwalają rozwiązać ten problem. W zależności od języka programowania te podstawowe operacje są mniej lub bardziej złożone. Można tu wymienić na przykład:

  • odczyt danych z klawiatury lub dysku
  • zapis danych na ekranie, na drukarce, na dysku itp.
  • obliczanie wyrażeń
  • poruszanie się po pliku
  • ...

Opisanie złożonego problemu może wymagać kilku tysięcy takich podstawowych instrukcji, a nawet więcej. W takiej sytuacji bardzo trudno jest ludzkiemu umysłowi uzyskać całościowy obraz programu. W obliczu tej trudności w ogarnięciu problemu w całości, dzielimy go na podproblemy, które łatwiej rozwiązać. Rozważmy następujący problem: posortowanie listy wartości liczbowych wpisanych z klawiatury i wyświetlenie posortowanej listy na ekranie.

W pierwszej kolejności rozwiązanie można opisać w następującej postaci:

  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

Problem podzielono na trzy podproblemy, które są łatwiejsze do rozwiązania. Zapis algorytmiczny jest często bardziej sformalizowany niż poprzedni, a algorytm będzie wyglądał raczej następująco:

   début
         lire_tableau(T)
         trier_tableau(T)
         écrire_tableau(T)
   fin

gdzie T oznacza tablicę. Operacje

    . lire_tableau(T)
    . trier_tableau(T)
    . écrire_tableau(T)

są operacjami nieelementarnymi, które z kolei muszą być opisane za pomocą operacji elementarnych. Odbywa się to w tak zwanych modułach. Dane T nazywane są parametrem modułu. Jest to informacja, którą program wywołujący przekazuje do modułu wywoływanego (parametr wejściowy) lub otrzymuje od modułu wywoływanego (parametr wyjściowy). Parametry modułu to zatem informacje wymieniane między programem wywołującym a modułem wywoływanym.

moduł lire_tableau(T)
moduł trier_tableau(T)
moduł écrire_tableau(T)

Moduł lire_tableau(T) można opisać w następujący sposób:


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

W tym miejscu wystarczająco szczegółowo opisaliśmy moduł lire_tableau. Trzy niezbędne czynności mają bowiem bezpośredni odpowiednik w języku VBScript. Ostatnia z nich będzie wymagała użycia funkcji split. Gdyby język VBScript nie posiadał tej funkcji, czynność 3 musiałaby zostać z kolei podzielona na podstawowe czynności, które mają bezpośredni odpowiednik w języku VBScript.

Moduł écrire_tableau(T) można opisać w następujący sposób:


début
    construire chaîne texte "valeur1,valeur2,...." à partir du tableau T
    écrire texte
fin

Moduł écrire_tableau(T) można opisać w następujący sposób (zakładając, że indeksy elementów T zaczynają się od 0):

début
      N<-- indice dernier élément du tableau T
      pour IFIN variant de N à 1
      faire
           //szukamy indeksu IMAX największego elementu z T
           // IFIN to indeks ostatniego elementu T

          chercher_max(T, IFIN, IMAX) 

           // zamieniamy największy element z T na ostatni element z T

          échanger (T, IMAX, IFIN)

      finfaire
FIN

W tym miejscu algorytm ponownie wykorzystuje operacje nieelementarne:


 . chercher_max(T, IFIN, IMAX)
 . échanger(T, IMAX, IFIN)

chercher_max(T, IFIN, IMAX) zwraca indeks IMAX największego elementu tablicy T, której indeks ostatniego elementu wynosi IFIN.

zamień(T, IMAX, IFIN) zamienia dwa elementy tablicy T o indeksach IMAX i IFIN.

Należy zatem opisać nowe operacje nieelementarne.

moduł chercher_max(A, IFIN, IMAX)
   début
        IMAX<--0

        pour i variant de 1 à IFIN
        faire
           si T[i]>T[IMAX] alors 
             début
                IMAX<--i
             fin
        finfaire
    fin
moduł wymiany (T IMAX, IFIN)
  début
       temp<----T[IMAX]
       T[IMAX]<---T[IFIN]
       T[IFIN]<---temp
  fin

Pierwotny problem został w pełni opisany za pomocą podstawowych operacji języka VBScript i może zatem zostać przetłumaczony na ten język. Należy zauważyć, że podstawowe operacje mogą się różnić w zależności od języka programowania, dlatego analiza problemu musi w pewnym momencie uwzględniać używany język. Obiekt istniejący w jednym języku może nie istnieć w innym, co w konsekwencji może wpłynąć na zastosowany algorytm. Tak więc, gdyby dany język posiadał funkcję sortowania, nie wykorzystanie jej w tym przypadku byłoby absurdalne.

Zastosowana tutaj zasada to tzw. analiza z góry na dół. Jeśli przedstawimy szkielet rozwiązania, otrzymamy następujący obraz:

Mamy strukturę drzewa.

5.3. Funkcje i procedury VBScript

Po przeprowadzeniu analizy modułowej programista może przełożyć moduły swojego algorytmu na kod VBScript, np. fonctions lub procédures. Zarówno fonctions, jak i procédures akceptują parametry wejściowe/wyjściowe, ale fonction zwraca wynik, który pozwala na wykorzystanie go w wyrażeniach, podczas gdy procédure takiego wyniku nie zwraca.

5.3.1. Deklaracja funkcji i procedur w VBScript

Deklaracja procedury VBScript wygląda następująco

sub nomProcédure([Byref/Byval] param1, [Byref/Byval] param2, ...)
    instructions
end sub

a deklaracja funkcji wygląda następująco

function nomFonction([Byref/Byval] param1, [Byref/Byval] param2, ...)
    instructions
end sub

Aby zwrócić wynik, funkcja musi zawierać instrukcję przypisania wyniku do zmiennej o nazwie funkcji:

nazwa_funkcji = wynik

Wykonanie funkcji lub procedury kończy się na dwa sposoby:

  1. po napotkaniu instrukcji zakończenia funkcji (end function) lub zakończenia procedury (end sub)
  2. po napotkaniu instrukcji wyjścia z funkcji (exit function) lub procedury (exit sub)

W przypadku funkcji należy pamiętać, że wynik musi zostać przypisany do zmiennej o nazwie funkcji, zanim funkcja zakończy się instrukcją end function lub exit function.

5.3.2. Sposoby przekazywania parametrów funkcji lub procedury

W deklaracji parametrów wejściowych i wyjściowych funkcji lub procedury określa się tryb (byRef, byVal) przekazywania parametru z programu wywołującego do programu wywoływanego:

sub nomProcédure([Byref/Byval] param1, [Byref/Byval] param2, ...)

function nomFonction([Byref/Byval] param1, [Byref/Byval] param2, ...)

Jeśli nie określono trybu przesyłania byRef lub byVal, stosowany jest tryb byRef.

Parametry rzeczywiste, parametry formalne

Niech vbscriptową funkcję zdefiniowano jako

function nomFonction([Byref/Byval] paramForm1, [Byref/Byval] paramForm2, ...)
...
end function

Parametry parmamFormi użyte w definicji funkcji lub procedury nazywane są parametrami formalnymi. Powyższą funkcję można wywołać z programu głównego lub innego modułu za pomocą instrukcji typu:

résultat=nomFonction(paramEff1, paramEff2, ...)

Parametry parmamEffi używane w wywołaniu funkcji lub procedury nazywane są parametrami rzeczywistymi. Gdy rozpoczyna się wykonywanie funkcji nomFonction, parametry formalne przyjmują wartości odpowiadających im parametrów rzeczywistych. Słowa kluczowe byRef i byVal określają tryb przekazywania tych wartości.

Tryb przekazywania wartości (byVal)

Gdy parametr formalny określa ten tryb przekazywania, parametr formalny i parametr rzeczywisty są wówczas dwiema różnymi zmiennymi. Wartość parametru rzeczywistego jest kopiowana do parametru formalnego przed wykonaniem funkcji lub procedury. Jeśli funkcja lub procedura zmieni wartość parametru formalnego w trakcie swojego wykonywania, nie ma to żadnego wpływu na wartość odpowiadającego mu parametru rzeczywistego. Ten tryb przekazywania dobrze nadaje się do parametrów wejściowych funkcji lub procedury.

Tryb przekazywania przez odwołanie (byRef)

Ten tryb przekazywania jest trybem domyślnym, jeśli nie określono żadnego trybu przekazywania parametru. Gdy parametr formalny określa ten tryb przekazywania, parametr formalny i odpowiadający mu parametr rzeczywisty stanowią jedną i tę samą zmienną. Zatem jeśli funkcja modyfikuje parametr formalny, modyfikowany jest również parametr rzeczywisty. Ten tryb przekazywania dobrze nadaje się do:

  • dla parametrów wyjściowych, ponieważ ich wartości muszą zostać przekazane do programu wywołującego
  • dla parametrów wejściowych, których przepisywanie jest uciążliwe, takich jak tabele

Poniższy program przedstawia przykłady przekazywania parametrów:

Program

Sub proc1(byval i, ByRef j, k)
  ' i jest przekazywane przez wartość (byval) – parametr rzeczywisty i parametr formalny są wówczas różne
  ' j jest przekazywane przez wartość (byref) – parametr rzeczywisty i parametr formalny są wówczas identyczne
  ' sposób przekazania k nie jest określony. Domyślnie odbywa się to przez odwołanie
  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)
  ' wyświetla wartości i, j i k
  wscript.echo msg & " i=" & i & " j=" & j & " k=" & k
End Sub


' ------------- wywołania funkcji i procedur

' inicjuje i oraz j
  i=4:j=5 : k=6

' weryfikacja
  affiche "dans programme principal, avant l'appel à proc1 :",i,j,k

' wywołanie procedury proc1
  proc1 i,j,k

' weryfikacja
  affiche "dans programme principal, après l'appel à proc1 :",i,j,k

' koniec
  wscript.quit 0
Wyniki
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

Komentarze

  • W skrypcie VBScript nie ma wyznaczonego miejsca na funkcje i procedury. Mogą one znajdować się w dowolnym miejscu tekstu źródłowego. Zazwyczaj grupuje się je na początku lub na końcu, tak aby główny program stanowił ciągły blok.

5.3.3. Składnia wywoływania funkcji i procedur

Niech procedura p przyjmuje parametry formalne pf1, pf2, ...

  • wywołanie procedury p odbywa się w postaci
p pe1, pe2, ...

bez nawiasów wokół parametrów

  • jeśli procedura p nie przyjmuje żadnych parametrów, można bez różnicy użyć wywołania p lub p() oraz deklaracji sub p lub sub p()

Niech f będzie funkcją przyjmującą parametry formalne pf1, pf2, ...

  • wywołanie funkcji f ma postać
résultat=f(pe1, pe2, ...)

Nawiasy wokół parametrów są obowiązkowe. Jeśli funkcja f nie przyjmuje żadnych parametrów, można bez różnicy użyć wywołania f lub f() oraz deklaracji function f lub function f().

  • Wynik funkcji f może zostać zignorowany przez program wywołujący. Funkcja f jest wówczas traktowana jako procedura i podlega zasadom wywoływania procedur. Aby wywołać funkcję f, pisze się wówczas f pe1, pe2, ... (bez nawiasów).

Jeśli funkcja lub procedura jest metodą obiektu, wydaje się, że zasady są nieco inne i niejednolite.

  • Można więc zapisać MyFile.WriteLine „To jest test.” lub MyFile.WriteLine („To jest test.”)
  • ale choć można zapisać wscript.echo 4, nie można zapisać wscript.echo(4).

Będziemy przestrzegać następujących zasad:

  • nie stosujemy nawiasów wokół parametrów procedury lub funkcji używanej jako procedura
  • nawiasy wokół parametrów funkcji

5.3.4. Kilka przykładów funkcji

Poniżej znajduje się kilka przykładów definicji i zastosowań funkcji:

Program

 Function plusgrandque(byval i, ByVal j)
  ' zwraca wartość logiczną „prawda”, jeśli i > j, w przeciwnym razie „fałsz”

  ' weryfikacja danych
  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)
  ' zwraca tablicę zawierającą n elementów
  tableau=array()
  ' sprawdza poprawność parametru 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
  ' zwraca wynik
  rendUnTableau=tableau
End Function

 Function argumentsVariables(byref arguments)
  ' argumentem jest tablica liczb, z której zwracana jest suma
  somme=0
  For i=0 To ubound(arguments)
    somme=somme+arguments(i)
  Next
  argumentsVariables=somme
End Function

  ' dwie funkcje bez argumentów zadeklarowane na dwa różne sposoby
  Function sansParametres1
    sansParametres=4
  End Function

  Function sansParametres2()
    sansParametres=4
  End Function

  
' ------------- wywołania funkcji i procedur

' wywołania funkcji 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")

' wywołania funkcji rendUnTableau
  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

' wywołania funkcji argumentsVariables
  wscript.echo "somme=" & argumentsVariables(array(-1,2,7,8))
  wscript.echo "somme=" & argumentsVariables(array(-1,10,12))

' wywołania funkcji bez parametrów
  res=sansParametres1
  res=sansParametres1()
  sansParametres1
  sansParametres1()

  res=sansParametres2
  res=sansParametres2()
  sansParametres2
  sansParametres2()

' koniec
  wscript.quit 0
Wyniki
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

Komentarze

  • Funkcja rendUnTableau pokazuje, że funkcja może zwracać wiele wyników, a nie tylko jeden. Wystarczy, że umieści je w wariancie typu tablicowego i zwróci ten wariant jako wynik.
  • Z kolei funkcja argumentsVariables pokazuje, że można napisać funkcję, która przyjmuje zmienną liczbę argumentów. Wystarczy również umieścić je w wariancie tablicowym i uczynić ten wariant parametrem funkcji.

5.3.5. Parametr wyjściowy lub wynik funkcji

Załóżmy, że analiza aplikacji wykazała konieczność zastosowania modułu M z parametrami wejściowymi Ei i parametrami wyjściowymi Sj. Przypomnijmy, że parametry wejściowe to informacje, które program wywołujący przekazuje programowi wywoływanym, a odwrotnie – parametry wyjściowe to informacje, które program wywoływany przekazuje programowi wywołującemu. W języku VBScript istnieje kilka rozwiązań dotyczących parametrów wyjściowych:

  • jeśli istnieje tylko jeden parametr wyjściowy, można uczynić go wynikiem funkcji. Wówczas nie ma już parametru wyjściowego, a jedynie wynik funkcji.
  • jeśli istnieje n parametrów wyjściowych, jeden z nich może pełnić rolę wyniku funkcji, a pozostałe n-1 pozostają parametrami wyjściowymi. Można również zrezygnować z funkcji na rzecz procedury z n parametrami wyjściowymi. Można również użyć funkcji, która zwróci tablicę, w której umieszczono n wartości do przekazania programowi wywołującemu. Należy pamiętać, że wywoływany program zwraca wyniki do programu wywołującego poprzez kopiowanie wartości. W przypadku parametrów wyjściowych przekazywanych przez odwołanie unika się tego kopiowania. W związku z tym to ostatnie rozwiązanie pozwala zaoszczędzić czas.

5.4. Program VBScript do sortowania wartości

Rozpoczęliśmy omówienie programowania modułowego od analizy algorytmicznej sortowania wartości liczbowych wprowadzanych z klawiatury. Oto przykładowy kod VBScript, który można by w tym celu stworzyć:

Program
' program główny
Option Explicit

Dim T        ' le tableau de valeurs à trier

' odczyt wartości
T=lire_tableau

' sortowanie wartości
trier_tableau T

' wyświetlanie posortowanych wartości
ecrire_tableau T

' koniec
wscript.quit 0

' ---------- funkcje i procedury

' -------- lire_tableau
Function lire_tableau
    ' żądanie wartości
    wscript.stdout.write "Tapez les valeurs à trier sous la forme val1 val2  ... valn : "
    ' odczytuje się je
    Dim valeurs
    valeurs=wscript.stdin.readLine
    ' umieszczamy je w tablicy
    lire_tableau=split(valeurs," ")
End Function

' -------- ecrire_tableau
Sub ecrire_tableau(byref T)
    ' wyświetla zawartość tablicy T
    wscript.echo join(T," ")
End Sub

' -------- trier_tableau
Sub trier_tableau (byref T)
    ' sortuje tablicę T w porządku rosnącym

    ' szukamy indeksu imax tablicy T[0..ifin]
    ' w celu zamiany T[imax] z ostatnim elementem tablicy T[0..ifin]
    ' następnie zaczynamy od nowa z tablicą zawierającą o jeden element mniej

    Dim ifin, imax, temp
    For ifin=ubound(T) To 1 Step -1
        ' szukamy indeksu imax tablicy T[0..ifin]
        imax=chercher_max(T,ifin)
        ' zamieniamy element o największym indeksie na ostatni element tablicy 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)
    ' szukamy indeksu imax tablicy T[0..ifin]
    Dim i, imax
    imax=0
    For i=1 To ifin
        If cdbl(T(i))>cdbl(T(imax)) Then imax=i
    Next

    ' Zwracamy wynik
    chercher_max=imax    
End Function
Wyniki
Tapez les valeurs à trier sous la forme val1 val2  ... valn : 10 9 8 7 6 1
1 6 7 8 9 10

Uwagi:

  • moduł échanger, który został zidentyfikowany w początkowym algorytmie, nie został tutaj zaimplementowany jako moduł w języku VBScript, ponieważ uznano go za zbyt prosty, by poświęcać mu osobny moduł.

5.5. Program IMPOTS w formie modułowej

Powracamy do programu do obliczania podatku, tym razem napisanego w formie modułowej

Program
' obliczenie podatku podatnika
' program należy wywołać z trzema parametrami: stan cywilny, liczba dzieci, wynagrodzenie
' stan cywilny: znak O, jeśli jest żonaty, N, jeśli jest kawalerem
' dzieci: liczba dzieci
' wynagrodzenie: roczne wynagrodzenie bez centów

' obowiązkowa deklaracja zmiennych
Option Explicit
Dim erreur

' argumenty są pobierane po sprawdzeniu ich poprawności
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' błąd?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' pobieramy dane niezbędne do obliczenia podatku
Dim limites, coeffR, coeffN
getData limites,coeffR,coeffN

' wyświetlanie wyniku
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

' program kończy działanie bez błędu
wscript.quit 0

' ------------ funkcje i procedury

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' musi pobrać trzy wartości przekazane jako argumenty do programu głównego
    ' argument jest przekazywany do programu bez spacji przed i po nim
    ' do sprawdzenia poprawności danych zostaną użyte wyrażenia regularne

    ' zwraca tablicę błędów zawierającą 2 wartości
    ' błąd(0): kod błędu, 0, jeśli nie ma błędu
    ' błąd(1): komunikat o błędzie, jeśli wystąpił błąd, w przeciwnym razie pusty ciąg znaków

    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)"

    ' sprawdzamy, czy są 3 argumenty
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' komunikat o błędzie
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' koniec
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    ' stan cywilny musi znajdować się wśród znaków oOnN
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' komunikat o błędzie
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        ' kończymy
        Exit Function
    End If
    ' pobieranie wartości
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' liczba dzieci musi być liczbą całkowitą >=0
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' błąd
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        ' kończenie
        Exit Function
    End If
    ' odzyskuje się wartość
    enfants=cint(wscript.arguments(1))

    ' wynagrodzenie musi być liczbą całkowitą >=0
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' błąd
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        ' kończymy
        Exit Function
    End If
    ' pobieramy wartość
    salaire=clng(wscript.arguments(2))

    ' zakończono bez błędu
    getArguments=array(0,"")
End Function

' ----------- getData
Sub getData(byref limites, ByRef coeffR, ByRef coeffN)  
    ' definiujemy dane niezbędne do obliczenia podatku w 3 tabelach
    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)

    ' oblicza się liczbę udziałów
    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

    ' oblicza się współczynnik rodzinny i dochód podlegający opodatkowaniu
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' oblicza się podatek
    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

Komentarze

  • Funkcja getArguments umożliwia pobranie informacji (małżonek, dzieci, wynagrodzenie) o podatniku. W tym przypadku informacje te są przekazywane jako argumenty do programu VBScript. Gdyby sytuacja uległa zmianie, na przykład gdyby argumenty te pochodziły z interfejsu graficznego, konieczna byłaby zmiana wyłącznie procedury getArguments, a nie pozostałych.
  • Funkcja getArguments może wykrywać błędy w argumentach. Gdy tak się stanie, można by zdecydować o zatrzymaniu wykonywania programu w funkcji getArguments za pomocą instrukcji wscript.quit. Nigdy nie należy tego robić w funkcji ani procedurze. Jeśli funkcja lub procedura wykryje błąd, musi w jakiś sposób zgłosić go programowi wywołującemu. To program wywołujący podejmuje decyzję o zatrzymaniu lub kontynuowaniu wykonywania, a nie procedura. W naszym przykładzie program wywołujący mógłby zdecydować się na ponowne poproszenie użytkownika o wprowadzenie błędnych danych z klawiatury zamiast zatrzymywać wykonywanie.
  • W tym przypadku funkcja getArguments zwraca tablicę, której pierwszy element to kod błędu (0, jeśli nie wystąpił błąd), a drugi – komunikat o błędzie, jeśli błąd wystąpił. Sprawdzając uzyskany wynik, program wywołujący może ustalić, czy wystąpił błąd, czy nie.
  • Procedura getData pozwala uzyskać dane niezbędne do obliczenia podatku. W tym przypadku dane te są zdefiniowane bezpośrednio w procedurze getData. Gdyby dane te miały pochodzić z innego źródła, na przykład z pliku lub bazy danych, należałoby przepisać jedynie procedurę getData, a nie pozostałe.
  • Funkcja calculerImpot umożliwia obliczenie podatku po uzyskaniu wszystkich danych, niezależnie od sposobu ich pozyskania.
  • Należy zatem zauważyć, że programowanie modułowe umożliwia (ponowne) wykorzystanie niektórych modułów w różnych kontekstach. Koncepcja ta została w ciągu ostatnich dwudziestu lat znacznie rozwinięta w ramach paradygmatu obiektowego.