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:
| 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 |
| 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 |
| 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)
- 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.
- pode-se querer procurar o padrão várias vezes na sequência (por padrão, isso não é feito)
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:
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.
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
|