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