Skip to content

4. Gestión de errores

En programación, hay una regla absoluta: un programa nunca debe «colgarse» de forma imprevista. Todos los errores que puedan producirse durante la ejecución del programa deben gestionarse y deben generarse mensajes de error significativos.

Si retomamos el ejemplo de los impuestos tratado anteriormente, ¿qué ocurre si el usuario introduce cualquier valor para el número de hijos? Veamos este ejemplo:

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

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

Esto es lo que se denomina un fallo imprevisto. Se ha producido un «fallo» en la instrucción hijos=cint(wscript.arguments(1)) porque arguments(1) contenía la cadena «xyzt».

Antes de utilizar una variante de la que no se conoce la naturaleza exacta, hay que verificar su subtipo exacto. Esto se puede hacer de diferentes maneras:

  • comprobar el tipo real de los datos contenidos en una variante con las funciones vartype o typename
  • utilizar una expresión regular para comprobar que el contenido de la variante se ajusta a un determinado patrón
  • dejar que se produzca el error, interceptarlo y gestionarlo

Analizamos estos diferentes métodos.

4.1. Conocer el tipo exacto de un dato

Recordemos que las funciones vartype o varname permiten conocer el tipo exacto de un dato. Esto no siempre nos resulta de gran ayuda. Por ejemplo, cuando leemos un dato introducido con el teclado, las funciones vartype y typename nos dirán que se trata de una cadena de caracteres, ya que así se considera cualquier dato introducido con el teclado. Esto no nos indica si dicha cadena puede, por ejemplo, considerarse un número válido. Por lo tanto, utilizamos otras funciones para acceder a este tipo de información:

isNumeric(expresión)
devuelve verdadero si la expresión puede utilizarse como un número
isDate(expresión)
devuelve verdadero si la expresión puede utilizarse como una fecha
isEmpty(var)
devuelve «verdadero» si la variable var no se ha inicializado
isNull(var)
devuelve verdadero si la variable var contiene datos no válidos
isArray(var)
devuelve verdadero si var es una matriz
isObject(var)
devuelve verdadero si var es un objeto

El siguiente ejemplo solicita que se introduzca un dato mediante el teclado hasta que este sea reconocido como un número:

Programa

' lectura de un dato hasta que se reconozca como un número

Option Explicit

Dim fini, nombre

' se repite el bucle mientras el dato introducido no sea correcto
' el bucle se controla mediante un valor booleano finito, establecido en falso al inicio (= no ha terminado)

fini=false
Do While Not fini
     ' se solicita el número
    wscript.stdout.write "Tapez un nombre : "
     ' se lee
    nombre=wscript.stdin.readLine
     ' el tipo es necesariamente cadena al leer
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
     ' se comprueba el tipo real de los datos leídos
    If isNumeric(nombre) Then
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' confirmación
wscript.echo "Merci pour le nombre " & nombre

' y fin
wscript.quit 0

Resultados

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 función isNumeric no nos indica si una expresión es un entero o no. Para obtener esta información, es necesario realizar pruebas adicionales. El siguiente ejemplo solicita un número entero >0:

Programa

' lectura de un dato hasta que este se reconozca como un número entero >0

Option Explicit

Dim fini, nombre

' se repite el bucle mientras el dato introducido no sea correcto
' el bucle se controla mediante un valor booleano finito, establecido en falso al inicio (= no ha terminado)

fini=false
Do While Not fini
     ' se solicita el número
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' se lee
    nombre=wscript.stdin.readLine
     ' se comprueba el tipo real de los datos leídos
    If isNumeric(nombre) Then
         ' ¿Es un entero (número igual a su parte entera) positivo?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
     ' posible mensaje de error
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmación
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' y fin
wscript.quit 0

Resultados

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

Comentarios:

  • int(nombre) devuelve la parte entera de un número. Un número igual a su parte entera es un entero.
  • Cabe destacar, curiosamente, que ha sido necesario emplear la prueba If (número-int(número))=0 And número>0 porque la prueba If número=int(número) And número>0 no daba los resultados esperados. No detectaba los números enteros positivos. Dejamos al lector la tarea de descubrir por qué.
  • La prueba If (número - int(número)) = 0 no es totalmente fiable. Veamos el siguiente ejemplo de ejecución:
Tapez un nombre entier >0: 4,0000000000000000000000001

Merci pour le nombre entier >0 : 4,0000000000000000000000001

