Skip to content

4. 错误处理

在编程中有一条铁律:程序绝不能无故“崩溃”。程序运行过程中可能发生的任何错误都必须得到处理,并生成有意义的错误信息。

如果我们回顾之前处理的税款示例,当用户在子女数量字段中输入任意内容时会发生什么?让我们来看这个示例:

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

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

这就是所谓的“意外崩溃”。在语句 <span style="color: #000000">children=cint(wscript.arguments(1)) 处发生了“崩溃”,因为 arguments(1) 包含字符串“xyzt”。

在使用性质不明的变量之前,必须先验证其确切的子类型。可以通过以下几种方式实现:

  • 使用函数 vartype typename 测试变量中数据的实际类型
  • 使用正则表达式验证变量内容是否符合特定模式
  • 允许错误发生,随后进行捕获并处理

我们将探讨这些不同的方法。

4.1. 确定数据的精确类型

需要提醒的是,函数 vartypevarname 可用于确定数据的精确类型。但这并不总能提供实质性帮助。 例如,当我们读取键盘输入的数据时,函数 vartypetypename 会告诉我们这是字符串,因为所有键盘输入的数据都被视为字符串。但这并不能告诉我们该字符串是否可以被视为有效的数字。 因此,我们需要使用其他函数来获取此类信息:

isNumeric(表达式)
如果表达式可作为数字使用,则返回 true
isDate(表达式)
如果表达式可作为日期使用,则返回真
isEmpty(var)
如果变量 var 未被初始化,则返回 true
isNull(var)
如果变量 var 包含无效数据,则返回 true
isArray(var)
如果 var 是数组,则返回 true
isObject(var)
如果 var 是对象,则返回 true

以下示例要求用户通过键盘输入数据,直到该数据被识别为数字:

程序

' 读取数据直至被识别为数字

Option Explicit

Dim fini, nombre

' 在输入数据不正确时循环
' 循环由一个初始值为假的布尔变量控制(表示未结束)

fini=false
Do While Not fini
     ' 请求输入数字
    wscript.stdout.write "Tapez un nombre : "
     ' 读取该数值
    nombre=wscript.stdin.readLine
     ' 读取时类型必然为字符串
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
     ' 检测读取数据的实际类型
    If isNumeric(nombre) Then
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' 确认
wscript.echo "Merci pour le nombre " & nombre

' 结束
wscript.quit 0

结果

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

函数 isNumeric 无法判断表达式是否为整数。要获取此信息,需要进行额外测试。以下示例要求输入一个大于 0 的整数:

程序

' 读取数据,直到该数据被识别为大于0的整数

Option Explicit

Dim fini, nombre

' 只要输入的数据不正确,就循环
' 循环由一个初始值为假的布尔变量控制(表示未结束)

fini=false
Do While Not fini
     ' 请求输入数字
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' 读取该数值
    nombre=wscript.stdin.readLine
     ' 检测读取数据的实数类型
    If isNumeric(nombre) Then
         ' 是否为正整数(即数值等于其整数部分)?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
     ' 可能的错误信息
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

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

' 结束
wscript.quit 0

结果

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

注释:

  • int(nombre) 返回一个数的整数部分。一个数等于其整数部分即为整数。
  • 值得注意的是,我们不得不使用条件判断 If (数字 - int(数字)) = 0 数字 > 0,因为条件判断 If 数字 = int(数字) 数字 > 0 并未产生预期结果。它无法识别正整数。具体原因请读者自行探究。
  • If (数字 - int(数字)) = 0 这一判断并非完全可靠。让我们来看以下运行示例:
Tapez un nombre entier >0: 4,0000000000000000000000001

Merci pour le nombre entier >0 : 4,0000000000000000000000001

实数并非以精确值表示,而是以近似值表示。在此,运算 nombre-int(nombre) 得出的结果为 0,其精度取决于计算机的计算能力。

4.2. 正则表达式

正则表达式允许我们验证字符串的格式。因此,我们可以检查表示日期的字符串是否符合 dd/mm/yy 格式。为此,我们使用一个模式并将字符串与该模式进行比较。因此,在此示例中,j、m 和 a 必须是数字。 因此,有效的日期格式模式为“\d\d/\d\d/\d\d”,其中符号 \d 表示一个数字。模式中可使用的符号如下(微软文档):

