Skip to content

4. La gestion des erreurs

En programmation, il y a une règle absolue : un programme ne doit jamais "planter" sauvagement. Toutes les erreurs qui peuvent se produire lors de l'exécution du programme doivent être gérées et des messages d'erreurs significatifs générés.

Si nous reprenons l'exemple des impôts traité précédemment, que se passe-t-il si l'utilisateur entre n'importe quoi pour le nombre d'enfants. Regardons sur cet exemple :

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

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

C'est ce qu'on appelle un plantage sauvage. Il y a eu "plantage" sur l'instruction enfants=cint(wscript.arguments(1)) car arguments(1) contenait la chaîne "xyzt".

Avant d'utiliser un variant dont on ne connaît pas la nature exacte, il faut vérifier son sous-type exact. On peut faire ceci de différentes façons :

  • tester le type réel de la donnée contenue dans un variant avec les fonctions vartype ou typename
  • utiliser une expression régulière pour vérifier que le contenu du variant correspond à un certain modèle
  • laisser l'erreur se produire puis l'intercepter pour ensuite la gérer

Nous examinons ces différentes méthodes.

4.1. Connaître le type exact d'une donnée

Rappelons que les fonctions vartype ou varname permettent de connaître le type exact d'une donnée. Cela ne nous est pas toujours d'un grand secours. Par exemple, lorsque nous lisons une donnée tapée au clavier, les fonctions vartype et typename vont nous dire que c'est une chaîne de caractères car c'est ainsi qu'est considérée toute donnée tapée au clavier. Cela ne nous dit pas si cette chaîne peut par exemple être considérée comme un nombre valide. On utilise alors d'autres fonctions pour avoir accès à ce type d'informations :

isNumeric(expression)

rend vrai si expression peut être utilisée comme un nombre

isDate(expression)

rend vrai si expression peut être utilisée comme une date

isEmpty(var)

rend vrai si la variable var n'a pas été initialisée

isNull(var)

rend vrai si la variable var contient des données invalides

isArray(var)

rend vrai si var est un tableau

isObject(var)

rend vrai si var est un objet

L'exemple suivant demande de taper une donnée au clavier jusqu'à ce que celle-ci soit reconnue comme un nombre :

Programme

' lecture d'une donnée jusqu'à ce que celle-ci soit reconnue comme un nombre

Option Explicit

Dim fini, nombre

' on boucle tant que la donnée saisie n'est pas correcte
' la boucle est contrôlée par un booléen fini, mis à faux au départ (= ce n'est pas fini)

fini=false
Do While Not fini
    ' on demande le nombre
    wscript.stdout.write "Tapez un nombre : "
    ' on le lit
    nombre=wscript.stdin.readLine
    ' le type est forcément string lors d'une lecture
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' on teste le type réel de la donnée lue
    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

' et fin
wscript.quit 0

Résultats

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

La fonction isNumeric ne nous dit pas si une expression est un entier ou pas. Pour avoir cette information, il faut faire des tests supplémentaires. L'exemple suivant demande un nombre entier >0 :

Programme

' lecture d'une donnée jusqu'à ce que celle-ci soit reconnue comme un nombre entier >0

Option Explicit

Dim fini, nombre

' on boucle tant que la donnée saisie n'est pas correcte
' la boucle est contrôlée par un booléen fini, mis à faux au départ (= ce n'est pas fini)

fini=false
Do While Not fini
    ' on demande le nombre
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' on le lit
    nombre=wscript.stdin.readLine
    ' on teste le type réel de la donnée lue
    If isNumeric(nombre) Then
        ' est-ce un entier (nombre égal à sa partie entière) positif ?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
    ' msg d'erreur éventuel
    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

' et fin
wscript.quit 0

Résultats

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

Commentaires :

  • int(nombre) donne la partie entière d'un nombre. Un nombre égal à sa partie entière est un entier.
  • On notera, de façon intéressante, qu'il a fallu employer le test If (nombre-int(nombre))=0 And nombre>0 parce que le test If nombre=int(nombre) And nombre>0 ne donnait pas les résultats escomptés. Il ne détectait pas les nombres entiers positifs. Nous laissons au lecteur le soin de découvrir pourquoi.
  • Le test If (nombre-int(nombre))=0 n'est pas totalement fiable. Regardons l'exemple d'exécution suivant :
Tapez un nombre entier >0: 4,0000000000000000000000001

