Skip to content

4. Tratamento de erros

Na programação, existe uma regra absoluta: um programa nunca deve «travar» inesperadamente. Todos os erros que possam ocorrer durante a execução do programa devem ser tratados, e devem ser geradas mensagens de erro significativas.

Se voltarmos ao exemplo do imposto discutido anteriormente, o que acontece se o utilizador introduzir qualquer valor para o número de filhos? Vejamos este exemplo:

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

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

Isto é o que se designa por uma falha grave. A instrução enfants=cint(wscript.arguments(1)) provocou uma «falha» porque arguments(1) continha a cadeia de caracteres «xyzt».

Antes de utilizar uma variante cuja natureza exata é desconhecida, deve verificar o seu subtipo exato. Existem várias formas de o fazer:

  • testar o tipo real dos dados contidos numa variante utilizando as funções vartype ou typename
  • utilizar uma expressão regular para verificar se o conteúdo da variante corresponde a um padrão específico
  • deixar que o erro ocorra, para depois o interceptar e tratar

Iremos examinar estes diferentes métodos.

4.1. Determinar o tipo exato de um item de dados

Lembre-se de que as funções vartype e varname permitem determinar o tipo exato de um dado. Isto nem sempre é muito útil. Por exemplo, quando lemos dados digitados no teclado, as funções vartype e typename dir-nos-ão que se trata de uma cadeia de caracteres, uma vez que todos os dados digitados no teclado são tratados como tal. Isto não nos diz se esta cadeia de caracteres pode, por exemplo, ser considerada um número válido. Por isso, utilizamos outras funções para aceder a este tipo de informação:

isNumeric(expressão)
retorna true se a expressão puder ser usada como um número
isDate(expressão)
retorna true se a expressão puder ser usada como uma data
isEmpty(var)
retorna true se a variável var não tiver sido inicializada
isNull(var)
retorna true se a variável var contiver dados inválidos
isArray(var)
retorna true se var for uma matriz
isObject(var)
retorna true se var for um objeto

O exemplo seguinte solicita ao utilizador que introduza dados através do teclado até que sejam reconhecidos como um número:

Programa

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre : "
    ' we read it
    nombre=wscript.stdin.readLine
    ' the type is necessarily string when read
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' test the actual type of data read
    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

' and end
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

A função isNumeric não nos diz se uma expressão é um número inteiro ou não. Para obter esta informação, são necessários testes adicionais. O exemplo seguinte solicita um número inteiro maior que 0:

Programa

' read data until it is recognized as an integer >0

Option Explicit

Dim fini, nombre

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the actual type of data read
    If isNumeric(nombre) Then
        ' is it a positive integer (number equal to its integer part)?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    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

' and end
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

Comentários:

  • int(número) devolve a parte inteira de um número. Um número igual à sua parte inteira é um número inteiro.
  • É interessante notar que tivemos de utilizar o teste If (número - int(número)) = 0 And número > 0 porque o teste If número = int(número) And número > 0 não produziu os resultados esperados. Não detectou números inteiros positivos. Deixamos ao leitor a tarefa de descobrir porquê.
  • O teste If (número - int(número)) = 0 não é totalmente fiável. Vejamos o seguinte exemplo:
Introduza um número inteiro >0: 4.0000000000000000000000001

Obrigado pelo número inteiro >0: 4.0000000000000000000000001

Os números reais não são representados com exatidão, mas sim de forma aproximada. E, neste caso, a operação number-int(number) devolveu 0 com a precisão do computador.

4.2. Expressões regulares

As expressões regulares permitem-nos testar o formato de uma cadeia de caracteres. Desta forma, podemos verificar se uma cadeia de caracteres que representa uma data está no formato dd/mm/aa. Para tal, utilizamos um padrão e comparamos a cadeia de caracteres com esse padrão. Assim, neste exemplo, d, m e y devem ser dígitos. O padrão para um formato de data válido é, então, "\d\d/\d\d/\d\d", onde o símbolo \d denota um dígito. Os símbolos que podem ser utilizados num padrão são os seguintes (documentação da Microsoft):

