Skip to content

4. Manejo de errores

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

Si retomamos el ejemplo de los impuestos que vimos anteriormente, ¿qué sucede si el usuario ingresa 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'

A esto se le llama un «bloqueo inesperado». Se produjo un «bloqueo» en la instrucción hijos=cint(wscript.arguments(1)) porque arguments(1) contenía la cadena «xyzt».

Antes de utilizar un variante del 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 verificar que el contenido de la variante se ajuste a un patrón determinado
  • dejar que se produzca el error, interceptarlo y luego 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 ingresado con el teclado, las funciones vartype y typename nos indicarán que se trata de una cadena de caracteres, ya que así se considera cualquier dato ingresado 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 ha sido inicializada
isNull(var)
devuelve verdadero si la variable var contiene datos no válidos
isArray(var)
devuelve verdadero si var es un array
isObject(var)
devuelve verdadero si var es un objeto

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

Programa
' Lee un dato hasta que se reconozca como un número

Option Explicit

Dim fini, nombre

' se repite el ciclo mientras el dato ingresado no sea correcto
' el bucle se controla mediante una variable booleana de estado «no terminado», que se establece en falso al inicio (= aún 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 leerlo
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' se verifica 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 número entero o no. Para obtener esta información, es necesario realizar pruebas adicionales. El siguiente ejemplo solicita un número entero mayor que 0:

Programa
' se lee un dato hasta que se reconozca como un número entero >0

Option Explicit

Dim fini, nombre

' se repite el ciclo mientras el dato ingresado no sea correcto
' el bucle se controla mediante una variable booleana de estado «no terminado», que se establece en falso al inicio (= aún 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 verifica si el dato leído es de tipo real
    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, como dato interesante, que fue 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 arrojaba los resultados esperados. No detectaba los números enteros positivos. Dejamos que el lector descubra por qué.
  • La condición If (número - int(número)) = 0 no es totalmente confiable. 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 manera exacta, sino aproximada. Y aquí, la operación nombre-int(nombre) dio como resultado 0, con la precisión del computadora.

4.2. Las expresiones regulares

Las expresiones regulares nos permiten validar el formato de una cadena de caracteres. Así, podemos verificar que una cadena que representa una fecha esté en el formato dd/mm/aa. Para ello, se utiliza un patrón y se compara la cadena con dicho patrón. Por lo tanto, 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 representa 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. Por lo tanto, «zo*» corresponde a «z» o a «zoo».
+
Corresponde al carácter anterior una o más veces. Por lo tanto, «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».
.
Corresponde a cualquier carácter único, excepto al carácter de línea nueva.
(patrón)
Busca modèle y guarda 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 ( ), usa "\(" o "\)".
x|y
Corresponde a x o a y. Por ejemplo, «z|foot» corresponde a «z» o a «foot». «(z|f)oo» corresponde a «zoo» o a «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 la «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» en «Bob», sino con todas las «o» en «fooooot». «o{1,}» equivale a «o+» y «o{0,}» equivale a «o*».
{n,m}
m y n son números enteros no negativos. Corresponde a un número de veces del carácter que va desde al menos n hasta, como máximo, m. Por ejemplo, «o{1,3}» corresponde a las tres primeras «o» en «foooooot» y «o{0,1}» equivale a «o?».
[xyz]
Conjunto de caracteres. Corresponde a uno de los caracteres indicados. Por ejemplo, «[abc]» corresponde a la «a» en «plat».
[^xyz]
Conjunto de caracteres negativo. Corresponde a cualquier carácter no indicado. Por ejemplo, «[^abc]» corresponde a la «p» en «plat».
[a-z]
Rango de caracteres. Corresponde a cualquier carácter dentro de la serie especificada. Por ejemplo, «[a-z]» corresponde a cualquier letra minúscula 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 número. Equivale a [0-9].
\D
Corresponde a un carácter que no representa un número. 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
Equivale 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 en 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, tanto «\11» como «\011» corresponden a un carácter de tabulación. "\0011" equivale a "\001" y "1". Los valores de escape octales no deben exceder 256. Si lo hicieran, solo se tomarían en cuenta los dos primeros dígitos en la expresión. Permite utilizar los códigos ASCII en expresiones regulares.
\xn
Equivale 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 en una plantilla puede aparecer una o más 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 inicia y termina la cadena
patrón
el patrón se busca en toda la cadena, comenzando por el inicio de esta.
cadena buscada
patrón
una cadena que termina con un signo de exclamación
!$
una cadena que termina con un punto
\.$
una cadena que comienza con la secuencia //
^//
una cadena que contiene solo una palabra, que puede ir seguida o precedida de espacios
^\s*\w+\s*$
una cadena que contenga dos palabras, que pueden ir precedidas o seguidas de espacios
^\s*\w+\s*\w+\s*$
una cadena que contenga la palabra «secreto»
\bsecret\b

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

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

  • En primer lugar, debemos crear un objeto RegExp (Expresión regular)
