Skip to content

4. Error Handling

In programming, there is one absolute rule: a program must never "crash" unexpectedly. All errors that may occur during program execution must be handled, and meaningful error messages must be generated.

If we return to the tax example discussed earlier, what happens if the user enters any value for the number of children? Let’s look at this example:

1
2
3
C:\>cscript impots1.vbs o xyzt 200000

C:\impots1.vbs(33, 3) Erreur d'exécution Microsoft VBScript: Type incompatible: 'cint'

This is what is known as a wild crash. The instruction enfants=cint(wscript.arguments(1)) caused a "crash" because arguments(1) contained the string "xyzt".

Before using a variant whose exact nature is unknown, you must verify its exact subtype. There are several ways to do this:

  • test the actual type of the data contained in a variant using the vartype or typename functions
  • use a regular expression to verify that the variant’s content matches a specific pattern
  • allow the error to occur, then intercept it and handle it

We will examine these different methods.

4.1. Determining the exact type of a data item

Remember that the vartype and varname functions let you determine the exact type of a piece of data. This isn’t always very helpful. For example, when we read data typed on the keyboard, the vartype and typename functions will tell us that it is a string, since all data typed on the keyboard is treated as such. This does not tell us whether this string can, for example, be considered a valid number. We therefore use other functions to access this type of information:

isNumeric(expression)
returns true if expression can be used as a number
isDate(expression)
returns true if expression can be used as a date
isEmpty(var)
returns true if the variable var has not been initialized
isNull(var)
returns true if the variable var contains invalid data
isArray(var)
returns true if var is an array
isObject(var)
returns true if var is an object

The following example prompts the user to enter data via the keyboard until it is recognized as a number:

Program

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre : "
    ' we read it
    nombre=wscript.stdin.readLine
    ' the type is necessarily string when read
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' test the actual type of data read
    If isNumeric(nombre) Then
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' confirmation
wscript.echo "Merci pour le nombre " & nombre

' and end
wscript.quit 0

Results

1
2
3
4
5
6
Tapez un nombre : a
Type de la donnée lue : String,8
Erreur, vous n'avez pas tapé un nombre. Recommencez svp...
Tapez un nombre : -12
Type de la donnée lue : String,8
Merci pour le nombre -12

The isNumeric function does not tell us whether an expression is an integer or not. To obtain this information, additional tests are required. The following example requests an integer greater than 0:

Program

' read data until it is recognized as an integer >0

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the actual type of data read
    If isNumeric(nombre) Then
        ' is it a positive integer (number equal to its integer part)?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' and end
wscript.quit 0

Results

1
2
3
4
5
6
7
8
Tapez un nombre entier >0: a
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -1
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 10.6
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 12
Merci pour le nombre entier >0 : 12

Comments:

  • int(number) returns the integer part of a number. A number equal to its integer part is an integer.
  • It is interesting to note that we had to use the test If (number - int(number)) = 0 And number > 0 because the test If number = int(number) And number > 0 did not yield the expected results. It did not detect positive integers. We leave it to the reader to discover why.
  • The test If (number - int(number)) = 0 is not entirely reliable. Let’s look at the following example:

Enter an integer >0: 4.0000000000000000000000001
 
Thank you for the integer >0: 4.0000000000000000000000001

Real numbers are not represented exactly but approximately. And here, the operation number-int(number) returned 0 to the precision of the computer.

4.2. Regular expressions

Regular expressions allow us to test the format of a string. This way, we can verify that a string representing a date is in the dd/mm/yy format. To do this, we use a pattern and compare the string to that pattern. Thus, in this example, d, m, and y must be digits. The pattern for a valid date format is then "\d\d/\d\d/\d\d", where the symbol \d denotes a digit. The symbols that can be used in a pattern are as follows (Microsoft documentation):