Merci pour le nombre entier >0 : 4,0000000000000000000000001

Les nombres réels ne sont pas représentés de façon exacte mais de façon approchée. Et ici, l'opération nombre-int(nombre) a donné 0 à la précision près de l'ordinateur.

4.2. Les expressions régulières

Les expressions régulières nous permettent de tester le format d'une chaîne de caractères. Ainsi on peut vérifier qu'une chaîne représentant une date est au format jj/mm/aa. On utilise pour cela un modèle et on compare la chaîne à ce modèle. Ainsi dans cet exemple, j m et a doivent être des chiffres. Le modèle d'un format de date valide est alors "\d\d/\d\d/\d\d" où le symbole \d désigne un chiffre. Les symboles utilisables dans un modèle sont les suivants (documentation Microsoft) :

Caractère

Description

\

Marque le caractère suivant comme caractère spécial ou littéral. Par exemple, "n" correspond au caractère "n". "\n" correspond à un caractère de nouvelle ligne. La séquence "\\" correspond à "\", tandis que "\(" correspond à "(".

^

Correspond au début de la saisie.

$

Correspond à la fin de la saisie.

*

Correspond au caractère précédent zéro fois ou plusieurs fois. Ainsi, "zo*" correspond à "z" ou à "zoo".

+

Correspond au caractère précédent une ou plusieurs fois. Ainsi, "zo+" correspond à "zoo", mais pas à "z".

?

Correspond au caractère précédent zéro ou une fois. Par exemple, "a?ve?" correspond à "ve" dans "lever".

.

Correspond à tout caractère unique, sauf le caractère de nouvelle ligne.

(modèle)

Recherche le modèle et mémorise la correspondance. La sous-chaîne correspondante peut être extraite de la collection Matches obtenue, à l'aide d'Item [0]...[n]. Pour trouver des correspondances avec des caractères entre parenthèses ( ), utilisez "\(" ou "\)".

x|y

Correspond soit à x soit à y. Par exemple, "z|foot" correspond à "z" ou à "foot". "(z|f)oo" correspond à "zoo" ou à "foo".

{n}

n est un nombre entier non négatif. Correspond exactement à n fois le caractère. Par exemple, "o{2}" ne correspond pas à "o" dans "Bob," mais aux deux premiers "o" dans "fooooot".

{n,}

n est un entier non négatif. Correspond à au moins n fois le caractère. Par exemple, "o{2,}" ne correspond pas à "o" dans "Bob", mais à tous les "o" dans "fooooot". "o{1,}" équivaut à "o+" et "o{0,}" équivaut à "o*".

{n,m}

m et n sont des entiers non négatifs. Correspond à au moins n et à au plus m fois le caractère. Par exemple, "o{1,3}" correspond aux trois premiers "o" dans "foooooot" et "o{0,1}" équivaut à "o?".

[xyz]

Jeu de caractères. Correspond à l'un des caractères indiqués. Par exemple, "[abc]" correspond à "a" dans "plat".

[^xyz]

Jeu de caractères négatif. Correspond à tout caractère non indiqué. Par exemple, "[^abc]" correspond à "p" dans "plat".

[a-z]

Plage de caractères. Correspond à tout caractère dans la série spécifiée. Par exemple, "[a-z]" correspond à tout caractère alphabétique minuscule compris entre "a" et "z".

[^m-z]

Plage de caractères négative. Correspond à tout caractère ne se trouvant pas dans la série spécifiée. Par exemple, "[^m-z]" correspond à tout caractère ne se trouvant pas entre "m" et "z".

\b

Correspond à une limite représentant un mot, autrement dit, à la position entre un mot et un espace. Par exemple, "er\b" correspond à "er" dans "lever", mais pas à "er" dans "verbe".

\B

Correspond à une limite ne représentant pas un mot. "en*t\B" correspond à "ent" dans "bien entendu".

\d

Correspond à un caractère représentant un chiffre. Équivaut à [0-9].

\D

Correspond à un caractère ne représentant pas un chiffre. Équivaut à [^0-9].

\f

Correspond à un caractère de saut de page.

\n

Correspond à un caractère de nouvelle ligne.

\r

Correspond à un caractère de retour chariot.

\s

Correspond à tout espace blanc, y compris l'espace, la tabulation, le saut de page, etc. Équivaut à "[ \f\n\r\t\v]".

\S

Correspond à tout caractère d'espace non blanc. Équivaut à "[^ \f\n\r\t\v]".

\t

Correspond à un caractère de tabulation.

\v

Correspond à un caractère de tabulation verticale.

\w

Correspond à tout caractère représentant un mot et incluant un trait de soulignement. Équivaut à "[A-Za-z0-9_]".

\W

Correspond à tout caractère ne représentant pas un mot. Équivaut à "[^A-Za-z0-9_]".

\num

Correspond à num, où num est un entier positif. Fait référence aux correspondances mémorisées. Par exemple, "(.)\1" correspond à deux caractères identiques consécutifs.

\n

Correspond à n, où n est une valeur d'échappement octale. Les valeurs d'échappement octales doivent comprendre 1, 2 ou 3 chiffres. Par exemple, "\11" et "\011" correspondent tous les deux à un caractère de tabulation. "\0011" équivaut à "\001" & "1". Les valeurs d'échappement octales ne doivent pas excéder 256. Si c'était le cas, seuls les deux premiers chiffres seraient pris en compte dans l'expression. Permet d'utiliser les codes ASCII dans des expressions régulières.

\xn

Correspond à n, où n est une valeur d'échappement hexadécimale. Les valeurs d'échappement hexadécimales doivent comprendre deux chiffres obligatoirement. Par exemple, "\x41" correspond à "A". "\x041" équivaut à "\x04" & "1". Permet d'utiliser les codes ASCII dans des expressions régulières.

Un élément dans un modèle peut être présent en 1 ou plusieurs exemplaires. Considérons quelques exemples autour du symbole \d qui représente 1 chiffre :

modèle

signification

\d

un chiffre

\d?

0 ou 1 chiffre

\d*

0 ou davantage de chiffres

\d+

1 ou davantage de chiffres

\d{2}

2 chiffres

\d{3,}

au moins 3 chiffres

\d{5,7}

entre 5 et 7 chiffres

Imaginons maintenant le modèle capable de décrire le format attendu pour une chaîne de caractères :

chaîne recherchée

modèle

une date au format jj/mm/aa

\d{2}/\d{2}/\d{2}

une heure au format hh:mm:ss

\d{2}:\d{2}:\d{2}

un nombre entier non signé

\d+

un suite d'espaces éventuellement vide

\s*

un nombre entier non signé qui peut être précédé ou suivi d'espaces

\s*\d+\s*

un nombre entier qui peut être signé et précédé ou suivi d'espaces

\s*[+|-]?\s*\d+\s*

un nombre réel non signé qui peut être précédé ou suivi d'espaces

\s*\d+(.\d*)?\s*

un nombre réel qui peut être signé et précédé ou suivi d'espaces

\s*[+|]?\s*\d+(.\d*)?\s*

une chaîne contenant le mot juste

\bjuste\b

  

On peut préciser où on recherche le modèle dans la chaîne :

modèle

signification

^modèle

le modèle commence la chaîne

modèle$

le modèle finit la chaîne

^modèle$

le modèle commence et finit la chaîne

modèle

le modèle est cherché partout dans la chaîne en commençant par le début de celle-ci.

chaîne recherchée

modèle

une chaîne se terminant par un point d'exclamation

!$

une chaîne se terminant par un point

\.$

une chaîne commençant par la séquence //

^//

une chaîne ne comportant qu'un mot éventuellement suivi ou précédé d'espaces

^\s*\w+\s*$

une chaîne ne comportant deux mot éventuellement suivis ou précédés d'espaces

^\s*\w+\s*\w+\s*$

une chaîne contenant le mot secret

\bsecret\b

Les sous-ensembles d'un modèle peuvent être "récupérés". Ainsi non seulement, on peut vérifier qu'une chaîne correspond à un modèle particulier mais on peut récupérer dans cette chaîne les éléments correspondant aux sous-ensembles du modèle qui ont été entourés de parenthèses. Ainsi si on analyse une chaîne contenant une date jj/mm/aa et si on veut de plus récupérer les éléments jj, mm, aa de cette date on utilisera le modèle (\d\d)/(\d\d)/(\d\d).

Voyons sur cette exemple, comment on opère avec vbscript.

  • il nous faut tout d'abord créer un objet RegExp (Regular Expression)
set modele=new regexp
  • ensuite on fixe le modèle à tester
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • on peut vouloir ne pas faire de différence entre majuscules et minuscules (par défaut elle est faite). Ici ça n'a aucune importance.
modele.IgnoreCase=true
  • on peut vouloir rechercher le modèle plusieurs fois dans la chaîne (par défaut ce n'est pas fait)
modele.Global=true

Une recherche globale n'a de sens que si le modèle utilisé ne fait pas référence au début ou à la fin de la chaîne.

  • on recherche alors toutes les correspondances du modèle dans la chaîne :
set correspondances=modele.execute(chaine)

La méthode execute d'un objet RegExp rend une collection d'objets de type match. Cet objet a une propriété value qui est l'élément de chaine correspondant au modèle. Si on a écrit modele.global=true, on peut avoir plusieurs correspondances. C'est pourquoi le résultat de la méthode execute est une collection de correspondances.

  • le nombre de correspondances est donné par correspondances.count. Si ce nombre vaut 0, c'est que le modèle n'a été trouvé nulle part. La valeur de la correspondance n° i est donnée par correspondances(i).value. Si le modèle contient des sous-modèles entre parenthèses, alors l'éléments de correspondances(i) correspondant à la parenthèse j du modèle est correspondances(i).submatches(j).

Tout ceci est montré dans l'exemple qui suit :

Programme

' expression régulière

' on veut vérifier qu'une chaîne contient une date au format jj/mm/aa

Option Explicit
Dim modele

' on définit le modèle
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

' c'est l'utilisateur qui donne la chaîne dans laquelle on cherchera le modèle
Dim chaine, correspondances, i

chaine=""
' on boucle tant que chaine<>"fin"
Do While true
    ' on demande à l'utilisateur de taper un texte
    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
    ' on compare la chaîne lue au modèle de la date
    Set correspondances=modele.execute(chaine)
    ' a-t-on trouvé une correspondance
    If correspondances.count<>0 Then
        ' on a au moins une correspondance
        For i=0 To correspondances.count-1
            ' on affiche la correspondance i
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' on récupère les sous-éléments de la correspondance 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
        ' pas de correspondance
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' fini
wscript.quit 0

Résultats

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

Avec les expressions régulières, le programme testant qu'une saisie clavier est bien un nombre entier positif pourrait s'écrire comme suit :

Programme

' lecture d'une donnée jusqu'à ce que celle-ci soit reconnue comme un nombre

Option Explicit

Dim fini, nombre

' on définit le modèle d'un nombre entier positif (mais qui peut être nul)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' on boucle tant que la donnée saisie n'est pas correcte
' la boucle est contrôlée par un booléen fini, mis à faux au départ (= ce n'est pas fini)

fini=false
Do While Not fini
    ' on demande le nombre
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' on le lit
    nombre=wscript.stdin.readLine
    ' on teste le format de la donnée lue
    Dim correspondances
    Set correspondances=modele.execute(nombre)
    ' le modèle a-t-il été vérifié ?
    If correspondances.count<>0 Then
        ' c'est un entier mais est-il >0 ?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
    ' msg d'erreur éventuel
    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

' et fin
wscript.quit 0

Résultats

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

Trouver l'expression régulière qui nous permet de vérifier qu'une chaîne correspond bien à un certain modèle est parfois un véritable défi. Le programme suivant permet de s'entraîner. Il demande un modèle et une chaîne et indique alors si la chaîne correspond ou non au modèle.

Programme

' expression régulière

' on veut vérifier qu'une chaîne correspond à un modèle

Option Explicit

' on définit le modèle
Dim modele
Set modele=new regexp
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' c'est l'utilisateur qui donne la chaîne dans laquelle on cherchera le modèle
Dim chaine, correspondances, i

Do While true
    ' on demande à l'utilisateur de taper un modèle
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' fini ?
    If modele.pattern="fin" Then Exit Do
        ' on demande à l'utilisateur les chaînes à comparer au modèle
        Do While true
            ' on demande à l'utilisateur de taper un modèle
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
            ' fini ?
            If chaine="fin" Then Exit Do
            ' on compare la chaîne lue au modèle de la date
            Set correspondances=modele.execute(chaine)
            ' a-t-on trouvé une correspondance
            If correspondances.count<>0 Then
                ' on a au moins une correspondance
                For i=0 To correspondances.count-1
                    ' on affiche la correspondance i
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                ' pas de correspondance
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' fini
wscript.quit 0

Résultats

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. Intercepter les erreurs d'exécution

Une autre méthode de gestion des erreurs d'exécution est de les laisser se produire, d'en être avertis et de les gérer alors. Normalement lorsqu'une erreur se passe à l'exécution, WSH affiche un message d'erreur et le programme est arrêté. Deux instructions nous permettent de modifier ce fonctionnement :

on error resume next

Cette instruction indique au système (WSH) que nous allons gérer les erreurs nous-mêmes. Après cette instruction, toute erreur est simplement ignorée. par le système.

on error goto 0

Cette instruction nous ramène au fonctionnement normal de gestion des erreurs.

Lorsque l'instruction on error resume next est active, nous devons gérer nous-mêmes les erreurs qui peuvent survenir. L'objet Err nous y aide. Cet objet a diverses propriétés et méthodes dont nous retiendrons les deux suivantes :

  • number : un nombre entier numéro de la dernière erreur qui s'est produite. 0 veut dire "pas d'erreur"
  • description : le message d'erreur qu'aurait affiché le système si on n'avait pas émis l'instruction on error resume next

Regardons l'exemple qui suit :

Programme

Résultats


' erreur non gérée

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'

Gérons maintenant l'erreur :

Programme

Résultats

' erreur gérée

Option Explicit
Dim nombre

' on gère les erreurs nous-mêmes
On Error Resume Next
nombre=cdbl("abcd")
' y-a-t-il eu erreur ?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' pas d'erreur - on revient au fonctionnement normal
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0
L'erreur [Type incompatible] s'est produite

Réécrivons le programme de saisie d'un entier >0 avec cette nouvelle méthode :

Programme


' lecture d'une donnée jusqu'à ce que celle-ci soit reconnue comme un nombre

Option Explicit

Dim fini, nombre

' on boucle tant que la donnée saisie n'est pas correcte
' la boucle est contrôlée par un booléen fini, mis à faux au départ (= ce n'est pas fini)

fini=false
Do While Not fini
  ' on demande le nombre
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' on le lit
  nombre=wscript.stdin.readLine
  ' on teste le format de la donnée lue
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' pas d'erreur c'est un nombre
    ' on revient au mode normal de gestion des erreurs
    On Error GoTo 0
    ' est-ce un entier >0
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' on revient au mode normal de gestion des erreurs
  On Error GoTo 0
  ' msg d'erreur éventuel
  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

' et fin
wscript.quit 0

Résultats

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

Commentaires :

  • Cette méthode est parfois la seule utilisable. Il ne faut alors pas oublier de revenir au mode normal de gestion des erreurs dès que la séquence d'instructions susceptible de générer l'erreur est terminée.

4.4. Application au programme de calcul d'impôts

Nous reprenons le programme de calcul d'impôts déjà écrit pour, cette fois, vérifier la validité des arguments passés au programme :

Programme


' calcul de l'impôt d'un contribuable
' le programme doit être appelé avec trois paramètres : marié enfants salaire
' marié : caractère O si marié, N si non marié
' enfants : nombre d'enfants
' salaire : salaire annuel sans les centimes

' aucune vérification de la validité des données n'est faite mais on
' vérifie qu'il y en a bien trois

' déclaration obligatoire des variables
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)"