set modele=new regexp
  • luego definimos el patrón que queremos probar
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 inicio 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 que corresponde 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 verificar que una cadena contenga una fecha en el 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 formato 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 correspondencia i
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' se recuperan los subelementos de la correspondencia 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 verifica que una entrada del teclado sea un número entero positivo podría escribirse de la siguiente manera:

Programa
' se lee 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 ciclo mientras el dato ingresado no sea correcto
' el bucle se controla mediante una variable booleana finita, que se establece en falso al inicio (= aún 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 verifica 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 patrón determinado puede ser, en ocasiones, todo un reto. El siguiente programa te permite practicar. Te pide un patrón y una cadena, y luego indica si la cadena se ajusta o no al patrón.

Programa
' expresión regular

' queremos verificar que una cadena coincida con 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 ingrese un patrón
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' ¿Ya terminaste?
    If modele.pattern="fin" Then Exit Do
        ' se le pide al usuario las cadenas que se compararán con el patrón
        Do While true
            ' se le pide al usuario que ingrese 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
            ' ¿Listo?
            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 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 manejar los errores de ejecución consiste en dejar que ocurran, recibir una notificación al respecto y manejarlos 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 le indica al sistema (WSH) que nosotros mismos nos encargaremos de gestionar los errores. Después de esta instrucción, el sistema simplemente ignora cualquier error.

on error goto 0

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

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

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

Veamos el siguiente ejemplo:

Programa
Resultados

' error no manejado

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'

Ahora manejemos el error:

Programa
Resultados
' error manejado

Option Explicit
Dim nombre

' nosotros mismos manejamos los errores
On Error Resume Next
nombre=cdbl("abcd")
' ¿Hubo 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 retoma el funcionamiento normal
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0
L'erreur [Type incompatible] s'est produite

Reescribamos el programa para ingresar un número 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 ciclo mientras el dato ingresado no sea correcto
' el bucle se controla mediante una variable booleana de estado «no terminado», que se establece en falso al inicio (= aún no ha terminado)

fini=false
Do While Not fini
  ' se solicita el número
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' se lee el número
  nombre=wscript.stdin.readLine
  ' se verifica el formato de los datos leídos
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' no hay error, es un número
    ' se regresa al modo normal de manejo de errores
    On Error GoTo 0
    ' ¿Es un entero mayor que 0?
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' se regresa al modo normal de manejo 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 manejo de errores tan pronto como termine la secuencia de instrucciones que podría 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: letra O si está casado, N si no lo está
' hijos: número de hijos
' salario: salario anual sin centavos

' No se verifica la validez de los datos, pero
' se verifica 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 verifica 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"
    ' interrupción con código de error 1
    wscript.quit 1
  End If
  
' se recuperan los argumentos verificando su validez
' se pasa un argumento al programa sin espacios ni al principio ni al final
' 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 número 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"
    ' salimos
    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 partes
  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 el ingreso 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 error
  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