Character
Description
\
Designates the following character as a special character or literal. For example, "n" corresponds to the character "n". "\n" corresponds to a newline character. The sequence "\\" corresponds to "\", while "\(" corresponds to "(".
^
Matches the start of the input.
$
Matches the end of the input.
*
Matches the preceding character zero or more times. Thus, "zo*" matches "z" or "zoo".
+
Matches the preceding character one or more times. Thus, "zo+" matches "zoo", but not "z".
?
Matches the preceding character zero or one time. For example, "a?ve?" matches "ve" in "lever".
.
Matches any single character, except the newline character.
(pattern)
Searches for the pattern and stores the match. The matching substring can be retrieved from the resulting Matches collection using Item [0]...[n]. To find matches with characters inside parentheses ( ), use "\(" or "\)".
x|y
Matches either x or y. For example, "z|foot" matches "z" or "foot". "(z|f)oo" matches "zoo" or "foo".
{n}
n is a non-negative integer. Matches exactly n occurrences of the character. For example, "o{2}" does not match "o" in "Bob," but matches the first two "o"s in "fooooot".
{n,}
n is a non-negative integer. Matches at least n occurrences of the character. For example, "o{2,}" does not match "o" in "Bob," but matches all "o"s in "fooooot." "o{1,}" is equivalent to "o+" and "o{0,}" is equivalent to "o*".
{n,m}
m and n are non-negative integers. Matches at least n and at most m occurrences of the character. For example, "o{1,3}" matches the first three "o"s in "foooooot", and "o{0,1}" matches "o?".
[xyz]
Character set. Matches any of the specified characters. For example, "[abc]" matches "a" in "plat".
[^xyz]
Negative character set. Matches any character not listed. For example, "[^abc]" matches "p" in "plat".
[a-z]
Character range. Matches any character in the specified range. For example, "[a-z]" matches any lowercase alphabetical character between "a" and "z".
[^m-z]
Negative character range. Matches any character not in the specified range. For example, "[^m-z]" matches any character not between "m" and "z".
\b
Matches a word boundary, that is, the position between a word and a space. For example, "er\b" matches "er" in "lever," but not "er" in "verb."
\B
Matches a boundary that does not represent a word. "en*t\B" matches "ent" in "bien entendu".
\d
Matches a character representing a digit. Equivalent to [0-9].
\D
Matches a character that is not a digit. Equivalent to [^0-9].
\f
Matches a line break character.
\n
Matches a newline character.
\r
Equivalent to a carriage return character.
\s
Matches any whitespace, including space, tab, page break, etc. Equivalent to "[ \f\n\r\t\v]".
\S
Matches any non-whitespace character. Equivalent to "[^ \f\n\r\t\v]".
\t
Matches a tab character.
\v
Matches a vertical tab character.
\w
Matches any character representing a word and including an underscore. Equivalent to "[A-Za-z0-9_]".
\W
Matches any character that does not represent a word. Equivalent to "[^A-Za-z0-9_]".
\num
Matches num, where num is a positive integer. Refers to stored matches. For example, "(.)\1" matches two consecutive identical characters.
\n
Matches n, where n is an octal escape value. Octal escape values must consist of 1, 2, or 3 digits. For example, "\11" and "\011" both match a tab character. "\0011" is equivalent to "\001" & "1". Octal escape values must not exceed 256. If they do, only the first two digits are taken into account in the expression. Allows ASCII codes to be used in regular expressions.
\xn
Corresponds to n, where n is a hexadecimal escape value. Hexadecimal escape values must consist of exactly two digits. For example, "\x41" corresponds to "A". "\x041" is equivalent to "\x04" & "1". Allows the use of ASCII codes in regular expressions.

An element in a pattern may appear once or multiple times. Let’s look at a few examples involving the \d symbol, which represents a single digit:

pattern
meaning
\d
a digit
\d?
0 or 1 digit
\d*
0 or more digits
\d+
1 or more digits
\d{2}
2 digits
\d{3,}
at least 3 digits
\d{5,7}
between 5 and 7 digits

Now let’s imagine a model capable of describing the expected format for a string:

target string
pattern
a date in dd/mm/yy format
\d{2}/\d{2}/\d{2}
a time in hh:mm:ss format
\d{2}:\d{2}:\d{2}
an unsigned integer
\d+
a sequence of spaces, which may be empty
\s*
an unsigned integer that may be preceded or followed by spaces
\s*\d+\s*
an integer that may be signed and preceded or followed by spaces
\s*[+|-]?\s*\d+\s*
an unsigned real number that may be preceded or followed by spaces
\s*\d+(.\d*)?\s*
a real number that may be signed and preceded or followed by spaces
\s*[+|]?\s*\d+(.\d*)?\s*
a string containing the word "just"
\bjuste\b
  

You can specify where to search for the pattern in the string:

pattern
meaning
^pattern
the pattern starts the string
pattern$
the pattern ends the string
^pattern$
the pattern starts and ends the string
pattern
the pattern is searched for anywhere in the string, starting from the beginning.
search string
pattern
a string ending with an exclamation point
!$
a string ending with a period
\.$
a string beginning with the sequence //
^//
a string consisting of a single word, optionally preceded or followed by spaces
^\s*\w+\s*$
a string consisting of two words, optionally followed or preceded by spaces
^\s*\w+\s*\w+\s*$
a string containing the word secret
\bsecret\b

Sub-patterns of a pattern can be "extracted." Thus, not only can we verify that a string matches a particular pattern, but we can also extract from that string the elements corresponding to the sub-patterns of the pattern that have been enclosed in parentheses. For example, if we are parsing a string containing a date in the format dd/mm/yy and want to extract the dd, mm, and yy components of that date, we would use the pattern (\d\d)/(\d\d)/(\d\d).

Let’s look at this example to see how to do this with VBScript.

  • First, we need to create a RegExp (Regular Expression) object
set modele=new regexp
  • Then we set the pattern to be tested
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • You may want to ignore case (by default, it is case-sensitive). Here, it doesn’t matter.
modele.IgnoreCase=true
  • You may want to search for the pattern multiple times in the string (by default, this is not done)
modele.Global=true

A global search only makes sense if the pattern used does not refer to the beginning or end of the string.

  • We then search for all matches of the pattern in the string:
set correspondances=modele.execute(chaine)

The execute method of a RegExp object returns a collection of match objects. This object has a value property that is the string element matching the pattern. If you have set pattern.global=true, there may be multiple matches. This is why the result of the execute method is a collection of matches.

  • The number of matches is given by matches.count. If this number is 0, it means the pattern was not found anywhere. The value of match #i is given by matches(i).value. If the pattern contains subpatterns in parentheses, then the element of matches(i) corresponding to parenthesis j in the pattern is matches(i).submatches(j).

All of this is shown in the following example:

Program

' regular expression

' we want to check that a string contains a date in dd/mm/yy format

Option Explicit
Dim modele

' we define the
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b"  ' a date anywhere in the chain
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

chaine=""
' loop as long as string<>"end"
Do While true
    ' the user is asked to type a text
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
    ' fini si chaine=fin
    If chaine="fin" Then Exit Do
    ' the string read is compared with the date template
    Set correspondances=modele.execute(chaine)
    ' was a match found
    If correspondances.count<>0 Then
        ' we have at least one match
        For i=0 To correspondances.count-1
            ' the i correspondence is displayed
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' we retrieve the sub-elements of correspondence i
            wscript.echo "Les éléments de la date " & i & " sont (" & correspondances(i).submatches(0) & "," _
            & correspondances(i).submatches(1) & "," & correspondances(i).submatches(2) & ")"
        Next
    Else
        ' no correspondence
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' finish
wscript.quit 0

Results

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
aujourd'hui on est le 01/01/01 et demain sera le 02/01/02
J'ai trouvé la date 01/01/01
Les éléments de la date 0 sont (01,01,01)
J'ai trouvé la date 02/01/02
Les éléments de la date 1 sont (02,01,02)

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
une date au format incorrect : 01/01/2002
Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
une suite de dates : 10/10/10, 11/11/11, 12/12/12
J'ai trouvé la date 10/10/10
Les éléments de la date 0 sont (10,10,10)
J'ai trouvé la date 11/11/11
Les éléments de la date 1 sont (11,11,11)
J'ai trouvé la date 12/12/12
Les éléments de la date 2 sont (12,12,12)

Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrÛter :
fin

Using regular expressions, the program that checks whether a keyboard input is indeed a positive integer could be written as follows:

Program

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' we define the model of a positive integer (which may be zero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the format of the data read
    Dim correspondances
    Set correspondances=modele.execute(nombre)
    ' has the model been checked?
    If correspondances.count<>0 Then
        ' it's an integer, but is it >0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' and end
wscript.quit 0

Results

Tapez un nombre entier >0: 10.3
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: abcd
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -4
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 0
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 1
Merci pour le nombre entier >0 : 1

Finding the regular expression that allows us to verify whether a string matches a certain pattern can sometimes be a real challenge. The following program lets you practice. It asks for a pattern and a string, and then indicates whether or not the string matches the pattern.

Program

' regular expression

' we want to check that a chain corresponds to a model

Option Explicit

' we define the
Dim modele
Set modele=new regexp
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

Do While true
    ' the user is asked to type in a template
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' finished?
    If modele.pattern="fin" Then Exit Do
        ' the user is asked for the strings to be compared with the model
        Do While true
            ' the user is asked to type in a template
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
            ' finished?
            If chaine="fin" Then Exit Do
            ' the string read is compared with the date template
            Set correspondances=modele.execute(chaine)
            ' was a match found
            If correspondances.count<>0 Then
                ' we have at least one match
                For i=0 To correspondances.count-1
                    ' the i correspondence is displayed
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                ' no correspondence
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' finish
wscript.quit 0

Results

Tapez le modèle à tester et fin pour arrêter : ^\s*\d+(\,\d+)*\s*$

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
18
J'ai trouvé la correspondance [18]

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
145.678
Je n'ai pas trouvé de correspondance

Tapez la chaîne à tester avec le modèle [^\s*\d+(\,\d+)*\s*$] et fin pour arrêter :
145,678
J'ai trouvé la correspondance [  145,678   ]

4.3. Handling runtime errors

Another method for handling runtime errors is to let them occur, be notified of them, and then handle them. Normally, when an error occurs at runtime, WSH displays an error message and the program stops. Two statements allow us to change this behavior:

on error resume next

This statement tells the system (WSH) that we will handle errors ourselves. After this statement, any errors are simply ignored by the system.

on error goto 0

This statement returns us to normal error handling.

When the on error resume next statement is active, we must handle any errors that may occur ourselves. The Err object helps us do this. This object has various properties and methods, of which we will focus on the following two:

  • number: an integer representing the number of the last error that occurred. 0 means "no error"
  • description: the error message the system would have displayed if we hadn’t issued the on error resume next statement

Let’s look at the following example:

Program


' unhandled error
 
Option Explicit
Dim nombre
 
nombre=cdbl("abcd")
wscript.echo "nombre=" & nombre

Results

C:\ err5.vbs(6, 1) Erreur d'exécution Microsoft VBScript: Type incompatible: 'cdbl'

Now let's handle the error:

Program

' managed error

Option Explicit
Dim nombre

' we manage mistakes ourselves
On Error Resume Next
nombre=cdbl("abcd")
' was there a mistake?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' no error - returns to normal operation
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0

Results

L'erreur [Type incompatible] s'est produite

Let's rewrite the program for entering an integer >0 using this new method:

Program


' read data until it is recognized as a number
 
Option Explicit
 
Dim fini, nombre
 
' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)
 
fini=false
Do While Not fini
  ' we ask for the number
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' we read it
  nombre=wscript.stdin.readLine
  ' test the format of the data read
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' no error it's a number
    ' returns to normal error handling mode
    On Error GoTo 0
    ' is it an integer >0
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' returns to normal error handling mode
  On Error GoTo 0
  ' possible error msg
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop
 
' confirmation
wscript.echo "Merci pour le nombre entier >0 : " & nombre
 
' and end
wscript.quit 0

Results

Tapez un nombre entier >0: 4.5
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 4,5
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: abcd
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: -4
Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp...
Tapez un nombre entier >0: 1
Merci pour le nombre entier >0 : 1

Comments:

  • This method is sometimes the only one that can be used. In that case, do not forget to return to normal error handling mode as soon as the sequence of instructions likely to generate the error is complete.

4.4. Application to the tax calculation program

We’ll revisit the tax calculation program we wrote earlier to, this time, verify the validity of the arguments passed to the program:

Program


' 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
 
' no verification of data validity is performed, but we do
' check that there are three of them
 
' mandatory variable declaration
Option Explicit
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
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' stop with error code 1
    wscript.quit 1
  End If

' retrieve arguments and check their validity
' an argument is passed to the program without spaces in front and behind it
' use regular expressions to check data validity
  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
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' we leave
    wscript.quit 2
  End If
  ' the value
  Dim marie
  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
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' we leave
    wscript.quit 3
  End If
  ' the value
  Dim enfants
  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
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' we leave
    wscript.quit 4
  End If
  ' the value
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' we define the data needed to calculate the tax in 3 tables
  Dim limites, coeffn, coeffr
  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)

  ' 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

  ' calculate the family quota 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
  impot=int(revenu*coeffr(i)-nbParts*coeffn(i))

  ' the result is displayed
  wscript.echo "impôt=" & impot

  ' leave without error
  wscript.quit 0

Results

C:\>cscript impots2.vbs

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : nombre d'arguments incorrect

C:\>cscript impots2.vbs a b c

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument marie incorrect


C:\>cscript impots2.vbs o b c

Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument enfants incorrect

C:\>cscript impots2.vbs o 2 c


Syntaxe : pg marié enfants salaire
marié : caractère O si marié, N si non marié
enfants : nombre d'enfants (entier >=0)
salaire : salaire annuel sans les centimes (entier >=0)

erreur : argument salaire incorrect

C:\>cscript impots2.vbs o 2 200000

impôt=22504