Caractere
Descrição
\
Designa o caractere seguinte como um caractere especial ou literal. Por exemplo, «n» corresponde ao caractere «n». «\n» corresponde a um caractere de nova linha. A sequência «\\» corresponde a «\», enquanto «\» corresponde a «(».
^
Corresponde ao início da entrada.
$
Corresponde ao fim da entrada.
*
Corresponde ao caractere anterior zero ou mais vezes. Assim, «zo*» corresponde a «z» ou «zoo».
+
Corresponde ao caractere anterior uma ou mais vezes. Assim, «zo+» corresponde a «zoo», mas não a «z».
?
Corresponde ao caractere anterior zero ou uma vez. Por exemplo, "a?ve?" corresponde a "ve" em "lever".
.
Corresponde a qualquer caractere único, exceto o caractere de nova linha.
(padrão)
Procura o padrão e armazena a correspondência. A subcadeia correspondente pode ser recuperada da coleção Matches resultante utilizando Item [0]...[n]. Para encontrar correspondências com caracteres dentro de parênteses ( ), utilize "\(" ou "\)".
x|y
Corresponde a x ou a y. Por exemplo, "z|foot" corresponde a "z" ou a "foot". "(z|f)oo" corresponde a "zoo" ou a "foo".
{n}
n é um número inteiro não negativo. Corresponde exatamente a n ocorrências do caractere. Por exemplo, "o{2}" não corresponde a "o" em "Bob", mas corresponde aos dois primeiros "o"s em "fooooot".
{n,}
n é um número inteiro não negativo. Corresponde a, pelo menos, n ocorrências do caractere. Por exemplo, "o{2,}" não corresponde ao "o" em "Bob", mas corresponde a todos os "o"s em "fooooot". "o{1,}" é equivalente a "o+" e "o{0,}" é equivalente a "o*".
{n,m}
m e n são números inteiros não negativos. Corresponde a, no mínimo, n e, no máximo, m ocorrências do caractere. Por exemplo, "o{1,3}" corresponde aos primeiros três "o"s em "foooooot", e "o{0,1}" corresponde a "o?".
[xyz]
Conjunto de caracteres. Corresponde a qualquer um dos caracteres especificados. Por exemplo, "[abc]" corresponde a "a" em "plat".
[^xyz]
Conjunto de caracteres negativo. Corresponde a qualquer caractere não listado. Por exemplo, "[^abc]" corresponde a "p" em "plat".
[a-z]
Intervalo de caracteres. Corresponde a qualquer caractere no intervalo especificado. Por exemplo, "[a-z]" corresponde a qualquer caractere alfabético minúsculo entre "a" e "z".
[^m-z]
Intervalo de caracteres negativo. Corresponde a qualquer caractere que não esteja no intervalo especificado. Por exemplo, "[^m-z]" corresponde a qualquer caractere que não esteja entre "m" e "z".
\b
Corresponde a um limite de palavra, ou seja, a posição entre uma palavra e um espaço. Por exemplo, "er\b" corresponde a "er" em "lever", mas não a "er" em "verb".
\B
Corresponde a um limite que não representa uma palavra. "en*t\B" corresponde a "ent" em "bien entendu".
\d
Corresponde a um caractere que representa um dígito. Equivalente a [0-9].
\D
Corresponde a um carácter que não seja um dígito. Equivalente a [^0-9].
\f
Corresponde a um caractere de quebra de linha.
\n
Corresponde a um caractere de nova linha.
\r
Equivalente a um caractere de retorno de carro.
\s
Corresponde a qualquer espaço em branco, incluindo espaço, tabulação, quebra de página, etc. Equivalente a "[ \f\n\r\t\v]".
\S
Corresponde a qualquer caractere que não seja um espaço em branco. Equivalente a "[^ \f\n\r\t\v]".
\t
Corresponde a um caractere de tabulação.
\v
Corresponde a um caractere de tabulação vertical.
\w
Corresponde a qualquer caractere que represente uma palavra, incluindo o sublinhado. Equivalente a "[A-Za-z0-9_]".
\W
Corresponde a qualquer caractere que não represente uma palavra. Equivalente a "[^A-Za-z0-9_]".
\num
Corresponde a num, onde num é um número inteiro positivo. Refere-se a correspondências armazenadas. Por exemplo, "(.)\1" corresponde a dois caracteres idênticos consecutivos.
\n
Corresponde a n, onde n é um valor de escape octal. Os valores de escape octais devem consistir em 1, 2 ou 3 dígitos. Por exemplo, "\11" e "\011" correspondem ambos a um caractere de tabulação. "\0011" é equivalente a "\001" e "1". Os valores de escape octais não devem exceder 256. Se excederem, apenas os dois primeiros dígitos são tidos em conta na expressão. Permite que os códigos ASCII sejam utilizados em expressões regulares.
\xn
Corresponde a n, onde n é um valor de escape hexadecimal. Os valores de escape hexadecimais devem consistir em exatamente dois dígitos. Por exemplo, "\x41" corresponde a "A". "\x041" é equivalente a "\x04" e "1". Permite a utilização de códigos ASCII em expressões regulares.

Um elemento num padrão pode aparecer uma ou várias vezes. Vejamos alguns exemplos envolvendo o símbolo \d, que representa um único dígito:

padrão
significado
\d
um dígito
\d?
0 ou 1 dígito
\d*
0 ou mais dígitos
\d+
1 ou mais dígitos
\d{2}
2 dígitos
\d{3,}
pelo menos 3 dígitos
\d{5,7}
entre 5 e 7 dígitos

Agora, imaginemos um modelo capaz de descrever o formato esperado para uma cadeia de caracteres:

cadeia de caracteres alvo
padrão
uma data no formato dd/mm/aa
\d{2}/\d{2}/\d{2}
uma hora no formato hh:mm:ss
\d{2}:\d{2}:\d{2}
um inteiro sem sinal
\d+
uma sequência de espaços, que pode estar vazia
\s*
um inteiro sem sinal que pode ser precedido ou seguido por espaços
\s*\d+\s*
um inteiro que pode ser assinado e precedido ou seguido por espaços
\s*[+|-]?\s*\d+\s*
um número real sem sinal que pode ser precedido ou seguido por espaços
\s*\d+(.\d*)?\s*
um número real que pode ser assinado e precedido ou seguido por espaços
\s*[+|]?\s*\d+(.\d*)?\s*
uma cadeia de caracteres contendo a palavra «just»
\bjuste\b
  

Pode especificar onde procurar o padrão na cadeia de caracteres:

padrão
significado
^padrão
o padrão inicia a cadeia
padrão$
o padrão termina a cadeia
^padrão$
o padrão inicia e termina a cadeia
padrão
o padrão é procurado em qualquer parte da cadeia, começando pelo início.
cadeia de pesquisa
padrão
uma cadeia que termine com um ponto de exclamação
!$
uma cadeia que termina com um ponto
\.$
uma sequência que começa com //
^//
uma cadeia composta por uma única palavra, opcionalmente precedida ou seguida por espaços
^\s*\w+\s*$
uma cadeia composta por duas palavras, opcionalmente seguida ou precedida por espaços
^\s*\w+\s*\w+\s*$
uma cadeia que contém a palavra secret
\bsecret\b

Os subpadrões de um padrão podem ser «extraídos». Assim, não só podemos verificar se uma cadeia corresponde a um determinado padrão, como também podemos extrair dessa cadeia os elementos correspondentes aos subpadrões do padrão que foram colocados entre parênteses. Por exemplo, se estivermos a analisar uma cadeia de caracteres que contenha uma data no formato dd/mm/aa e quisermos extrair os componentes dd, mm e aa dessa data, usaríamos o padrão (\d\d)/(\d\d)/(\d\d).

Vejamos este exemplo para perceber como fazer isto com VBScript.

  • Primeiro, precisamos de criar um objeto RegExp (Expressão Regular)
set modele=new regexp
  • Em seguida, definimos o padrão a ser testado
modele.pattern="(\d\d)/(\d\d)/(\d\d)"
  • Pode querer ignorar maiúsculas e minúsculas (por predefinição, distingue-se entre maiúsculas e minúsculas). Aqui, isso não importa.
modele.IgnoreCase=true
  • Pode querer procurar o padrão várias vezes na cadeia de caracteres (por predefinição, isto não é feito)
modele.Global=true

Uma pesquisa global só faz sentido se o padrão utilizado não se referir ao início ou ao fim da cadeia de caracteres.

  • Em seguida, procuramos todas as ocorrências do padrão na cadeia de caracteres:
set correspondances=modele.execute(chaine)

O método execute de um objeto RegExp devolve uma coleção de objetos match. Este objeto possui uma propriedade value que corresponde à sequência de caracteres que corresponde ao padrão. Se tiver definido pattern.global=true*, poderá haver várias correspondências. É por isso que o resultado do método execute* é uma coleção de objetos match.

  • O número de correspondências é fornecido por `matches.count`. Se este número for 0, significa que o padrão não foi encontrado em nenhum lugar. O valor da correspondência #i é fornecido por `matches(i).value`. Se o padrão contiver subpadrões entre parênteses, então o elemento de `matches(i)` correspondente ao parêntese j no padrão é `matches(i).submatches(j)`.

Tudo isto é demonstrado no exemplo seguinte:

Programa

' regular expression

' we want to check that a string contains a date in dd/mm/yy format

Option Explicit
Dim modele

' we define the
Set modele=new regexp
modele.pattern="\b(\d\d)/(\d\d)/(\d\d)\b"  ' a date anywhere in the chain
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

chaine=""
' loop as long as string<>"end"
Do While true
    ' the user is asked to type a text
    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
    ' the string read is compared with the date template
    Set correspondances=modele.execute(chaine)
    ' was a match found
    If correspondances.count<>0 Then
        ' we have at least one match
        For i=0 To correspondances.count-1
            ' the i correspondence is displayed
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' we retrieve the sub-elements of correspondence 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 correspondence
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' finish
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 expressões regulares, o programa que verifica se uma entrada do teclado é de facto um número inteiro positivo poderia ser escrito da seguinte forma:

Programa

' read data until it is recognized as a number

Option Explicit

Dim fini, nombre

' we define the model of a positive integer (which may be zero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)

fini=false
Do While Not fini
    ' we ask for the number
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' we read it
    nombre=wscript.stdin.readLine
    ' test the format of the data read
    Dim correspondances
    Set correspondances=modele.execute(nombre)
    ' has the model been checked?
    If correspondances.count<>0 Then
        ' it's an integer, but is it >0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
    ' possible error msg
    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

' and end
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 a expressão regular que nos permite verificar se uma cadeia de caracteres corresponde a um determinado padrão pode, por vezes, ser um verdadeiro desafio. O programa seguinte permite-lhe praticar. Pede-lhe um padrão e uma cadeia de caracteres e, em seguida, indica se a cadeia de caracteres corresponde ou não ao padrão.

Programa

' regular expression

' we want to check that a chain corresponds to a model

Option Explicit

' we define the
Dim modele
Set modele=new regexp
modele.global=true                      ' we will search for the model several times in the chain

' the user specifies the string in which to search for the model
Dim chaine, correspondances, i

Do While true
    ' the user is asked to type in a template
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' finished?
    If modele.pattern="fin" Then Exit Do
        ' the user is asked for the strings to be compared with the model
        Do While true
            ' the user is asked to type in a template
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
            ' finished?
            If chaine="fin" Then Exit Do
            ' the string read is compared with the date template
            Set correspondances=modele.execute(chaine)
            ' was a match found
            If correspondances.count<>0 Then
                ' we have at least one match
                For i=0 To correspondances.count-1
                    ' the i correspondence is displayed
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                ' no correspondence
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' finish
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. Tratamento de erros de tempo de execução

Outro método para lidar com erros de tempo de execução consiste em deixá-los ocorrer, ser notificado sobre eles e, em seguida, tratá-los. Normalmente, quando ocorre um erro em tempo de execução, o WSH exibe uma mensagem de erro e o programa pára. Duas instruções permitem-nos alterar este comportamento:

on error resume next

Esta instrução indica ao sistema (WSH) que iremos tratar os erros nós próprios. Após esta instrução, quaisquer erros são simplesmente ignorados pelo sistema.

on error goto 0

Esta instrução faz-nos regressar ao tratamento normal de erros.

Quando a instrução on error resume next está ativa, temos de tratar nós próprios quaisquer erros que possam ocorrer. O objeto Err ajuda-nos a fazer isso. Este objeto tem várias propriedades e métodos, dos quais nos vamos concentrar nos dois seguintes:

  • number: um inteiro que representa o número do último erro ocorrido. 0 significa «sem erro»
  • description: a mensagem de erro que o sistema teria exibido se não tivéssemos emitido a instrução on error resume next

Vejamos o seguinte exemplo:

Programa


' unhandled error
 
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'

Agora vamos tratar do erro:

Programa

' managed error

Option Explicit
Dim nombre

' we manage mistakes ourselves
On Error Resume Next
nombre=cdbl("abcd")
' was there a mistake?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' no error - returns to normal operation
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0

Resultados

L'erreur [Type incompatible] s'est produite

Vamos reescrever o programa para introduzir um número inteiro >0 utilizando este novo método:

Programa


' read data until it is recognized as a number
 
Option Explicit
 
Dim fini, nombre
 
' loop until the data entered is correct
' the loop is controlled by a finite boolean, set to false at the start (= it's not finite)
 
