4. Gestión de errores
En programación, hay una regla absoluta: un programa nunca debe "bloquearse" de forma incontrolada. Los errores que puedan producirse durante la ejecución del programa deben gestionarse y generar mensajes de error significativos.
Si volvemos al ejemplo de los impuestos comentado anteriormente, ¿qué ocurre si el usuario introduce cualquier cosa para el número de hijos? Veamos este ejemplo:
| 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 llamamos un choque salvaje. Hubo un "choque" en la instrucción children=cint(wscript.arguments(1)) porque argumentos(1) contenía la cadena "xyzt".
Antes de utilizar una variante cuya naturaleza exacta desconocemos, debemos comprobar su subtipo exacto. Hay varias formas de hacerlo:
- 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 corresponde a un determinado modelo
- permitir que se produzca el error, interceptarlo y solucionarlo
Examinamos estos diferentes métodos.
4.1. Conocer el tipo exacto de datos
Recuerde que el vartype o varname se utilizan para identificar el tipo exacto de datos. Esto no siempre es muy útil. Por ejemplo, cuando leemos datos tecleados en el teclado, la etiqueta vartype y typename nos dirá que es una cadena de caracteres, porque así es como se considera cualquier dato escrito en el teclado. Esto no nos dice si la cadena puede considerarse un número válido, por ejemplo. A continuación, utilizaremos otras funciones para acceder a este tipo de información:
isNumeric(expresión) | hace verdadero si la expresión puede utilizarse como un número |
isDate(expresión) | hace verdadero si la expresión puede utilizarse como fecha |
isEmpty(var) | devuelve true si la variable var no ha sido inicializada |
isNull(var) | devuelve true si la variable var contiene datos no válidos |
isArray(var) | devuelve true si var es un array |
isObject(var) | devuelve true si var es un objeto |
El siguiente ejemplo le pide que escriba datos en el teclado hasta que sean reconocidos como un número :
Programa |
' leer los datos hasta que se reconozcan como un número
Option Explicit
Dim fini, nombre
' bucle hasta que los datos introducidos sean correctos
' el bucle está controlado por un booleano finito, puesto a false al principio (= no es finito)
fini=false
Do While Not fini
' pedimos el número
wscript.stdout.write "Tapez un nombre : "
' lo leemos
nombre=wscript.stdin.readLine
' el tipo es necesariamente string cuando se lee
wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
' comprobamos el tipo real de 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 |
| 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 dice si una expresión es un entero o no. Para obtener esta información, necesitamos hacer algunas pruebas adicionales. El siguiente ejemplo pide un entero >0 :
Programa |
' leer datos hasta que se reconozcan como enteros >0
Option Explicit
Dim fini, nombre
' bucle hasta que los datos introducidos sean correctos
' el bucle está controlado por un booleano finito, puesto a false al principio (= no es finito)
fini=false
Do While Not fini
' pedimos el número
wscript.stdout.write "Tapez un nombre entier >0: "
' lo leemos
nombre=wscript.stdin.readLine
' comprobar el tipo real de datos leídos
If isNumeric(nombre) Then
' ¿es un número entero positivo (un número igual a su parte entera)?
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 |
| 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(número) da la parte entera de un número. Un número igual a su parte entera es un número entero.
- Curiosamente, fue necesario utilizar el Si (número-int(número))=0 Y número>0 porque la prueba Si número=int(número) Y número>0 no dio los resultados esperados. No detectó números enteros positivos. Dejamos que el lector averigüe por qué.
- La prueba Si (número-int(número))=0 no es totalmente fiable. Veamos el siguiente ejemplo:
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 aquí, la operación número-int(número) dio 0 a la precisión más cercana del ordenador.
4.2. Expresiones regulares
Las expresiones regulares nos permiten comprobar el formato de una cadena de caracteres. Por ejemplo, podemos comprobar que una cadena que representa una fecha tiene el formato dd/mm/aa. Para ello, utilizamos una plantilla y comparamos la cadena con esta plantilla. En este ejemplo, d m y a deben ser números. El modelo para un formato de fecha válido es entonces "\d\d/\d\d/\d\d" donde el símbolo \d designa un número. En un modelo pueden utilizarse los siguientes símbolos (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 nuevo carácter de 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 veces o varias veces. Por ejemplo, "zo*" corresponde a "z" o "zoo". |
+ | Corresponde al carácter anterior una o más veces. Por ejemplo, "zo+" coincide con "zoo", pero no con "z". |
? | Corresponde al carácter anterior cero o una vez. Por ejemplo, "a?ve?" corresponde a "ve" en "lever". |
. | Corresponde a cualquier carácter individual, excepto el carácter de nueva línea. |
(modelo) | Buscar modelo y almacena la coincidencia. La subcadena correspondiente puede extraerse de la colección Partidos obtenido mediante Item [0]...[n]. Para encontrar coincidencias con caracteres entre paréntesis ( ), utilice "\(" o "\)". |
x|y | Corresponde a x o a y. Por ejemplo, "z|foot" corresponde a "z" o "foot". "(z|f)oo" corresponde a "zoo" o "foo". |
{n} | n es un número entero no negativo. Corresponde exactamente a n veces el carácter. Por ejemplo, "o{2}" no corresponde a la "o" de "Bob", sino a las dos primeras "o "s de "fooooot". |
{n,} | n es un número entero no negativo. Corresponde como mínimo a n veces el carácter. Por ejemplo, "o{2,}" no corresponde a la "o" de "Bob", sino a todas las "o "s de "fooooot". "o{1,}" equivale a "o+" y "o{0,}" a "o*". |
{n,m} | m y n son enteros no negativos. Corresponde como mínimo a n y como máximo m veces el carácter. Por ejemplo, "o{1,3}" corresponde a las tres primeras "o "s de "foooooot" y "o{0,1}" equivale a "o?". |
[xyz] | Juego de caracteres. Corresponde a uno de los caracteres indicados. Por ejemplo, "[abc]" corresponde a la "a" de "plat". |
[^xyz] | Conjunto de caracteres negativos. Corresponde a cualquier carácter no especificado. Por ejemplo, "[^abc]" corresponde a "p" en "plat". |
[a-z] | Rango de caracteres. Corresponde a cualquier carácter del rango especificado. Por ejemplo, "[a-z]" corresponde a cualquier carácter alfabético minúsculo entre "a" y "z". |
[^m-z] | Rango de caracteres negativo. Corresponde a cualquier carácter que no se encuentre en el intervalo especificado. Por ejemplo, "[^m-z]" corresponde a cualquier carácter que no esté entre "m" y "z". |
\b | Corresponde a un límite que representa una palabra, es decir, la posición entre una palabra y un espacio. Por ejemplo, "er" corresponde a "er" en "palanca", pero no a "er" en "verbo". |
\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 dígito. Equivale a [^0-9]. |
\f | Corresponde a un carácter de salto de página. |
\n | Corresponde a un nuevo carácter de línea. |
\r | Corresponde a un carácter de retorno de carro. |
\s | Corresponde a cualquier espacio en blanco, incluyendo espacio, tabulación, salto de página, etc. Equivale a "[ ]". |
\S | Corresponde a cualquier carácter que no sea un espacio en blanco. Equivale a "[^ \f\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 numdonde num es un número entero positivo. Se refiere a coincidencias almacenadas. Por ejemplo, "(.)\1" corresponde a dos caracteres idénticos consecutivos. |
\n | Corresponde a ndonde n es un valor de escape octal. Los valores de escape octales deben contener 1, 2 ó 3 dígitos. Por ejemplo, "\11" y "\011" corresponden ambos a un carácter de tabulación. "\0011" equivale a "\001" & "1". Los valores de escape octales no deben superar 256. Si este fuera el caso, sólo se tendrían en cuenta en la expresión los dos primeros dígitos. Permite utilizar códigos ASCII en expresiones regulares. |
\xn | Corresponde a ndonde n es un valor de escape hexadecimal. Los valores de escape hexadecimales deben contener dos dígitos. Por ejemplo, "\x41" equivale a "A". "\x041" equivale a "\x04" & "1". Permite utilizar códigos ASCII en expresiones regulares. |
Un elemento de un modelo puede estar presente en 1 o más copias. Veamos algunos ejemplos en los que interviene el símbolo \d que representa 1 dígito :
modelo | significado |
\d | un número |
\d? | 0 o 1 dígito |
\d* | 0 o más dígitos |
\d+ | 1 o más dígitos |
\d{2} | 2 cifras |
\d{3,} | al menos 3 dígitos |
\d{5,7} | entre 5 y 7 dígitos |
Imaginemos ahora un modelo capaz de describir el formato esperado para una cadena de caracteres:
cadena de búsqueda | 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 entero sin signo | \d+ |
una secuencia de espacios que pueden estar vacíos | \s* |
un entero sin signo que puede ir precedido o seguido de espacios | \s*\d+\s* |
un número entero que puede ir con signo y precedido o seguido de espacios | \...que no es lo mismo.. |
un número real sin signo que puede ir precedido o seguido de espacios | \s*\d+(.\d*)?\s* |
un número real que puede ir con signo y precedido o seguido de espacios | \s*[+|]?\s*\d+(.\d*)?\s* |
una cadena que contenga la palabra correcta | \bjuste\b |
| | |
Puede especificar en qué punto de la cadena busca el modelo:
modelo | significado |
^modelo | el modelo inicia la cadena |
modelo$ | el modelo termina la cadena |
^model$ | el modelo inicia y termina la cadena |
modelo | el modelo se busca en toda la cadena, empezando por el principio. |
cadena de búsqueda | modelo |
una cadena acabada en signo de exclamación | !$ |
una cadena acabada en punto | \.$ |
una cadena que comienza con la secuencia // | ^// |
una cadena que contiene una sola palabra, posiblemente seguida o precedida de espacios | ^\s*\w+\s*$ |
una cadena que contiene sólo dos palabras, posiblemente seguidas o precedidas de espacios | ^\s*\w+\s*\w+\s*$ |
una cadena que contiene la palabra secreta | \bsecret\b |
Los subconjuntos de un modelo pueden "recuperarse". De este modo, no sólo podemos comprobar que una cadena corresponde a un modelo determinado, sino que también podemos recuperar de esta cadena los elementos correspondientes a los subconjuntos del modelo que se han encerrado entre paréntesis. Así, si analizamos una cadena que contiene una fecha dd/mm/aa y también queremos recuperar los elementos dd, mm, yy de esta fecha, utilizaremos el modelo (\d)/(\d)/(\d).
Utilicemos este ejemplo para ver cómo funciona vbscript.
- primero tenemos que crear un RegExp (Expresión regular)
- entonces establecemos el modelo a probar
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
- puede que no quieras diferenciar entre mayúsculas y minúsculas (por defecto sí). Aquí no importa.
- es posible que desee buscar el modelo varias veces en la cadena (esto no se hace por defecto)
Una búsqueda global sólo tiene sentido si el modelo utilizado no hace referencia al principio o al final de la cadena.
- buscamos todas las coincidencias en el archivo :
set correspondances=modele.execute(chaine)
El método ejecutar un objeto RegExp hace una colección de objetos de tipo match. Este objeto tiene una propiedad valor que es el elemento de cadena correspondiente al modelo. Si hemos escrito modele.global=truepuede haber varias coincidencias. Por ello, el resultado de la ejecutar es una colección de correspondencias.
- el número de coincidencias viene dado por correspondances.count. Si este número es 0, el modelo no se ha encontrado en ninguna parte. El valor de la coincidencia nº i viene dado por coincidencias(i).valor. Si el modelo contiene submodelos entre paréntesis, los elementos de coincidencias(i) correspondiente al paréntesis j en el modelo es coincidencias(i).subcomparaciones(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
' definimos el modelo
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b" ' una fecha en cualquier lugar de la cadena
modele.global=true ' buscaremos el modelo varias veces en la cadena
' el usuario proporciona la cadena en la que buscar el modelo
Dim chaine, correspondances, i
chaine=""
' bucle mientras cadena<>"fin"
Do While true
' se 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
' terminado si cadena=terminado
If chaine="fin" Then Exit Do
' la cadena leída se compara con la plantilla de fecha
Set correspondances=modele.execute(chaine)
' se encontró una coincidencia
If correspondances.count<>0 Then
' tenemos al menos una coincidencia
For i=0 To correspondances.count-1
' mostramos la correspondencia i
wscript.echo "J'ai trouvé la date " & correspondances(i).value
' recuperamos 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 correspondencia
wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
End If
Loop
' acabado
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
|
|
Utilizando expresiones regulares, el programa que comprueba si una entrada del teclado es un número entero positivo podría escribirse de la siguiente manera:
Programa |
' leer los datos hasta que se reconozcan como un número
Option Explicit
Dim fini, nombre
' definimos el modelo de un número entero positivo (que puede ser cero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"
' bucle hasta que los datos introducidos sean correctos
' el bucle está controlado por un booleano finito, puesto a false al principio (= no es finito)
fini=false
Do While Not fini
' pedimos el número
wscript.stdout.write "Tapez un nombre entier >0: "
' lo leemos
nombre=wscript.stdin.readLine
' comprobamos el formato de los datos leídos
Dim correspondances
Set correspondances=modele.execute(nombre)
' ¿Se ha comprobado el modelo?
If correspondances.count<>0 Then
' es un número 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 comprobar que una cadena corresponde a un determinado modelo es a veces un verdadero reto. El siguiente programa te da la oportunidad de practicar. Pide un patrón y una cadena y luego indica si la cadena coincide o no con el patrón.
Programa |
' expresión regular
' queremos comprobar que una cadena corresponde a un modelo
Option Explicit
' definimos el modelo
Dim modele
Set modele=new regexp
modele.global=true ' buscaremos el modelo varias veces en la cadena
' el usuario proporciona la cadena en la que buscar el modelo
Dim chaine, correspondances, i
Do While true
' se pide al usuario que escriba un modelo
wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
modele.pattern=wscript.stdin.readLine
' ¿Terminaste?
If modele.pattern="fin" Then Exit Do
' se pide al usuario las cadenas para compararlas con el modelo
Do While true
' se pide al usuario que escriba un modelo
wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
chaine=wscript.stdin.readLine
' ¿Terminaste?
If chaine="fin" Then Exit Do
' la cadena leída se compara con la plantilla de fecha
Set correspondances=modele.execute(chaine)
' se encontró una coincidencia
If correspondances.count<>0 Then
' tenemos al menos una coincidencia
For i=0 To correspondances.count-1
' mostramos la correspondencia i
wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
Next
Else
' no hay correspondencia
wscript.echo "Je n'ai pas trouvé de correspondance"
End If
Loop
Loop
' terminado
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 errores de ejecución
Otra forma de tratar los errores en tiempo de ejecución es dejar que se produzcan, ser advertido de ellos y luego tratarlos. Normalmente, cuando se produce un error en tiempo de ejecución, WSH muestra un mensaje de error y el programa se detiene. Dos instrucciones nos permiten cambiar esto:
Esta instrucción indica al sistema (WSH) que nosotros mismos manejaremos los errores. Después de esta instrucción, cualquier error es simplemente ignorado por el sistema.
Esta instrucción nos devuelve a la gestión normal de errores.
Cuando el en error reanudar siguiente está activo, tenemos que ocuparnos nosotros mismos de cualquier error. El objeto Err nos ayuda a ello. Este objeto tiene varias propiedades y métodos, de los cuales mencionaremos los dos siguientes:
- número un número entero del último error que se ha producido. 0 significa "ningún error"
- descripción el mensaje de error que el sistema habría mostrado si la instrucción en error reanudar siguiente
Veamos el siguiente ejemplo:
Programa | Resultados |
| ' error no controlado
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 vamos a tratar el error:
Programa | Resultados |
' error gestionado
Option Explicit
Dim nombre
' nosotros mismos nos ocupamos de los errores
On Error Resume Next
nombre=cdbl("abcd")
' ¿hubo un error?
If Err.number<>0 Then
wscript.echo "L'erreur [" & err.description & "] s'est produite"
On Error GoTo 0
wscript.quit 1
End If
' no hay error - vuelve al funcionamiento normal
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0
|
| L'erreur [Type incompatible] s'est produite
|
|
Reescribamos el programa para introducir un entero >0 utilizando este nuevo método:
Programa |
' leer los datos hasta que se reconozcan como un número
Option Explicit
Dim fini, nombre
' bucle hasta que los datos introducidos sean correctos
' el bucle está controlado por un booleano finito, puesto a false al principio (= no es finito)
fini=false
Do While Not fini
' pedimos el número
wscript.stdout.write "Tapez un nombre entier >0: "
' lo leemos
nombre=wscript.stdin.readLine
' comprobamos 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
' volvemos al modo normal de gestión de errores
On Error GoTo 0
' es un número entero >0
If (nombre-int(nombre))=0 And nombre>0 Then
fini=true
End If
End If
' volvemos 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 :
- Este método es a veces el único que puede utilizarse. En este caso, no olvide volver al modo normal de tratamiento de errores en cuanto haya finalizado la secuencia de instrucciones susceptible de generar el error.
4.4. Aplicación al programa de cálculo de impuestos
Volvemos al programa de cálculo de impuestos que ya hemos escrito, esta vez para comprobar la validez de los argumentos pasados al programa:
Programa |
' cálculo de la deuda tributaria del contribuyente
' el programa debe llamarse con tres parámetros: salario de los hijos casados
' casado: carácter Y si está casado, N si no lo está
' hijos: número de hijos
' salario: salario anual sin céntimos
' no se realiza ninguna verificación de la validez de los datos, pero sí
' compruebe que son tres
' declaración obligatoria de 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)"
' comprobamos que hay 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"
' parada con código de error 1
wscript.quit 1
End If
' recuperar los argumentos y comprobar su validez
' un argumento se pasa al programa sin espacios delante y detrás de él
' se utilizarán expresiones regulares para comprobar la validez de los datos
Dim modele, correspondances
Set modele=new regexp
' el estado civil debe ser uno de 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"
' nos vamos
wscript.quit 2
End If
' el valor
Dim marie
If lcase(wscript.arguments(0)) = "o"Then
marie=true
Else
marie=false
End If
' children debe ser un 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"
' nos vamos
wscript.quit 3
End If
' 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"
' nos vamos
wscript.quit 4
End If
' el valor
Dim salaire
salaire=clng(wscript.arguments(2))
' definimos los datos necesarios para calcular el 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 acciones
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
' calculamos la cuota 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
' salimos 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
|