Los números reales no se representan de forma exacta, sino aproximada. Y en este caso, la operación nombre-int(nombre) ha dado como resultado 0, con la precisión del ordenador.

4.2. Las expresiones regulares

Las expresiones regulares nos permiten comprobar el formato de una cadena de caracteres. Así, podemos verificar que una cadena que representa una fecha tiene el formato dd/mm/aa. Para ello, se utiliza un patrón y se compara la cadena con dicho patrón. Así, en este ejemplo, d, m y a deben ser dígitos. El patrón de un formato de fecha válido es entonces «\d\d/\d\d/\d\d», donde el símbolo \d designa un dígito. Los símbolos que se pueden utilizar en un patrón son los siguientes (documentación de Microsoft):

Carácter
Descripción
\
Marca el carácter siguiente como carácter especial o literal. Por ejemplo, «n» corresponde al carácter «n». «\n» corresponde a un carácter de nueva línea. La secuencia «\\» corresponde a «\», mientras que «\» corresponde a «(».
^
Corresponde al inicio de la entrada.
$
Corresponde al final de la entrada.
*
Corresponde al carácter anterior cero o más veces. Así, «zo*» corresponde a «z» o a «zoo».
+
Corresponde al carácter anterior una o varias veces. Así, «zo+» corresponde a «zoo», pero no a «z».
?
Coincide con el carácter anterior cero o una vez. Por ejemplo, «a?ve?» coincide con «ve» en «lever».
.
Coincide con cualquier carácter único, excepto el carácter de nueva línea.
(patrón)
Busca modèle y memoriza la coincidencia. La subcadena correspondiente se puede extraer de la colección Matches obtenida, utilizando Item [0]...[n]. Para encontrar coincidencias con caracteres entre paréntesis ( ), utilice "\(" o "\)".
x|y
Coincide con x o con y. Por ejemplo, «z|foot» coincide con «z» o con «foot». «(z|f)oo» coincide con «zoo» o con «foo».
{n}
n es un número entero no negativo. Corresponde exactamente a n multiplicado por el carácter. Por ejemplo, «o{2}» no corresponde a «o» en «Bob», sino a las dos primeras «o» en «fooooot».
{n,}
n es un número entero no negativo. Corresponde al menos a n veces el carácter. Por ejemplo, «o{2,}» no coincide con la «o» de «Bob», sino con todas las «o» de «fooooot». «o{1,}» equivale a «o+» y «o{0,}» equivale a «o*».
{n,m}
m y n son números enteros no negativos. Corresponde al menos a n y como máximo a m veces el carácter. Por ejemplo, «o{1,3}» corresponde a las tres primeras «o» de «foooooot» y «o{0,1}» equivale a «o?».
[xyz]
Conjunto de caracteres. Corresponde a uno de los caracteres indicados. Por ejemplo, «[abc]» corresponde a «a» en «plat».
[^xyz]
Conjunto de caracteres negativo. Corresponde a cualquier carácter no indicado. Por ejemplo, «[^abc]» corresponde a «p» en «plat».
[a-z]
Rango de caracteres. Corresponde a cualquier carácter de la serie especificada. Por ejemplo, «[a-z]» corresponde a cualquier carácter alfabético minúsculo comprendido entre «a» y «z».
[^m-z]
Rango de caracteres negativo. Corresponde a cualquier carácter que no se encuentre en la serie especificada. Por ejemplo, «[^m-z]» corresponde a cualquier carácter que no se encuentre entre «m» y «z».
\b
Corresponde a un límite que representa una palabra, es decir, a la posición entre una palabra y un espacio. Por ejemplo, «er\b» corresponde a «er» en «lever», pero no a «er» en «verbe».
\B
Corresponde a un límite que no representa una palabra. «en*t\B» corresponde a «ent» en «bien entendu».
\d
Corresponde a un carácter que representa un dígito. Equivale a [0-9].
\D
Corresponde a un carácter que no representa un dígito. Equivale a [^0-9].
\f
Corresponde a un carácter de salto de página.
\n
Corresponde a un carácter de nueva línea.
\r
Corresponde a un carácter de retorno de carro.
\s
Corresponde a cualquier espacio en blanco, incluyendo el espacio, la tabulación, el salto de página, etc. Equivale a «[ \f\n\r\t\v]».
\S
Corresponde a cualquier carácter de espacio no blanco. Equivale a «[^ \f\n\r\t\v]».
\t
Corresponde a un carácter de tabulación.
\v
Corresponde a un carácter de tabulación vertical.
\w
Corresponde a cualquier carácter que represente una palabra e incluya un guión bajo. Equivale a «[A-Za-z0-9_]».
\W
Corresponde a cualquier carácter que no represente una palabra. Equivale a «[^A-Za-z0-9_]».
\num
Corresponde a num, donde num es un número entero positivo. Hace referencia a las coincidencias almacenadas. Por ejemplo, «(.)\1» corresponde a dos caracteres idénticos consecutivos.
\n
Corresponde a n, donde n es un valor de escape octal. Los valores de escape octales deben tener 1, 2 o 3 dígitos. Por ejemplo, «\11» y «\011» corresponden ambos a un carácter de tabulación. «\0011» equivale a «\001» y «1». Los valores de escape octales no deben superar 256. Si fuera así, solo se tendrían en cuenta los dos primeros dígitos en la expresión. Permite utilizar los códigos ASCII en expresiones regulares.
\xn
Corresponde a n, donde n es un valor de escape hexadecimal. Los valores de escape hexadecimales deben constar obligatoriamente de dos dígitos. Por ejemplo, «\x41» corresponde a «A». «\x041» equivale a «\x04» y «1». Permite utilizar los códigos ASCII en expresiones regulares.

Un elemento de una plantilla puede aparecer una o varias veces. Veamos algunos ejemplos relacionados con el símbolo \d, que representa un dígito:

plantilla
significado
\d
un dígito
\d?
0 o 1 dígito
\d*
0 o más dígitos
\d+
1 o más dígitos
\d{2}
2 dígitos
\d{3,}
al menos 3 dígitos
\d{5,7}
entre 5 y 7 dígitos

Imaginemos ahora el modelo capaz de describir el formato esperado para una cadena de caracteres:

cadena buscada
modelo
una fecha en formato dd/mm/aa
\d{2}/\d{2}/\d{2}
una hora en formato hh:mm:ss
\d{2}:\d{2}:\d{2}
un número entero sin signo
\d+
una secuencia de espacios, que puede estar vacía
\s*
un número entero sin signo que puede ir precedido o seguido de espacios
\s*\d+\s*
un número entero que puede ser con signo y estar precedido o seguido de espacios
\s*[+|-]?\s*\d+\s*
un número real sin signo que puede ir precedido o seguido de espacios
\s*\d+(.\d*)?\s*
un número real que puede ser con signo y estar precedido o seguido de espacios
\s*[+|]?\s*\d+(.\d*)?\s*
una cadena que contenga la palabra «justo»
\bjusto\b
  

Se puede especificar dónde se busca el patrón en la cadena:

patrón
significado
^patrón
el patrón comienza la cadena
patrón$
el patrón termina la cadena
^patrón$
el patrón comienza y termina la cadena
patrón
el patrón se busca en toda la cadena, empezando por el principio de la misma.
cadena buscada
patrón
una cadena que termina con un signo de exclamación
!$
una cadena que termina en un punto
\.$
una cadena que comienza con la secuencia //
^//
una cadena que contiene solo una palabra, seguida o precedida opcionalmente de espacios
^\s*\w+\s*$
una cadena que contenga dos palabras, opcionalmente precedidas o seguidas de espacios
^\s*\w+\s*\w+\s*$
una cadena que contenga la palabra «secret»
\bsecret\b

Los subconjuntos de un patrón pueden «extraerse». De este modo, no solo se puede comprobar si una cadena se ajusta a un patrón concreto, sino que también se pueden extraer de dicha cadena los elementos que corresponden a los subconjuntos del patrón que se han encerrado entre paréntesis. Así, si analizamos una cadena que contiene una fecha dd/mm/aa y queremos además extraer los elementos dd, mm y aa de esa fecha, utilizaremos el patrón (\d\d)/(\d\d)/(\d\d).

Veamos en este ejemplo cómo se opera con VBScript.

  • En primer lugar, debemos crear un objeto RegExp (Expresión regular)
set modele=new regexp
  • A continuación, establecemos el patrón que queremos comprobar
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • Es posible que no queramos distinguir entre mayúsculas y minúsculas (por defecto, sí se distingue). En este caso, no tiene importancia.
modele.IgnoreCase=true
  • Es posible que se desee buscar el patrón varias veces en la cadena (por defecto no se hace)
modele.Global=true

Una búsqueda global solo tiene sentido si el patrón utilizado no hace referencia al principio o al final de la cadena.

  • Entonces se buscan todas las coincidencias del patrón en la cadena:
set correspondances=modele.execute(chaine)

El método execute de un objeto RegExp devuelve una colección de objetos de tipo match. Este objeto tiene una propiedad value que es el elemento de chaine correspondiente al patrón. Si se ha escrito modele.global=true, puede haber varias coincidencias. Por eso, el resultado del método execute es una colección de coincidencias.

  • El número de coincidencias viene dado por correspondances.count. Si este número es 0, significa que el modelo no se ha encontrado en ninguna parte. El valor de la coincidencia n.º i viene dado por correspondances(i).value. Si el patrón contiene subpatrones entre paréntesis, entonces el elemento de correspondances(i) correspondiente al paréntesis j del patrón es coincidencias(i).subcoincidencias(j).

Todo esto se muestra en el siguiente ejemplo:

Programa

' expresión regular

' queremos comprobar que una cadena contiene una fecha en formato dd/mm/aa

Option Explicit
Dim modele

' se define el patrón
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

' es el usuario quien proporciona la cadena en la que se buscará el patrón
Dim chaine, correspondances, i

chaine=""
' se realiza un bucle mientras cadena <> "fin"
Do While true
     ' se le pide al usuario que escriba un texto
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
     ' se termina si cadena = fin
    If chaine="fin" Then Exit Do
     ' se compara la cadena leída con el patrón de la fecha
    Set correspondances=modele.execute(chaine)
     ' ¿se ha encontrado una coincidencia?
    If correspondances.count<>0 Then
         ' hay al menos una coincidencia
        For i=0 To correspondances.count-1
             ' se muestra la coincidencia i
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
             ' se recuperan los subelementos de la coincidencia i
            wscript.echo "Les éléments de la date " & i & " sont (" & correspondances(i).submatches(0) & "," _
            & correspondances(i).submatches(1) & "," & correspondances(i).submatches(2) & ")"
        Next
    Else
         ' no hay coincidencia
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' fin
wscript.quit 0

Resultados

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

Con expresiones regulares, el programa que comprueba que una entrada del teclado es un número entero positivo podría escribirse de la siguiente manera:

Programa

' lectura de un dato hasta que se reconozca como un número

Option Explicit

Dim fini, nombre

' se define el formato de un número entero positivo (que puede ser cero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' se repite el bucle mientras el dato introducido no sea correcto
' el bucle se controla mediante un valor booleano finito, establecido en falso al inicio (= no ha terminado)

fini=false
Do While Not fini
     ' se solicita el número
    wscript.stdout.write "Tapez un nombre entier >0: "
     ' se lee
    nombre=wscript.stdin.readLine
     ' se comprueba el formato de los datos leídos
    Dim correspondances
    Set correspondances=modele.execute(nombre)
     ' ¿Se ha verificado el modelo?
    If correspondances.count<>0 Then
         ' es un entero, pero ¿es >0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
     ' posible mensaje de error
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmación
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' y fin
wscript.quit 0

Resultados

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

Encontrar la expresión regular que nos permita verificar que una cadena se ajusta a un determinado patrón es, a veces, todo un reto. El siguiente programa permite practicar. Solicita un patrón y una cadena y, a continuación, indica si la cadena se ajusta o no al patrón.

Programa

' expresión regular

' queremos comprobar que una cadena se ajusta a un patrón

Option Explicit

' se define el patrón
Dim modele
Set modele=new regexp
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' es el usuario quien proporciona la cadena en la que se buscará el patrón
Dim chaine, correspondances, i

Do While true
     ' se le pide al usuario que introduzca un patrón
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
     ' ¿Terminado?
    If modele.pattern="fin" Then Exit Do
         ' se le pide al usuario las cadenas que se van a comparar con el patrón
        Do While true
             ' se le pide al usuario que introduzca un patrón
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
             ' ¿Terminado?
            If chaine="fin" Then Exit Do
             ' se compara la cadena leída con el patrón de la fecha
            Set correspondances=modele.execute(chaine)
             ' ¿se ha encontrado alguna coincidencia?
            If correspondances.count<>0 Then
                 ' hay al menos una coincidencia
                For i=0 To correspondances.count-1
                     ' se muestra la coincidencia i
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                 ' no hay coincidencia
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' fin
wscript.quit 0

Resultados

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. Interceptar los errores de ejecución

Otro método para gestionar los errores de ejecución consiste en dejar que se produzcan, recibir una notificación y gestionarlos en ese momento. Normalmente, cuando se produce un error durante la ejecución, WSH muestra un mensaje de error y el programa se detiene. Hay dos instrucciones que nos permiten modificar este comportamiento:

on error resume next

Esta instrucción indica al sistema (WSH) que vamos a gestionar los errores nosotros mismos. Tras esta instrucción, el sistema simplemente ignora cualquier error.

on error goto 0

Esta instrucción nos devuelve al funcionamiento normal de gestión de errores.

Cuando la instrucción «on error resume next» está activa, debemos gestionar nosotros mismos los errores que puedan surgir. El objeto Err nos ayuda en ello. Este objeto tiene diversas propiedades y métodos, de los cuales destacaremos los dos siguientes:

  • number: un número entero que indica el número del último error que se ha producido. 0 significa «sin error»
  • descripción: el mensaje de error que habría mostrado el sistema si no se hubiera emitido la instrucción on error resume next

Veamos el siguiente ejemplo:

Programa


' error no gestionado

Option Explicit
Dim nombre

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

Resultados

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

Ahora gestionemos el error:

Programa

' error gestionado

Option Explicit
Dim nombre

' gestionamos los errores nosotros mismos
On Error Resume Next
nombre=cdbl("abcd")
' ¿Ha habido algún error?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' sin error: se vuelve al funcionamiento normal
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0

Resultados

L'erreur [Type incompatible] s'est produite

Reescribamos el programa de introducción de un entero >0 con este nuevo método:

Programa


' lectura de un dato hasta que se reconozca como un número

Option Explicit

Dim fini, nombre

' se repite el bucle hasta que el dato introducido sea correcto
' el bucle se controla mediante un booleano finito, establecido en falso al inicio (= no ha terminado)

fini=false
Do While Not fini
  ' se solicita el número
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' se lee
  nombre=wscript.stdin.readLine
  ' se comprueba el formato de los datos leídos
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' sin errores, es un número
    ' se vuelve al modo normal de gestión de errores
    On Error GoTo 0
    ' ¿Es un entero >0?
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' se vuelve al modo normal de gestión de errores
  On Error GoTo 0
  ' posible mensaje de error
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmación
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' y fin
wscript.quit 0

Resultados

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

Comentarios:

  • En ocasiones, este es el único método que se puede utilizar. En ese caso, no hay que olvidar volver al modo normal de gestión de errores tan pronto como finalice la secuencia de instrucciones que pueda generar el error.

4.4. Aplicación al programa de cálculo de impuestos

Retomamos el programa de cálculo de impuestos ya escrito para, en esta ocasión, verificar la validez de los argumentos pasados al programa:

Programa


' cálculo del impuesto de un contribuyente
' el programa debe ejecutarse con tres parámetros: casado, hijos, salario
' casado: carácter O si está casado, N si no lo está
' hijos: número de hijos
' salario: salario anual sin céntimos

' no se comprueba la validez de los datos, pero
' se comprueba que haya tres

' declaración obligatoria de las 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)"

' se comprueba que haya 3 argumentos
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' mensaje de error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' salida con código de error 1
    wscript.quit 1
  End If

' se recuperan los argumentos comprobando su validez
' se pasa un argumento al programa sin espacios delante ni detrás
' se utilizarán expresiones regulares para verificar la validez de los datos
  Dim modele, correspondances
  Set modele=new regexp

  ' el estado civil debe estar entre los caracteres oOnN
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' salimos
    wscript.quit 2
  End If
  ' se recupera el valor
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If

  ' «hijos» debe ser un número entero >=0
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' salimos
    wscript.quit 3
  End If
  ' se recupera el valor
  Dim enfants
  enfants=cint(wscript.arguments(1))

  ' el salario debe ser un entero >=0
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' error
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' salir
    wscript.quit 4
  End If
  ' se recupera el valor
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' se definen los datos necesarios para el cálculo del impuesto en 3 tablas
  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)

  ' se calcula el número de participaciones
  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

  ' se calcula el coeficiente familiar y la base imponible
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts

  ' se calcula el impuesto
  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))

  ' se muestra el resultado
  wscript.echo "impôt=" & impot

  ' se sale sin errores
  wscript.quit 0

Resultados

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