fini=false
Do While Not fini
  ' we ask for the number
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' we read it
  nombre=wscript.stdin.readLine
  ' test the format of the data read
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' no error it's a number
    ' returns to normal error handling mode
    On Error GoTo 0
    ' is it an integer >0
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' returns to normal error handling mode
  On Error GoTo 0
  ' possible error msg
  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
 
' and end
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

Comentários:

  • Este método é, por vezes, o único que pode ser utilizado. Nesse caso, não se esqueça de regressar ao modo normal de tratamento de erros assim que a sequência de instruções suscetível de gerar o erro estiver concluída.

4.4. Aplicação ao programa de cálculo de impostos

Vamos revisitar o programa de cálculo de impostos que escrevemos anteriormente para, desta vez, verificar a validade dos argumentos passados ao programa:

Programa


' calculating a taxpayer's tax liability
' the program must be called with three parameters: married children salary
' married: character Y if married, N if unmarried
' children: number of children
' salary: annual salary without cents
 
' no verification of data validity is performed, but we do
' check that there are three of them
 
' mandatory variable declaration
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)"
 
' we check that there are 3 arguments
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' error msg
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' stop with error code 1
    wscript.quit 1
  End If

' retrieve arguments and check their validity
' an argument is passed to the program without spaces in front and behind it
' use regular expressions to check data validity
  Dim modele, correspondances
  Set modele=new regexp

  ' marital status must be among the characters 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"
    ' we leave
    wscript.quit 2
  End If
  ' the value
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If

  ' children must be an integer >=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"
    ' we leave
    wscript.quit 3
  End If
  ' the value
  Dim enfants
  enfants=cint(wscript.arguments(1))
 
  ' salary must be an integer >=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"
    ' we leave
    wscript.quit 4
  End If
  ' the value
  Dim salaire
  salaire=clng(wscript.arguments(2))

  ' we define the data needed to calculate the tax in 3 tables
  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)

  ' the number of shares is calculated
  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

  ' calculate the family quota and taxable income
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts

  ' tax calculation
  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))

  ' the result is displayed
  wscript.echo "impôt=" & impot

  ' leave without 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