' on vérifie qu'il y a 3 arguments
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' msg d'erreur
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' arrêt avec code d'erreur 1
    wscript.quit 1
  End If
  
' on récupère les arguments en vérifiant leur validité
' un argument est transmis au programme sans espaces devant et derrière
' on utilisera des expression régulières pour vérifier la validité des données
  Dim modele, correspondances
  Set modele=new regexp

  ' le statut marital doit être parmi les caractères oOnN
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' erreur
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' on quitte
    wscript.quit 2
  End If
  ' on récupère la valeur
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If
  
  ' enfants doit être un nombre entier >=0
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' erreur
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' on quitte
    wscript.quit 3
  End If
  ' on récupère la valeur
  Dim enfants
  enfants=cint(wscript.arguments(1))

  ' salaire doit être un entier >=0
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' erreur
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' on quitte
    wscript.quit 4
  End If
  ' on récupère la valeur
  Dim salaire
  salaire=clng(wscript.arguments(2))
  
  ' on définit les données nécessaire au calcul de l'impôt dans 3 tableaux
  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)

  ' on calcule le nombre de parts
  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
  
  ' on calcule le quotient familial et le revenu imposable
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts
  
  ' on calcule l'impôt
  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))
  
  ' on affiche le résultat
  wscript.echo "impôt=" & impot
  
  ' on quitte sans erreur
  wscript.quit 0

Résultats

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