Skip to content

4. Gerenciamento de erros

Na programação, há uma regra absoluta: um programa nunca deve “travar” de forma inesperada. Todos os erros que possam ocorrer durante a execução do programa devem ser gerenciados e mensagens de erro significativas devem ser geradas.

Se retomarmos o exemplo dos impostos tratado anteriormente, o que acontece se o usuário inserir 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'

Isso é o que chamamos de falha repentina. Ocorreu uma “falha” na instrução children=cint(wscript.arguments(1)) porque arguments(1) continha a sequência “xyzt”.

Antes de usar uma variante cuja natureza exata não se conhece, é preciso verificar seu subtipo exato. Isso pode ser feito de diferentes maneiras:

  • testar o tipo real dos dados contidos em uma variante com as funções vartype ou typename
  • usar uma expressão regular para verificar se o conteúdo da variante corresponde a um determinado padrão
  • deixar que o erro ocorra, interceptá-lo e, em seguida, tratá-lo

Analisaremos esses diferentes métodos.

4.1. Conhecer o tipo exato de um dado

Vale lembrar que as funções vartype ou varname permitem determinar o tipo exato de um dado. Isso nem sempre nos ajuda muito. Por exemplo, quando lemos um dado digitado no teclado, as funções vartype e typename nos dirão que se trata de uma sequência de caracteres, pois é assim que todo dado digitado no teclado é considerado. Isso não nos diz se essa sequência pode, por exemplo, ser considerada um número válido. Utilizamos, então, outras funções para ter acesso a esse tipo de informação:

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

O exemplo a seguir solicita que o usuário digite um valor no teclado até que ele seja reconhecido como um número:

Programa
' leitura de um dado até que ele seja reconhecido como um número

Option Explicit

Dim fini, nombre

' repete o ciclo enquanto o dado inserido não estiver correto
' o loop é controlado por uma variável booleana, inicialmente definida como falsa (= ainda não terminou)

fini=false
Do While Not fini
    ' solicita-se o número
    wscript.stdout.write "Tapez un nombre : "
    ' ele é lido
    nombre=wscript.stdin.readLine
    ' o tipo é necessariamente string durante a leitura
    wscript.echo "Type de la donnée lue : " & typename(nombre) & "," & vartype(nombre)
    ' verifica-se o tipo real do dado lido
    If isNumeric(nombre) Then 
        fini=true
    Else
        wscript.echo "Erreur, vous n'avez pas tapé un nombre. Recommencez svp..."
    End If
Loop

' confirmação
wscript.echo "Merci pour le nombre " & nombre

' e fim
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 informa se uma expressão é um número inteiro ou não. Para obter essa informação, é necessário realizar testes adicionais. O exemplo a seguir solicita um número inteiro >0:

Programa
' leitura de um dado até que ele seja reconhecido como um número inteiro >0

Option Explicit

Dim fini, nombre

' o ciclo é repetido enquanto o dado inserido não estiver correto
' o loop é controlado por uma variável booleana definida como falso no início (= ainda não terminou)

fini=false
Do While Not fini
    ' solicita-se o número
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' ele é lido
    nombre=wscript.stdin.readLine
    ' verifica-se se o tipo do dado lido é real
    If isNumeric(nombre) Then
        ' é um inteiro (número igual à sua parte inteira) positivo?
        If (nombre-int(nombre))=0 And nombre>0 Then
            fini=true
        End If
    End If
    ' possível mensagem de erro
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmação
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' e fim
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(nombre) retorna a parte inteira de um número. Um número igual à sua parte inteira é um número inteiro.
  • É interessante notar que foi necessário utilizar o teste If (número - int(número)) = 0 And número > 0, pois o teste If número = int(número) And número > 0 não apresentava os resultados esperados. Ele não detectava os números inteiros positivos. Deixamos ao leitor a tarefa de descobrir o motivo.
  • O teste If (número - int(número)) = 0 não é totalmente confiável. Vejamos o seguinte exemplo de execução:
Tapez un nombre entier >0: 4,0000000000000000000000001

Merci pour le nombre entier >0 : 4,0000000000000000000000001

Os números reais não são representados de forma exata, mas sim aproximada. E, neste caso, a operação nombre-int(nombre) resultou em 0, dentro da precisão do computador.

4.2. Expressões regulares