字符
描述
\
将后续字符标记为特殊字符或字面字符。例如,“n”表示字符“n”。“\n”表示换行符。字符序列“\\”表示“\”,而“\("表示“(”。
^
表示输入的开头。
$
表示输入的结尾。
*
表示前一个字符零次或多次出现。因此,“zo*”匹配“z”或“zoo”。
+
匹配前一个字符一次或多次。因此,“zo+”匹配“zoo”,但不匹配“z”。
?
匹配前一个字符零次或一次。例如,“a?ve?”匹配“lever”中的“ve”。
.
匹配除换行符以外的任何单个字符。
(模式)
搜索 modèle 并记录匹配结果。可以通过 Item [0]...[n] 从获得的 Matches 集合中提取匹配的子字符串。 若要查找包含括号 ( ) 内的字符的匹配项,请使用 "\(" 或 "\)"。
x|y
匹配 xy。例如,“z|foot”匹配“z”或“foot”。“(z|f)oo”匹配“zoo”或“foo”。
{n}
n 是一个非负整数。它精确匹配 n 倍的该字符。例如,“o{2}”不匹配“Bob,”中的“o”,而是匹配“fooooot”中的前两个“o”。
{n,}
n 是一个非负整数。匹配至少 n 倍的该字符。 例如,“o{2,}”不匹配“Bob”中的“o”,而是匹配“fooooot”中的所有“o”。“o{1,}”等同于“o+”,而“o{0,}”等同于“o*”。
{n,m}
m n 是非负整数。 表示该字符出现次数不少于 n 次,且不超过 m 次。例如,“o{1,3}”匹配“foooooot”中的前三个“o”,而“o{0,1}”等同于“o?”。
[xyz]
字符集。匹配所列出的任意一个字符。例如,“[abc]”匹配“plat”中的“a”。
[^xyz]
否定字符集。匹配所有未列出的字符。例如,“[^abc]”匹配“plat”中的“p”。
[a-z]
字符范围。匹配指定字符序列中的任何字符。例如,“[a-z]”匹配“a”到“z”之间的所有小写字母。
[^m-z]
负字符集。匹配指定字符集中的所有非字符。例如,“[^m-z]”匹配“m”和“z”之间的所有非字符。
\b
匹配表示单词的边界,即单词与空格之间的位置。例如,“er\b”匹配“lever”中的“er”,但不匹配“verbe”中的“er”。
\B
匹配不代表单词的边界。“en*t\B”匹配“bien entendu”中的“ent”。
\d
表示一个数字字符。等同于 [0-9]。
\D
匹配不代表数字的字符。等同于 [^0-9]。
\f
对应于换行符。
\n
表示换行符。
\r
对应回车符。
\s
表示任何空白字符,包括空格、制表符、分页符等。等同于“[ \f\n\r\t\v]”。
\S
匹配任何非空白字符。等同于“[^ \f\n\r\t\v]”。
\t
匹配一个制表符。
\v
匹配垂直制表符。
\w
匹配任何代表单词的字符,包括下划线。等同于“[A-Za-z0-9_]”。
\W
匹配任何不代表单词的字符。等同于“[^A-Za-z0-9_]”。
\num
匹配 num,其中 num 是一个正整数。指代存储的匹配项。例如,"(.)\1" 匹配两个连续的相同字符。
\n
对应于 n,其中 n 是一个八进制转义值。八进制转义值必须包含 1、2 或 3 个数字。例如,“\11”和“\011”都对应于一个制表符。 "\0011" 等同于 "\001" & "1"。八进制转义值不得超过 256。如果超过,则表达式中仅考虑前两位数字。允许在正则表达式中使用 ASCII 代码。
\xn
等同于 n,其中 n 是一个十六进制转义值。 十六进制转义值必须包含两个数字。例如,“\x41”对应“A”。“\x041”等同于“\x04”和“1”。允许在正则表达式中使用代码 ASCII。

模板中的一个元素可以出现一次或多次。下面通过几个关于 \d 符号的示例来说明,该符号代表 1 个数字:

模板
含义
\d
一个数字
\d?
0 或 1 个数字
\d*
0 个或更多数字
\d+
1 个或多个数字
\d{2}
2个数字
\d{3,}
至少 3 个数字
\d{5,7}
5 到 7 位数字

现在设想一个能够描述字符串预期格式的模式:

要查找的字符串
模式
日期格式为 dd/mm/yy
\d{2}/\d{2}/\d{2}
时长格式为 hh:mm:ss
\d{2}:\d{2}:\d{2}
一个无符号整数
\d+
一个可能为空的空格序列
\s*
一个无符号整数,其前后可能有空格
\s*\d+\s*
一个可能带符号且前后可能有空格的整数
\s*[+|-]?\s*\d+\s*
一个无符号实数,其前后可能有空格
\s*\d+(.\d*)?\s*
一个可能带符号且前后带有空格的实数
\s*[+|]?\s*\d+(.\d*)?\s*
包含单词“just”的字符串
\bjuste\b
  

可以指定在字符串中搜索模式的位置:

模式
含义
^模式
模式位于字符串开头
模式$
模式结束字符串
^模式$
模式开头和结尾
模式
从字符串开头开始,在整个字符串中搜索该模式。
要搜索的字符串
模式
以感叹号结尾的字符串
!$
以句点结尾的字符串
\.$
以 // 序列开头的字符串
^//
仅包含一个单词(前后可能有空格)的字符串
^\s*\w+\s*$
一个字符串,包含两个单词,前后可能有空格
^\s*\w+\s*\w+\s*$
包含单词 secret 的字符串
\bsecret\b

模型的子集可以被“提取”。因此,我们不仅可以验证一个字符串是否符合特定模型,还可以从该字符串中提取出模型中用圆括号括起的子集对应的元素。 例如,如果要解析一个包含日期格式 dd/mm/yy 的字符串,并希望从中提取日期中的 dd、mm、yy 这三个元素,则应使用正则表达式 (\d\d)/(\d\d)/(\d\d)。

让我们通过这个示例,看看如何使用 VBScript 进行操作。

  • 首先,我们需要创建一个 RegExp(正则表达式)对象
set modele=new regexp
  • 然后设定待测试的模式
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • 可能需要设置不区分大小写(默认情况下是区分大小写的)。在此处,这并不重要。
modele.IgnoreCase=true
  • 可能需要对字符串中的模式进行多次搜索(默认不进行多次搜索)
modele.Global=true

只有当所用的模式不涉及字符串的开头或结尾时,全局搜索才有意义。

  • 此时,系统将搜索字符串中所有与该模式匹配的内容:
set correspondances=modele.execute(chaine)

execute 对象的 RegExp 方法返回一个 match 类型的对象集合。该对象具有 value 属性,其值为 chaine 中与模式匹配的元素。 如果设置了 modele.global=true,则可能存在多个匹配项。因此,方法 execute 的返回结果是一个匹配项集合。

  • 匹配项的数量由 correspondances.count 给出。如果该数值为 0,则表示该模型在任何地方均未被找到。 第 i 个匹配项的值由 correspondances(i).value 给出。如果模式包含括号内的子模式,则 correspondances(i) 中对应模式中第 j 个括号的元素即为 correspondances(i).submatches(j)

以下示例展示了上述内容:

程序

' 正则表达式

' 需要验证字符串是否包含日期(格式为 dd/mm/yy)

Option Explicit
Dim modele

' 定义模式
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b"  ' une date n'importe où dans la chaîne
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' 由用户提供待匹配的字符串
Dim chaine, correspondances, i

chaine=""
' 循环处理,直到字符串不等于“end”
Do While true
     ' 提示用户输入文本
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
     ' 若字符串=“end”则结束
    If chaine="fin" Then Exit Do
     ' 将读取的字符串与日期模板进行比对
    Set correspondances=modele.execute(chaine)
     ' 是否找到匹配项
    If correspondances.count<>0 Then
         ' 至少有一个匹配项
        For i=0 To correspondances.count-1
             ' 显示匹配项 i
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
             ' 获取匹配项 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
         ' 无匹配项
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' 结束
wscript.quit 0

结果

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

利用正则表达式,验证键盘输入是否为正整数的程序可以编写如下:

程序

' 读取数据直至被识别为数字

Option Explicit

Dim fini, nombre

' 定义正整数(但可以为零)的模板
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' 只要输入的数据不正确,就循环
' 循环由一个初始值为假的布尔变量控制(表示循环未结束)

fini=false
Do While Not fini
     ' 请求输入数字
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' 读取该数值
    nombre=wscript.stdin.readLine
     ' 验证读取数据的格式
    Dim correspondances
    Set correspondances=modele.execute(nombre)
     ' 模型是否已通过验证?
    If correspondances.count<>0 Then
         ' 这是一个整数,但它是否大于0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
     ' 可能的错误信息
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

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

' 结束
wscript.quit 0

结果

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

找到能够验证字符串是否符合特定模式的正则表达式,有时是一项真正的挑战。以下程序可用于练习。它需要一个模式和一个字符串,然后会指出该字符串是否符合该模式。

程序

' 正则表达式

' 需要验证字符串是否符合模式

Option Explicit

' 定义模式
Dim modele
Set modele=new regexp
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' 由用户提供要搜索模式的字符串
Dim chaine, correspondances, i

Do While true
     ' 要求用户输入正则表达式
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
     ' 完成了吗?
    If modele.pattern="fin" Then Exit Do
         ' 要求用户输入与模板进行比对的字符串
        Do While true
             ' 要求用户输入一个模式
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
             ' 完成了吗?
            If chaine="fin" Then Exit Do
             ' 将读取的字符串与日期模板进行比较
            Set correspondances=modele.execute(chaine)
             ' 是否找到匹配项
            If correspondances.count<>0 Then
                 ' 至少有一个匹配项
                For i=0 To correspondances.count-1
                     ' 显示匹配项 i
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                 ' 未找到匹配项
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' 完成
wscript.quit 0

结果

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. 拦截运行时错误

处理运行时错误的另一种方法是允许错误发生,收到通知后再进行处理。通常,当运行时发生错误时,WSH 会显示一条错误消息并终止程序。以下两条语句可让我们修改这种行为:

on error resume next

该语句告知系统(WSH),我们将自行处理错误。执行此语句后,系统将直接忽略所有错误。

on error goto 0

该语句将恢复正常的错误处理机制。

on error resume next 语句生效时,我们必须自行处理可能出现的错误。Err 对象可协助我们完成此操作。该对象具有多种属性和方法,其中我们重点关注以下两项:

  • number:一个整数,表示最近发生的错误编号。0 表示“无错误”
  • description:如果未执行 on error resume next 语句,系统本会显示的错误信息

让我们来看以下示例:

程序


' 未处理的错误

Option Explicit
Dim nombre

nombre=cdbl("abcd")
wscript.echo "nombre=" & nombre

结果

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

现在处理错误:

程序

' 已处理的错误

Option Explicit
Dim nombre

' 我们自行处理错误
On Error Resume Next
nombre=cdbl("abcd")
' 是否发生错误?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' 无错误 - 恢复正常运行
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0

结果

L'erreur [Type incompatible] s'est produite

让我们用这种新方法重写输入大于0的整数的程序:

程序


' 读取数据直至其被识别为数字

Option Explicit

Dim fini, nombre

' 只要输入的数据不正确,就循环
' 循环由一个初始值为假的布尔变量控制(表示尚未结束)

fini=false
Do While Not fini
  ' 请求输入数字
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' 读取该数字
  nombre=wscript.stdin.readLine
  ' 验证读取数据的格式
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' 无错误,为数字
    ' 恢复到正常的错误处理模式
    On Error GoTo 0
    ' 是否为大于0的整数
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' 恢复到常规错误处理模式
  On Error GoTo 0
  ' 可能的错误消息
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

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

' 结束
wscript.quit 0

结果

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

注释:

  • 有时这是唯一可用的方法。此时,一旦可能引发错误的指令序列执行完毕,切记要恢复到正常的错误处理模式。

4.4. 应用于税款计算程序

我们重新使用已编写的税款计算程序,这次用于验证传递给程序的参数是否有效:

程序


' 计算纳税人的税款
' 调用该程序时需提供三个参数:已婚 子女 工资
' 已婚:已婚时为字符 O,未婚时为 N
' 子女:子女数量
' 工资:年薪(不包含分)

' 不进行数据有效性验证,但
' 会验证是否确实有三个

' 变量必须声明
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)"

' 验证参数数量为3
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' 错误信息
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' 以错误代码 1 终止
    wscript.quit 1
  End If

' 获取参数并验证其有效性
' 参数在传递给程序时前后不带空格
' 将使用正则表达式验证数据有效性
  Dim modele, correspondances
  Set modele=new regexp

  ' 婚姻状况必须包含在指定字符范围内 oOnN
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' 错误
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' 退出
    wscript.quit 2
  End If
  ' 获取值
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If

  ' 子女数必须为大于等于0的整数
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' 错误
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' 退出
    wscript.quit 3
  End If
  ' 获取值
  Dim enfants
  enfants=cint(wscript.arguments(1))

  ' 工资必须是大于等于0的整数
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' 错误
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' 退出
    wscript.quit 4
  End If
  ' 获取值
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' 在 3 个数组中定义计算税款所需的数据
  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)

  ' 计算份额数
  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

  ' 计算家庭分摊额和应税收入
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts

  ' 计算税额
  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))

  ' 显示结果
  wscript.echo "impôt=" & impot

  ' 无错误退出
  wscript.quit 0

结果

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