IV. 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 :
C:\>cscript impots1.vbs o xyzt 200000
C:\impots1.vbs(33, 3) Erreur d'éxecution 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 a un certain modèle
- laisser l'erreur se produire puis l'intercepter pour ensuite la gérer Nous examinons ces différentes méthodes.
IV-A. 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 :
'
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
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 :
'
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
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 escomptes. 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.
IV-B. 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 pond à 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+ |
une 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 cet 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 correspondences 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 d modèle est correspondances(i).submatches(j).
Tout ceci est montré dans l'exemple qui suit :
'
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
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 :
'
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
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.
'
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
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 ]
IV-C. 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. Apres 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 affiche le système si on n'avait pas émis l'instruction on error resume next
Regardons l'exemple qui suit :
'
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 :
'
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 :
'
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
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 des que la séquence d'instructions susceptible de générer l'erreur est terminée.
IV-D. 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 :
'
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
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