As expressões regulares nos permitem verificar o formato de uma sequência de caracteres. Assim, podemos verificar se uma sequência que representa uma data está no formato dd/mm/aa. Para isso, utilizamos um padrão e comparamos a sequência com esse padrão. Portanto, neste exemplo, d, m e a devem ser algarismos. O modelo de um formato de data válido é, portanto, “\d\d/\d\d/\d\d”, onde o símbolo \d representa um algarismo. Os símbolos que podem ser usados em um modelo são os seguintes (documentação da Microsoft):

Caractere
Descrição
\
Marca o caractere seguinte como 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 final da entrada.
*
Corresponde ao caractere anterior zero ou mais vezes. Assim, “zo*” corresponde a “z” ou a “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)
Pesquisa por modèle e armazena a correspondência. A subcadeia correspondente pode ser extraída da coleção Matches obtida, usando Item [0]...[n]. Para encontrar correspondências com caracteres entre parênteses ( ), use "\(" ou "\)".
x|y
Corresponde tanto a x quanto 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 vezes o caractere. Por exemplo, “o{2}” não corresponde a “o” em “Bob”, mas aos dois primeiros “o” em “fooooot”.
{n,}
n é um número inteiro não negativo. Corresponde a pelo menos n vezes o caractere. Por exemplo, “o{2,}” não corresponde ao “o” em “Bob”, mas a todos os “o” em “fooooot”. “o{1,}” equivale a “o+” e “o{0,}” equivale a “o*”.
{n,m}
m e n são números inteiros não negativos. Corresponde a pelo menos n e, no máximo, m vezes o caractere. Por exemplo, “o{1,3}” corresponde aos três primeiros “o” em “foooooot” e “o{0,1}” equivale a “o?”.
[xyz]
Conjunto de caracteres. Corresponde a um dos caracteres indicados. Por exemplo, “[abc]” corresponde a “a” em “plat”.
[^xyz]
Conjunto de caracteres negativo. Corresponde a qualquer caractere não indicado. Por exemplo, “[^abc]” corresponde a “p” em “prato”.
[a-z]
Intervalo de caracteres. Corresponde a qualquer caractere na série especificada. Por exemplo, “[a-z]” corresponde a qualquer letra minúscula entre “a” e “z”.
[^m-z]
Intervalo de caracteres negativo. Corresponde a qualquer caractere que não esteja na série especificada. Por exemplo, “[^m-z]” corresponde a qualquer caractere que não esteja entre “m” e “z”.
\b
Corresponde a um delimitador que representa uma palavra, ou seja, à posição entre uma palavra e um espaço. Por exemplo, “er\b” corresponde a “er” em “lever”, mas não a “er” em “verbe”.
\B
Corresponde a um delimitador que não representa uma palavra. “en*t\B” corresponde a “ent” em “bien entendu”.
\d
Corresponde a um caractere que representa um algarismo. É equivalente a [0-9].
\D
Corresponde a um caractere que não representa um algarismo. É equivalente a [^0-9].
\f
Corresponde a um caractere de quebra de página.
\n
Corresponde a um caractere de nova linha.
\r
Corresponde 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 de espaço não em branco. Equivale 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 e inclua um 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 às 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 conter 1, 2 ou 3 dígitos. Por exemplo, “\11” e “\011” correspondem ambos a um caractere de tabulação. "\0011" equivale a "\001" e "1". Os valores de escape octais não devem exceder 256. Se isso ocorrer, apenas os dois primeiros dígitos serão considerados na expressão. Permite usar os códigos ASCII em expressões regulares.
\xn
Corresponde a n, onde n é um valor de escape hexadecimal. Os valores de escape hexadecimais devem conter obrigatoriamente dois dígitos. Por exemplo, "\x41" corresponde a "A". "\x041" equivale a "\x04" e "1". Permite usar os códigos ASCII em expressões regulares.

Um elemento em um modelo pode aparecer uma ou mais vezes. Vejamos alguns exemplos relacionados ao símbolo \d, que representa um dígito:

modelo
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

Imaginemos agora o modelo capaz de descrever o formato esperado para uma sequência de caracteres:

cadeia procurada
modelo
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 número inteiro sem sinal
\d+
uma sequência de espaços, que pode estar vazia
\s*
um número inteiro sem sinal que pode ser precedido ou seguido por espaços
\s*\d+\s*
um número inteiro que pode ser com sinal 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 com sinal e precedido ou seguido por espaços
\s*[+|]?\s*\d+(.\d*)?\s*
uma sequência de caracteres contendo a palavra “justo”
\bjusto\b
  

É possível especificar onde procurar o padrão na sequência:

padrão
significado
^padrão
o padrão inicia a sequência
padrão$
o modelo encerra a sequência
^padrão$
o modelo inicia e encerra a sequência
padrão
o padrão é procurado em toda a sequência, começando pelo início dela.
sequência pesquisada
padrão
uma sequência que termina com um ponto de exclamação
!$
uma sequência que termina com um ponto
\.$
uma sequência que começa com //
^//
uma sequência contendo apenas uma palavra, eventualmente seguida ou precedida por espaços
^\s*\w+\s*$
uma sequência contendo duas palavras, eventualmente seguidas ou precedidas por espaços
^\s*\w+\s*\w+\s*$
uma sequência que contenha a palavra “secret”
\bsecret\b

Os subconjuntos de um padrão podem ser “recuperados”. Assim, não só é possível verificar se uma sequência corresponde a um padrão específico, como também é possível recuperar nessa sequência os elementos correspondentes aos subconjuntos do padrão que foram colocados entre parênteses. Assim, se analisarmos uma sequência que contenha uma data dd/mm/aa e quisermos, além disso, extrair os elementos dd, mm e aa dessa data, utilizaremos o padrão (\d\d)/(\d\d)/(\d\d).

Vejamos, neste exemplo, como se opera com o VBScript.

  • Primeiramente, precisamos 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)"
  • Podemos optar por não distinguir entre maiúsculas e minúsculas (por padrão, essa distinção é feita). Aqui, isso não faz diferença.
modele.IgnoreCase=true
  • pode-se querer procurar o padrão várias vezes na sequência (por padrão, isso não é feito)
modele.Global=true

Uma busca global só faz sentido se o padrão utilizado não se referir ao início ou ao fim da sequência.

  • Procura-se, então, todas as ocorrências do padrão na sequência:
set correspondances=modele.execute(chaine)

O método execute de um objeto RegExp retorna uma coleção de objetos do tipo match. Esse objeto possui uma propriedade value que é o elemento de chaine correspondente ao padrão. Se tiver sido definido modele.global=true, pode haver várias correspondências. É por isso que o resultado do método execute é uma coleção de correspondências.

  • O número de correspondências é dado por correspondances.count. Se esse número for 0, significa que o modelo não foi encontrado em lugar algum. O valor da correspondência nº i é dado por correspondances(i).value. Se o modelo contiver submodelos entre parênteses, então o elemento de correspondances(i) correspondente ao parêntese j do modelo é correspondências(i).submatches(j).

Tudo isso é mostrado no exemplo a seguir:

Programa
' expressão regular

' queremos verificar se uma string contém uma data no formato dd/mm/aa

Option Explicit
Dim modele

' definimos o modelo
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

' é o usuário que fornece a string na qual se buscará o modelo
Dim chaine, correspondances, i

chaine=""
' repetimos o ciclo enquanto a string não for igual a “fim”
Do While true
    ' solicita-se ao usuário que digite um texto
    wscript.stdout.writeLine "Tapez un texte contenant des dates au format jj/mm/aa et fin pour arrêter : "
    chaine=wscript.stdin.readLine
    ' termina se a string for igual a “fin”
    If chaine="fin" Then Exit Do
    ' comparamos a string lida com o modelo de data
    Set correspondances=modele.execute(chaine)
    ' encontrou-se uma correspondência?
    If correspondances.count<>0 Then
        ' há pelo menos uma correspondência
        For i=0 To correspondances.count-1
            ' exibe-se a correspondência i
            wscript.echo "J'ai trouvé la date " & correspondances(i).value
            ' recuperam-se os subelementos da correspondência 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
        ' nenhuma correspondência
        wscript.echo "Je n'ai pas trouvé de date au format jj/mm/aa dans votre texte"
    End If
Loop

' concluído
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

Com expressões regulares, o programa que verifica se uma entrada do teclado é realmente um número inteiro positivo poderia ser escrito da seguinte forma:

Programa
' leitura de um dado até que ele seja reconhecido como um número

Option Explicit

Dim fini, nombre

' define-se o modelo de um número inteiro positivo (que pode ser zero)
Dim modele
Set modele=new regexp
modele.pattern="^\s*\d+\s*$"

' o ciclo é repetido enquanto o dado inserido não estiver correto
' o loop é controlado por uma variável booleana inicializada como falso (= ainda não terminou)

fini=false
Do While Not fini
    ' solicita-se o número
    wscript.stdout.write "Tapez un nombre entier >0: "
    ' ele é lido
    nombre=wscript.stdin.readLine
    ' verifica-se o formato dos dados lidos
    Dim correspondances
    Set correspondances=modele.execute(nombre)
    ' o modelo foi verificado?
    If correspondances.count<>0 Then
        ' é um número inteiro, mas será que é >0?
        nombre=cint(nombre)
        If nombre>0 Then
            fini=true
        End If
    End If
    ' possível mensagem de erro
    If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmação
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' e fim
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 permita verificar se uma sequência corresponde a um determinado padrão pode, às vezes, ser um verdadeiro desafio. O programa a seguir permite que você pratique. Ele solicita um padrão e uma sequência e, em seguida, indica se a sequência corresponde ou não ao padrão.

Programa
' expressão regular

' queremos verificar se uma string corresponde a um padrão

Option Explicit

' definimos o padrão
Dim modele
Set modele=new regexp
modele.global=true                      ' on recherchera le modèle plusieurs fois dans la chaîne

' é o usuário que fornece a sequência na qual se buscará o padrão
Dim chaine, correspondances, i

Do While true
    ' solicita-se ao usuário que digite um padrão
    wscript.stdout.write "Tapez le modèle à tester et fin pour arrêter : "
    modele.pattern=wscript.stdin.readLine
    ' Concluído?
    If modele.pattern="fin" Then Exit Do
        ' solicita-se ao usuário as sequências a serem comparadas com o modelo
        Do While true
            ' solicita-se ao usuário que digite um padrão
            wscript.stdout.writeLine "Tapez la chaîne à tester avec le modèle [" & modele.pattern & "] et fin pour arrêter : "
            chaine=wscript.stdin.readLine
            ' Concluído?
            If chaine="fin" Then Exit Do
            ' compara-se a sequência lida com o modelo de data
            Set correspondances=modele.execute(chaine)
            ' foi encontrada uma correspondência?
            If correspondances.count<>0 Then
                ' há pelo menos uma correspondência
                For i=0 To correspondances.count-1
                    ' exibe-se a correspondência i
                    wscript.echo "J'ai trouvé la correspondance " & correspondances(i).value
                Next
            Else
                ' nenhuma correspondência
                wscript.echo "Je n'ai pas trouvé de correspondance"
            End If
    Loop
Loop

' concluído
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 erros de execução

Outro método para lidar com erros de execução é deixá-los ocorrer, ser notificado sobre eles e, então, tratá-los. Normalmente, quando ocorre um erro durante a execução, o WSH exibe uma mensagem de erro e o programa é interrompido. Duas instruções nos permitem alterar esse comportamento:

on error resume next

Essa instrução indica ao sistema (WSH) que nós mesmos trataremos dos erros. Após essa instrução, qualquer erro é simplesmente ignorado pelo sistema.

on error goto 0

Essa instrução nos leva de volta ao funcionamento normal de gerenciamento de erros.

Quando a instrução on error resume next está ativa, devemos lidar nós mesmos com os erros que possam ocorrer. O objeto **Err** nos ajuda nisso. Esse objeto possui diversas propriedades e métodos, dos quais destacaremos os dois seguintes:

  • number: um número inteiro correspondente ao último erro ocorrido. 0 significa “nenhum 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 exemplo a seguir:

Programa
Resultados

' erro não tratado

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'

Vamos agora tratar o erro:

Programa
Resultados
' erro tratado

Option Explicit
Dim nombre

' nós mesmos tratamos dos erros
On Error Resume Next
nombre=cdbl("abcd")
' houve algum erro?
If Err.number<>0 Then
    wscript.echo "L'erreur [" & err.description & "] s'est produite"
    On Error GoTo 0
    wscript.quit 1
End If
' sem erro — retornamos ao funcionamento normal
On Error GoTo 0
wscript.echo "nombre=" & nombre
wscript.quit 0
L'erreur [Type incompatible] s'est produite

Vamos reescrever o programa para inserir um número inteiro >0 usando esse novo método:

Programa

' leitura de um dado até que ele seja reconhecido como um número

Option Explicit

Dim fini, nombre

' o ciclo se repete até que o dado inserido esteja correto
' o loop é controlado por uma variável booleana, inicialmente definida como falsa (= ainda não terminou)

fini=false
Do While Not fini
  ' solicita-se o número
  wscript.stdout.write "Tapez un nombre entier >0: "
  ' ele é lido
  nombre=wscript.stdin.readLine
  ' verifica-se o formato dos dados lidos
  On Error Resume Next
  nombre=cdbl(nombre)
  If err.number=0 Then
    ' sem erro, é um número
    ' retornamos ao modo normal de gerenciamento de erros
    On Error GoTo 0
    ' é um número inteiro >0
    If (nombre-int(nombre))=0 And nombre>0 Then
      fini=true
    End If
  End If
  ' retornamos ao modo normal de gerenciamento de erros
  On Error GoTo 0
  ' possível mensagem de erro
  If Not fini Then wscript.echo "Erreur, vous n'avez pas tapé un nombre entier >0. Recommencez svp..."
Loop

' confirmação
wscript.echo "Merci pour le nombre entier >0 : " & nombre

' e fim
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

Observações:

  • Esse método é, às vezes, o único utilizável. Nesse caso, não se deve esquecer de retornar ao modo normal de gerenciamento de erros assim que a sequência de instruções suscetível de gerar o erro for concluída.

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

Retomamos o programa de cálculo de impostos já escrito para, desta vez, verificar a validade dos argumentos passados ao programa:

Programa

' cálculo do imposto de um contribuinte
' o programa deve ser chamado com três parâmetros: casado, filhos, salário
' casado: caractere O se casado, N se solteiro
' filhos: número de filhos
' salário: salário anual sem os centavos

' não é feita nenhuma verificação da validade dos dados, mas
' verifica se há, de fato, três

' declaração obrigatória das variáveis
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)"

' verifica-se se há 3 argumentos
  Dim nbArguments
  nbArguments=wscript.arguments.count
  If nbArguments<>3 Then
    ' mensagem de erro
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect"
    ' interrupção com código de erro 1
    wscript.quit 1
  End If
  
' recuperam-se os argumentos, verificando sua validade
' um argumento é passado para o programa sem espaços antes e depois
' serão utilizadas expressões regulares para verificar a validade dos dados
  Dim modele, correspondances
  Set modele=new regexp

  ' o estado civil deve estar entre os caracteres oOnN
  modele.pattern="^[oOnN]$"
  Set correspondances=modele.execute(wscript.arguments(0))
  If correspondances.count=0 Then
    ' erro
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect"
    ' saímos
    wscript.quit 2
  End If
  ' recuperamos o valor
  Dim marie
  If lcase(wscript.arguments(0)) = "o"Then
    marie=true
  Else
    marie=false
  End If
  
  ' filhos deve ser um número inteiro >=0
  modele.pattern="^\d{1,2}$"
  Set correspondances=modele.execute(wscript.arguments(1))
  If correspondances.count=0 Then
    ' erro
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect"
    ' saindo
    wscript.quit 3
  End If
  ' recuperando o valor
  Dim enfants
  enfants=cint(wscript.arguments(1))

  ' o salário deve ser um número inteiro >= 0
  modele.pattern="^\d{1,9}$"
  Set correspondances=modele.execute(wscript.arguments(2))
  If correspondances.count=0 Then
    ' erro
    wscript.echo syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect"
    ' saindo
    wscript.quit 4
  End If
  ' recuperamos o valor
  Dim salaire
  salaire=clng(wscript.arguments(2))
  
  ' definem-se os dados necessários para o cálculo do imposto em 3 tabelas
  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)

  ' calcula-se o número de cotas
  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
  
  ' calcula-se o quociente familiar e a renda tributável
  Dim revenu, qf
  revenu=0.72*salaire
  qf=revenu/nbParts
  
  ' calcula-se o imposto
  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))
  
  ' exibe-se o resultado
  wscript.echo "impôt=" & impot
  
  ' saímos sem erros
  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