Skip to content

2. Noções básicas da linguagem VB.NET

2.1. Introdução

Abordamos o VB.NET, em primeiro lugar, como uma linguagem de programação clássica. Abordaremos os objetos mais tarde.

Num programa, encontramos duas coisas

  • dados
  • as instruções que os manipulam

Normalmente, procura-se separar os dados das instruções:

2.2. Os dados de VB.NET

VB.NET utilizam os seguintes tipos de dados:

  1. números inteiros, reais e decimais
  1. caracteres e cadeias de caracteres
  2. valores booleanos
  3. datas
  4. objetos

2.2.1. Os tipos de dados predefinidos

Tipo VB
Tipo .NET equivalente
Tamanho
Intervalo de valores
Booleano
System.Boolean
2 bytes
Verdadeiro ou Falso.
Byte
System.Byte
1 byte
0 a 255 (sem sinal).
Caractere
System.Char
2 bytes
0 a 65 535 (sem sinal).
Data
System.DateTime
8 bytes
0:00:00 de 1 de janeiro de 0001 a 23:59:59 de 31 de dezembro de 9999.
Decimal
System.Decimal
16 octetos
0 a +/-79 228 162 514 264 337 593 543 950 335 sem casas decimais; 0 a +/-7,9228162514264337593543950335 com 28 casas decimais; sendo o menor número diferente de zero +/-0,0000000000000000000000000001 (+/-1E-28).
Duplo
System.Double
8 octetos
-1,79769313486231E+308 a
-4,94065645841247E-324 para os valores negativos; 4,94065645841247E-324 a 1,79769313486231E+308 para os valores positivos.
Inteiro
System.Int32
4 bytes
-2 147 483 648 a 2 147 483 647.
Long
System.Int64
8 bytes
-9 223 372 036 854 775 808 a 9 223 372 036 854 775 807.
Objeto
System.Object
4 bytes
Qualquer tipo pode ser armazenado numa variável do tipo Object.
Short
System.Int16
2 bytes
-32 768 a 32 767.
Single
System.Single
4 bytes
-3,402823E+38 a -1,401298E-45 para os valores negativos; 1,401298E-45 a 3,402823E+38 para os valores positivos.
String
System.String (classe)
 
0 a cerca de 2 mil milhões de caracteres Unicode.

Na tabela acima, verifica-se que existem dois tipos possíveis para um inteiro de 32 bits: Integer e System.Int32. Ambos os tipos são intercambiáveis. O mesmo se aplica aos outros tipos VB e aos seus equivalentes na plataforma .NET. Eis um exemplo de programa:


Module types
    Sub Main()
        ' números inteiros
        Dim var1 As Integer = 100
        Dim var2 As Long = 10000000000L
        Dim var3 As Byte = 100
        Dim var4 As Short = 4
        ' números reais
        Dim var5 As Decimal = 4.56789D
        Dim var6 As Double = 3.4
        Dim var7 As Single = -0.000103F
        ' data
        Dim var8 As Date = New Date(2003, 1, 1, 12, 8, 4)
        ' booleano
        Dim var9 As Boolean = True
        ' caractere
        Dim var10 As Char = "A"c
        ' cadeia de caracteres
        Dim var11 As String = "abcde"
        ' objeto
        Dim var12 As Object = New Object
        ' exibições
        Console.Out.WriteLine("var1=" + var1.ToString)
        Console.Out.WriteLine("var2=" + var2.ToString)
        Console.Out.WriteLine("var3=" + var3.ToString)
        Console.Out.WriteLine("var4=" + var4.ToString)
        Console.Out.WriteLine("var5=" + var5.ToString)
        Console.Out.WriteLine("var6=" + var6.ToString)
        Console.Out.WriteLine("var7=" + var7.ToString)
        Console.Out.WriteLine("var8=" + var8.ToString)
        Console.Out.WriteLine("var9=" + var9.ToString)
        Console.Out.WriteLine("var10=" + var10)
        Console.Out.WriteLine("var11=" + var11)
        Console.Out.WriteLine("var12=" + var12.ToString)
    End Sub
End Module

A execução produz os seguintes resultados:

var1=100
var2=10000000000
var3=100
var4=4
var5=4,56789
var6=3,4
var7=-0,000103
var8=01/01/2003 12:08:04
var9=True
var10=A
var11=abcde
var12=System.Object

2.2.2. Notação dos dados literais

Integer
145, -7, &FF (hexadecimal)
Long
100000L
Double
134,789, -45E-18 (-45 × 10⁻¹⁸)
Single
134.789F, -45E-18F (-45 10⁻¹⁸)
Decimal
100000D
Char
"A"c
String
"hoje"
Boolean
verdadeiro, falso
date
New Date(2003, 1, 1) para 01/01/2003

É importante destacar os seguintes pontos:

  • 100000L, o L significa que o número é considerado um inteiro longo
  • 134.789F, o «F» significa que o número é considerado um número real de precisão simples
  • 100000D, o D significa que o número é considerado um número real decimal
  • "A"c, para converter a cadeia de caracteres "A" no carácter 'A'
  • A cadeia de caracteres está entre aspas. Se a cadeia tiver de conter o caractere ", este deve ser duplicado, como em "abcd""e", para representar a cadeia [abcd"e].

2.2.3. Declaração dos dados

2.2.3.1. Função das declarações

Um programa manipula dados caracterizados por um nome e um tipo. Estes dados são armazenados na memória. No momento da compilação do programa, o compilador atribui a cada dado um local na memória caracterizado por um endereço e um tamanho. Faz-o com base nas declarações feitas pelo programador. Além disso, estas permitem ao compilador detetar erros de programação. Assim, a operação x=x*2 será declarada como errada se x for, por exemplo, uma cadeia de caracteres.

2.2.3.2. Declaração de constantes

A sintaxe para declarar uma constante é a seguinte:

const identificador as tipo=valor

por exemplo, [const PI as double=3.141592]. Porquê declarar constantes?

  1. A leitura do programa será mais fácil se tivermos atribuído à constante um nome significativo: [const taux_tva as single=0.186F]
  2. A modificação do programa será mais fácil se a «constante» vier a mudar. Assim, no caso anterior, se a taxa de IVA passar para 33%, a única alteração a fazer será modificar a instrução que define o seu valor: [const taux_tva as single=0.336F]. Se tivéssemos utilizado 0,186 explicitamente no programa, seria necessário alterar inúmeras instruções.

2.2.3.3. Declaração de variáveis

Uma variável é identificada por um nome e está associada a um tipo de dados. VB.NET não distingue entre maiúsculas e minúsculas. Assim, as variáveis FIN e fin são idênticas. As variáveis podem ser inicializadas no momento da sua declaração. A sintaxe para declarar uma ou mais variáveis é:

dim variável1, variável2, ..., variáveln as identificador_de_tipo

onde identificateur_de_type é um tipo predefinido ou um tipo definido pelo programador.

2.2.4. As conversões entre números e cadeias de caracteres

nombre -> chaîne
nombre.ToString ou "" & número ou CType(número, String)
objet -> chaîne
objet.ToString
chaine -> Integer
Integer.Parse(cadeia) ou Int32.Parse
chaîne -> Long
Long.Parse (cadeia) ou Int64.Parse
chaîne -> Double
Double.Parse (cadeia)
chaîne -> Single
Single.Parse (cadeia de caracteres)

A conversão de uma cadeia de caracteres num número pode falhar se a cadeia não representar um número válido. Nesse caso, é gerado um erro fatal denominado «exceção» em VB.NET. Este erro pode ser tratado através da seguinte cláusula try/catch:

try
        appel de la fonction susceptible de générer l'exception
 catch e as Exception
        traiter l'exception e
end try
instruction suivante

Se a função não gerar uma exceção, passa-se então para a instrução seguinte; caso contrário, passa-se para o corpo da cláusula catch e, em seguida, para a instrução seguinte. Voltaremos mais tarde à gestão de exceções. Aqui está um programa que apresenta as principais técnicas de conversão entre números e cadeias de caracteres. Neste exemplo, a função exibe no ecrã o valor do seu parâmetro. Assim, affiche(S) exibe o valor de S no ecrã.


' diretivas
Option Strict On

' espaços de nomes importados
Imports System

' o módulo de teste
Module Module1

    Sub Main()
        ' procedimento principal
        ' dados locais
        Dim S As String
        Const i As Integer = 10
        Const l As Long = 100000
        Const f As Single = 45.78F
        Dim d As Double = -14.98

        ' número --> cadeia
        affiche(CType(i, String))
        affiche(CType(l, String))
        affiche(CType(f, String))
        affiche(CType(d, String))

        'booleano --> cadeia
        Const b As Boolean = False
        affiche(b.ToString)

        ' cadeia de caracteres --> inteiro
        Dim i1 As Integer = Integer.Parse("10")
        affiche(i1.ToString)
        Try
            i1 = Integer.Parse("10.67")
            affiche(i1.ToString)
        Catch e As Exception
            affiche("Erreur [10.67] : " + e.Message)
        End Try

        ' cadeia de caracteres --> inteiro longo
        Dim l1 As Long = Long.Parse("100")
        affiche("" + l1.ToString)
        Try
            l1 = Long.Parse("10.675")
            affiche("" & l1)
        Catch e As Exception
            affiche("Erreur [10.675] : " + e.Message)
        End Try

        ' cadeia de caracteres --> duplo
        Dim d1 As Double = Double.Parse("100,87")
        affiche(d1.ToString)
        Try
            d1 = Double.Parse("abcd")
            affiche("" & d1)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try

        ' cadeia de caracteres --> single
        Dim f1 As Single = Single.Parse("100,87")
        affiche(f1.ToString)
        Try
            d1 = Single.Parse("abcd")
            affiche(f1.ToString)
        Catch e As Exception
            affiche("Erreur [abcd] : " + e.Message)
        End Try
    End Sub

    ' exibe
    Public Sub affiche(ByVal S As String)
        Console.Out.WriteLine("S=" + S)
    End Sub
End Module

Os resultados obtidos são os seguintes:

S=10
S=100000
S=45,78
S=-14,98
S=False
S=10
S=Erreur [10.67] : Le format de la chaîne d'entrée est incorrect.
S=100
S=Erreur [10.675] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.
S=100,87
S=Erreur [abcd] : Le format de la chaîne d'entrée est incorrect.

Note-se que os números reais na forma de cadeia de caracteres devem utilizar a vírgula e não o ponto decimal. Assim, escrever-se-á Dim d As Double = -14.98, mas Dim d1 As Double = Double.Parse("100,87")

2.2.5. As tabelas de dados

Uma tabela VB.NET é um objeto que permite agrupar, sob um único identificador, dados do mesmo tipo. A sua declaração é a seguinte:

Dim Tabela(n) as tipo ou Dim Tabela() as tipo = New tipo(n) {}

onde n é o índice do último elemento da tabela. A sintaxe Tableau(i) designa o dado n.º i, em que i pertence ao intervalo [0,n]. Qualquer referência ao dado Tableau(i), em que i não pertença ao intervalo [0,n], provocará uma exceção. Uma matriz pode ser inicializada ao mesmo tempo que é declarada. Nesse caso, não é necessário indicar o número do último elemento.


        Dim entiers() As Integer = {0, 10, 20, 30}

Os tabuletos têm uma propriedade Length, que corresponde ao número de elementos do tabuleto. Eis um programa de exemplo:


Module tab0
    Sub Main()
        ' uma primeira tabela
        Dim tab0(5) As Integer
        For i As Integer = 0 To UBound(tab0)
            tab0(i) = i
        Next
        For i As Integer = 0 To UBound(tab0)
            Console.Out.WriteLine("tab0(" + i.ToString + ")=" + tab0(i).tostring)
        Next

        ' um segundo quadro
        Dim tab1() As Integer = New Integer(5) {}
        For i As Integer = 0 To tab1.Length - 1
            tab1(i) = i * 10
        Next
        For i As Integer = 0 To tab1.Length - 1
            Console.Out.WriteLine("tab1(" + i.ToString + ")=" + tab1(i).tostring)
        Next
    End Sub
End Module

e a sua execução:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Uma matriz bidimensional pode ser declarada da seguinte forma:

Dim Tabela(n,m) as Tipo ou Dim Tabela(,) as Tipo = New Tipo(n,m) {}

onde n+1 é o número de linhas e m+1 o número de colunas. A sintaxe Matriz(i,j) refere-se ao elemento j da linha i da Matriz. A matriz bidimensional também pode ser inicializada ao mesmo tempo que é declarada:


        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}

O número de elementos em cada uma das dimensões pode ser obtido através do método GetLenth(i), em que i=0 representa a dimensão correspondente ao primeiro índice, i=1 a dimensão correspondente ao segundo índice, …Eis um programa de exemplo:


Module Module2
    Sub Main()
        ' um primeiro quadro
        Dim tab0(2, 1) As Integer
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                tab0(i, j) = i * 10 + j
            Next
        Next
        For i As Integer = 0 To UBound(tab0)
            For j As Integer = 0 To tab0.GetLength(1) - 1
                Console.Out.WriteLine("tab0(" + i.ToString + "," + j.ToString + ")=" + tab0(i, j).tostring)
            Next
        Next

        ' um segundo quadro
        Dim tab1(,) As Integer = New Integer(2, 1) {}
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                tab1(i, j) = i * 100 + j
            Next
        Next
        For i As Integer = 0 To tab1.GetLength(0) - 1
            For j As Integer = 0 To tab1.GetLength(1) - 1
                Console.Out.WriteLine("tab1(" + i.ToString + "," + j.ToString + ")=" + tab1(i, j).tostring)
            Next
        Next
    End Sub
End Module

e os resultados da sua execução:

tab0(0)=0
tab0(1)=1
tab0(2)=2
tab0(3)=3
tab0(4)=4
tab0(5)=5
tab1(0)=0
tab1(1)=10
tab1(2)=20
tab1(3)=30
tab1(4)=40
tab1(5)=50

Uma matriz de matrizes é declarada da seguinte forma:

Dim Tabela(n)() as Tipo ou Dim Tabela()() as Tipo = new Tipo(n)()

A declaração acima cria uma matriz com n+1 linhas. Cada elemento Matriz(i) é uma referência a uma matriz unidimensional. Estas matrizes não são criadas durante a declaração acima. O exemplo abaixo ilustra a criação de uma matriz de matrizes:


         ' uma matriz de matrizes
        Dim noms()() As String = New String(3)() {}
         ' inicialização
        For i = 0 To noms.Length - 1
            noms(i) = New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next

Aqui, noms(i) é uma matriz com i+1 elementos. Como noms(i) é uma matriz, noms(i).Length é o seu número de elementos. Segue-se um exemplo que reúne os três tipos de matrizes que acabámos de apresentar:


' diretivas
Option Strict On
Option Explicit On 

' importações
Imports System

' classe de teste
Module test
    Sub main()
        ' um tabuleiro unidimensional inicializado
        Dim entiers() As Integer = {0, 10, 20, 30}
        Dim i As Integer
        For i = 0 To entiers.Length - 1
            Console.Out.WriteLine("entiers[" & i & "]=" & entiers(i))
        Next

        ' um tabuleiro de duas dimensões inicializado
        Dim réels(,) As Double = {{0.5, 1.7}, {8.4, -6}}
        Dim j As Integer
        For i = 0 To réels.GetLength(0) - 1
            For j = 0 To réels.GetLength(1) - 1
                Console.Out.WriteLine("réels[" & i & "," & j & "]=" & réels(i, j))
            Next
        Next

        ' um array de arrays
        Dim noms()() As String = New String(3)() {}

        ' inicialização
        For i = 0 To noms.Length°- 1
            noms(i) =°New String(i) {}
            For j = 0 To noms(i).Length - 1
                noms(i)(j) = "nom" & i & j
            Next
        Next

        ' visualização
        For i = 0 To noms.Length°- 1
            For j = 0 To noms(i).Length - 1
                Console.Out.WriteLine("noms[" & i & "][" & j & "]=" & noms(i)(j))
            Next
        Next
    End Sub
End Module

Ao executar o código, obtemos os seguintes resultados:

entiers[0]=0
entiers[1]=10
entiers[2]=20
entiers[3]=30
réels[0,0]=0,5
réels[0,1]=1,7
réels[1,0]=8,4
réels[1,1]=-6
noms[0][0]=nom00
noms[1][0]=nom10
noms[1][1]=nom11
noms[2][0]=nom20
noms[2][1]=nom21
noms[2][2]=nom22
noms[3][0]=nom30
noms[3][1]=nom31
noms[3][2]=nom32
noms[3][3]=nom33

2.3. As instruções básicas do VB.NET

Distinguem-se

1 as instruções elementares executadas pelo computador.

2 as instruções de controlo do andamento do programa.

As instruções elementares tornam-se evidentes quando se analisa a estrutura de um microcomputador e dos seus periféricos.

  1. leitura de informações provenientes do teclado

  2. processamento de informações

  3. gravação de informações no ecrã

  4. leitura de informações provenientes de um ficheiro no disco

  5. gravação de informações num ficheiro no disco

2.3.1. Escrita no ecrã

Existem várias instruções para escrever no ecrã:

Console.Out.WriteLine(expression)
Console.WriteLine(expression)
Console.Error.WriteLine (expression)

onde expression representa qualquer tipo de dados que possa ser convertido numa cadeia de caracteres para ser apresentado no ecrã. Nos exemplos vistos até agora, utilizámos apenas a instrução Console.Out.WriteLine(expressão).

A classe System.Console dá acesso às operações de escrita no ecrã (Write, WriteLine). A classe Console tem duas propriedades, Out e Error, que são fluxos de escrita do tipo StreamWriter:

  • Console.WriteLine() é equivalente a Console.Out.WriteLine() e escreve no fluxo Out normalmente associado ao ecrã.
  • Console.Error.WriteLine() escreve no fluxo Error, que também está normalmente associado ao ecrã.

Os fluxos Out e Error estão associados, por predefinição, ao ecrã. No entanto, podem ser redirecionados para ficheiros de texto durante a execução do programa, como veremos em breve.

2.3.2. Leitura de dados introduzidos pelo teclado

O fluxo de dados proveniente do teclado é designado pelo objeto Console.In do tipo StreamReader. Este tipo de objeto permite ler uma linha de texto com o método ReadLine:


        Dim ligne As String = Console.In.ReadLine()

A linha digitada no teclado é armazenada na variável ligne e pode, em seguida, ser processada pelo programme.Le. O fluxo de entrada pode ser redirecionado para um ficheiro, tal como os fluxos de saída e de erro.

2.3.3. Exemplo de entradas e saídas

Eis um pequeno programa que ilustra as operações de entrada e saída do teclado/ecrã:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

' módulo
Module io1
    Sub Main()
        ' gravação no fluxo Out
        Dim obj As New Object
        Console.Out.WriteLine(("" & obj.ToString))

        ' gravação no fluxo Error
        Dim i As Integer = 10
        Console.Error.WriteLine(("i=" & i))

        ' leitura de uma linha introduzida pelo teclado
        Console.Out.Write("Tapez une ligne : ")
        Dim ligne As String = Console.In.ReadLine()
        Console.Out.WriteLine(("ligne=" + ligne))
    End Sub
End Module

e os resultados da execução:

System.Object
i=10
Tapez une ligne : ceci est un essai
ligne=ceci est un essai

As instruções


        Dim obj As New Object
        Console.Out.WriteLine(obj.ToString)

servem apenas para demonstrar que qualquer objeto pode ser exibido. Não pretendemos aqui explicar o significado do que é exibido.

2.3.4. Redirecionamento de E/S

No DOS/Windows, existem três dispositivos padrão denominados:

  1. dispositivo de entrada padrão — designa, por predefinição, o teclado e tem o n.º 0
  2. dispositivo de saída padrão — designa, por predefinição, o ecrã e tem o n.º 1
  3. dispositivo de erro padrão — designa, por predefinição, o ecrã e tem o n.º 2

No VB.NET, o fluxo de escrita Console.Out escreve no dispositivo 1, o fluxo de escrita Console.Error escreve no dispositivo 2 e o fluxo de leitura Console.In lê os dados provenientes do dispositivo 0. Ao iniciar um programa numa janela do DOS no Windows, é possível definir quais serão os dispositivos 0, 1 e 2 para o programa em execução. Consideremos a seguinte linha de comando:

pg arg1 arg2 .. argn

Através dos argumentos argi do programa pg, é possível redirecionar os dispositivos de E/S padrão para ficheiros:

0<in.txt
o fluxo de entrada padrão n.º 0 é redirecionado para o ficheiro in.txt. No programa, o fluxo Console.In irá, portanto, obter os seus dados do ficheiro in.txt.
 
1>out.txt
redireciona a saída n.º 1 para o ficheiro out.txt. Isto significa que, no programa, o fluxo Console.Out gravará os seus dados no ficheiro out.txt
  
1>>out.txt
o mesmo, mas os dados gravados são adicionados ao conteúdo atual do ficheiro out.txt.
  
2>error.txt
redireciona a saída n.º 2 para o ficheiro error.txt. Isto significa que, no programa, o fluxo Console.Error irá gravar os seus dados no ficheiro error.txt
  
2>>error.txt
o mesmo, mas os dados gravados são adicionados ao conteúdo atual do ficheiro error.txt.
  
1>out.txt 2>error.txt
Os dispositivos 1 e 2 são ambos redirecionados para ficheiros
  

Note-se que, para redirecionar os fluxos de E/S do programa pg para ficheiros, o programa pg não precisa de ser alterado. É o programa OS que define a natureza dos dispositivos 0, 1 e 2. Consideremos o seguinte programa:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

' redirecionamentos
Module console2
    Sub Main()
        ' leitura do fluxo In
        Dim data As String = Console.In.ReadLine()
        ' gravação do fluxo de saída
        Console.Out.WriteLine(("écriture dans flux Out : " + data))
        ' gravação no fluxo de erros
        Console.Error.WriteLine(("écriture dans flux Error : " + data))
    End Sub
End Module

Vamos compilar este programa:

dos>vbc es2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir
24/02/2004  15:39                  416 es2.vb
11/03/2004  08:20                3 584 es2.exe

Vamos fazer uma primeira execução:

dos>es2.exe
un premier test
écriture dans flux Out : un premier test
écriture dans flux Error : un premier test

A execução anterior não redireciona nenhum dos fluxos de E/S padrão In, Out e Error. Vamos agora redirecionar os três fluxos. O fluxo In será redirecionado para um ficheiro in.txt, o fluxo Out para o ficheiro out.txt e o fluxo Error para o ficheiro error.txt. Esta redireção é efetuada na linha de comandos da seguinte forma

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

A execução produz os seguintes resultados:

dos>more in.txt
un second test

dos>es2.exe 0<in.txt 1>out.txt 2>error.txt

dos>more out.txt
écriture dans flux Out : un second test

dos>more error.txt
écriture dans flux Error : un second test

É evidente que os fluxos Out e Error não escrevem nos mesmos dispositivos.

2.3.5. Atribuição do valor de uma expressão a uma variável

Vamos analisar aqui a operação variable=expression. A expressão pode ser do tipo: aritmética, relacional, booleana ou de caracteres.

2.3.5.1. Lista de operadores

Ação
Elemento da linguagem
Arithmétique
^, –, *, /, \, Mod, +, =
Assignation
=, ^=, *=, /=, \=, +=, -=, &=
Comparaison
=, <>, <, >, <=, >=, Like, Is
Concaténation
&, +
Opérations logiques/de bits
Not, And, Or, Xor, AndAlso, OrElse
Opérations diverses
AddressOf, GetType

2.3.5.2. Expressão aritmética

Os operadores das expressões aritméticas são os seguintes:

Arithmétique
^, –, *, /, \, Mod, +, =

+: adição, -: subtração, *: multiplicação, /: divisão real, \: quociente da divisão inteira, Mod: resto da divisão inteira, ^: elevação à potência. Assim, o seguinte programa:


' operadores aritméticos
Module operateursarithmetiques
    Sub Main()
        Dim i, j As Integer
        i = 4 : j = 3
        Console.Out.WriteLine(i & "/" & j & "=" & (i / j))
        Console.Out.WriteLine(i & "\" & j & "=" & (i \ j))
        Console.Out.WriteLine(i & " mod " & j & "=" & (i Mod j))

        Dim r1, r2 As Double
        r1 = 4.1 : r2 = 3.6
        Console.Out.WriteLine(r1 & "/" & r2 & "=" & (r1 / r2))
        Console.Out.WriteLine(r1 & "^2=" & (r1 ^ 2))
        Console.Out.WriteLine(Math.Cos(3))
    End Sub
End Module

dá os seguintes resultados:

4/3=1,33333333333333
4\3=1
4 mod 3=1
4,1/3,6=1,13888888888889
4,1^2=16,81
-0,989992496600445

Existem várias funções matemáticas. Aqui estão algumas delas:


Public Shared Function Sqrt(ByVal d As Double ) As Double
raiz quadrada

[Visual Basic]
Public Shared Function Cos(ByVal d As Double ) As Double
Cosseno

Public Shared Function Sin(ByVal a As Double) As Double
Senus

[Visual Basic]
Public Shared Function Tan(ByVal a As Double) As Double
Tangente

[Visual Basic]
Public Shared Function Pow(ByVal x As Double,ByVal y As Double) As Double
x elevado a y (x>0)

[Visual Basic]
Public Shared Function Exp(ByVal d As Double) As Double
Exponencial

[Visual Basic]
Overloads Public Shared Function Log( ByVal d As Double ) As Double
Logaritmo natural

Overloads Public Shared Function Abs(ByVal value As Double ) As Double
valor absoluto
....
 

Todas estas funções estão definidas numa classe .NET chamada Math. Ao utilizá-las, é necessário antepor-lhes o nome da classe onde estão definidas. Assim, escrever-se-á:

        Dim r1, r2 As Double
        r2 = Math.Sqrt(9)
        r1 = Math.Cos(3)

A definição completa da classe Math é a seguinte:

E 
Representa a base do logaritmo natural especificada pela constante e.
  
PI 
Representa a relação entre a circunferência de um círculo e o seu diâmetro, especificada pela constante π.
  
Abs 
Sobrescrito. Devolve o valor absoluto de um número especificado.
 
Acos 
Devolve o ângulo cujo cosseno é o número especificado.
 
Asin 
Devolve o ângulo cujo seno é o número especificado.
 
Atan 
Devolve o ângulo cuja tangente é o número especificado.
 
Atan2 
Devolve o ângulo cuja tangente é o quociente de dois números especificados.
 
BigMul
Gera o produto integral de dois números de 32 bits.
 
Ceiling 
Devolve o menor número inteiro maior ou igual ao número especificado.
 
Cos 
Devolve o cosseno do ângulo especificado.
 
Cosh 
Devolve o coseno hiperbólico do ângulo especificado.
 
DivRem
Sobrescrito. Devolve o quociente de dois números, passando o resto como parâmetro de saída.
 
Exp 
Devolve e elevado à potência especificada.
 
Floor 
Devolve o maior número inteiro menor ou igual ao número especificado.
 
IEEERemainder 
Devolve o resto da divisão de um número especificado por outro.
 
Log 
Sobrecarregada. Devolve o logaritmo de um número especificado.
 
Log10 
Devolve o logaritmo em base 10 de um número especificado.
 
Max 
Sobrescrito. Devolve o maior de dois números especificados.
 
Min 
Sobrecarga. Devolve o menor de dois números.
 
Pow 
Devolve um número especificado elevado à potência especificada.
 
Round 
Sobrescrito. Devolve o número mais próximo do valor especificado.
 
Sign 
Sobrescrito. Devolve um valor que indica o sinal de um número.
 
Sin 
Devolve o seno do ângulo especificado.
 
Sinh 
Devolve o seno hiperbólico do ângulo especificado.
 
Sqrt 
Devolve a raiz quadrada de um número especificado.
 
Tan 
Devolve a tangente do ângulo especificado.
 
Tanh 
Devolve a tangente hiperbólica do ângulo especificado.
 

Quando uma função é declarada como «sobrecarregada», significa que existe para vários tipos de parâmetros. Por exemplo, a função Abs(x) existe para x do tipo Integer, Long, Decimal, Single, Float. Para cada um destes tipos existe uma definição separada da função Abs. Diz-se então que está sobrecarregada.

2.3.5.3. Prioridades na avaliação de expressões aritméticas

A prioridade dos operadores na avaliação de uma expressão aritmética é a seguinte (da mais elevada à mais baixa):

Categoria
Operadores
Primaire
Todas as expressões sem operadores: funções, parênteses
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Mod
Addition
+, -

2.3.5.4. Expressões relacionais

Os operadores são os seguintes:

Comparaison
=, <>, <, >, <=, >=, Like, Is

=: igual a, <>: diferente de, <: menor que (estritamente), >: maior que (estritamente), <=: menor ou igual a, >=: maior ou igual a, Like: corresponde a um padrão, Is: identidade de objetos. Todos estes operadores têm a mesma prioridade. São avaliados da esquerda para a direita. O resultado de uma expressão relacional é um valor booleano.

Comparação de cadeias de caracteres: consideremos o seguinte programa:


' espaços de nomes
Imports System

Module string1
    Sub main()
        Dim ch1 As Char = "A"c
        Dim ch2 As Char = "B"c
        Dim ch3 As Char = "a"c
        Console.Out.WriteLine("A<B=" & (ch1 < ch2))
        Console.Out.WriteLine("A<a=" & (ch1 < ch3))
        Dim chat As String = "chat"
        Dim chien As String = "chien"
        Dim chaton As String = "chaton"
        Dim chat2 As String = "CHAT"
        Console.Out.WriteLine("chat<chien=" & (chat < chien))
        Console.Out.WriteLine("chat<chaton=" & (chat < chaton))
        Console.Out.WriteLine("chat<CHAT=" & (chat < chat2))
        Console.Out.WriteLine("chaton like chat*=" & ("chaton" Like "chat*"))
    End Sub
End Module

e o resultado da sua execução:

A<B=True
A<a=True
chat<chien=True
chat<chaton=True
chat<CHAT=False
chaton like chat*=True

Sejam dois caracteres C1 e C2. É possível compará-los com os operadores: <, <=, =, <>, >, >=. São então comparados os valores Unicode dos caracteres, que são números. De acordo com a ordem Unicode, temos as seguintes relações:

espaço < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'

As cadeias de caracteres são comparadas caractere a caractere. A primeira desigualdade encontrada entre dois caracteres implica uma desigualdade no mesmo sentido nas cadeias. Com estas explicações, convida-se o leitor a analisar os resultados do programa anterior.

2.3.5.5. Expressões booleanas

Os operadores são os seguintes:

Opérations logiques/de bits
Not, And, Or, Xor, AndAlso, OrElse

Not: «e» lógico, Or: «ou» lógico, Not: negação, Xor: «ou» exclusivo.

op1 AndAlso op2: se op1 for falso, op2 não é avaliado e o resultado é falso.

op1 OrElse op2: se op1 for verdadeiro, op2 não é avaliado e o resultado é verdadeiro.

A prioridade destes operadores entre si é a seguinte:

NOT logique
Not
AND logique
E, AndAlso
OR logique
Ou, OrElse
XOR logique
XOR

O resultado de uma expressão booleana é um valor booleano.

2.3.5.6. Operações com bits

Por um lado, encontramos os mesmos operadores que os operadores booleanos, com a mesma prioridade. Encontramos também dois operadores de deslocamento: << e >>. Sejam i e j dois inteiros.

i<<n
desloca i n bits para a esquerda. Os bits que entram são zeros.
i>>n
desloca i n bits para a direita. Se i for um inteiro com sinal (signed char, int, long), o bit de sinal é preservado.
i & j
realiza a operação lógica ET entre i e j, bit a bit.
i | j
realiza a operação lógica bit a bit entre i e j, como em OU.
~i
incrementa i em 1
i^j
cria o OU e o EXCLUSIF a partir de i e j

Seja o seguinte programa:


Module operationsbit
    Sub main()
        ' manipulação de bits
        Dim i As Short = &H123F
        Dim k As Short = &H7123
        Console.Out.WriteLine("i<<4=" & (i << 4).ToString("X"))
        Console.Out.WriteLine("i>>4=" & (i >> 4).ToString("X"))
        Console.Out.WriteLine("k>>4=" & (k >> 4).ToString("X"))
        Console.Out.WriteLine("i and 4=" & (i And 4).ToString("X"))
        Console.Out.WriteLine("i or 4 =" & (i Or 4).ToString("X"))
        Console.Out.WriteLine("not i=" & (Not i).ToString("X"))
    End Sub
End Module

A sua execução produz os seguintes resultados:

i<<4=23F0
i>>4=123
k>>4=712
i and 4=4
i or k =123F
not i=EDC0

2.3.5.7. Operador associado a uma atribuição

É possível escrever a+=b, o que significa a=a+b. A lista de operadores que podem ser combinados com a operação de atribuição é a seguinte:

combinaison d'opérateurs
^=, *=, /=, \=, +=, -=, &=

2.3.5.8. Prioridade geral dos operadores

Categoria
Operadores
Primaire
Todas as expressões sem operadores
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Mod
Addition
+, -
Concaténation
&
Déplacement
<<, >>
Relationnel
=, <>, <, >, <=, >=, Like, Is, TypeOf...Is
NOT logique
Not
AND logique
E, AndAlso
OR logique
Ou, OrElse
XOR logique
XOR

Quando um operando é colocado entre dois operadores com a mesma prioridade, a associatividade dos operadores determina a ordem em que as operações são realizadas. Todos os operadores são associativos à esquerda, o que significa que as operações são executadas da esquerda para a direita. A prioridade e a associatividade podem ser controladas através de expressões entre parênteses.

2.3.5.9. As conversões de tipo

Existem várias funções predefinidas que permitem converter um tipo de dados noutro. A lista é a seguinte:

CBool,CByte,CChar,CDate,CDbl,CDec,CInt,CLng,CObj,CShort,CSng,CStr

Estas funções aceitam como argumento uma expressão numérica ou uma cadeia de caracteres. O tipo do resultado é indicado na tabela seguinte:

função
resultado
Intervalo de valores do parâmetro da função
CBool
Booleano
Qualquer cadeia de caracteres ou expressão numérica válida.
CByte
Byte
0 a 255; as frações são arredondadas.
CChar
Caractere
Qualquer expressão String válida; o valor pode estar compreendido entre 0 e 65 535.
CDate
Data
Qualquer representação válida da data e da hora.
CDbl
Double
-1,79769313486231E+308 a
-4,94065645841247E-324 para valores negativos; 4,94065645841247E-324 a 1,79769313486231E+308 para valores positivos.
CDec
Decimal
+/-79 228 162 514 264 337 593 543 950 335 para os números sem casas decimais. O intervalo de valores dos números com 28 casas decimais é
+/-7,9228162514264337593543950335. O menor número diferente de zero é 0,0000000000000000000000000001.
CInt
Inteiro
-2 147 483 648 a 2 147 483 647; as frações são arredondadas.
CLng
Número longo
-9 223 372 036 854 775 808 a 9 223 372 036 854 775 807; as frações são arredondadas.

CObj 
Objeto
Qualquer expressão válida.
CShort
Curto
-32 768 a 32 767; as frações são arredondadas.
CSng
Single
-3,402823E+38 a -1,401298E-45 para os valores negativos; 1,401298E-45 a 3,402823E+38 para os valores positivos.
CStr
String
Os valores devolvidos pela função Cstr dependem do argumento expressão.

Eis um programa de exemplo:


Module conversion
    Sub main()
        Dim var1 As Boolean = CBool("true")
        Dim var2 As Byte = CByte("100")
        Dim var3 As Char = CChar("A")
        Dim var4 As Date = CDate("30 janvier 2004")
        Dim var5 As Double = CDbl("100,45")
        Dim var6 As Decimal = CDec("1000,67")
        Dim var7 As Integer = CInt("-30")
        Dim var8 As Long = CLng("456")
        Dim var9 As Short = CShort("-14")
        Dim var10 As Single = CSng("56,78")
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
    End Sub
End Module

e os resultados da sua execução:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78

Também é possível utilizar a função CType(expression, type), tal como ilustrado no programa seguinte:


Module ctype1
    Sub main()
        Dim var1 As Boolean = CType("true", Boolean)
        Dim var2 As Byte = CType("100", Byte)
        Dim var3 As Char = CType("A", Char)
        Dim var4 As Date = CType("30 janvier 2004", Date)
        Dim var5 As Double = CType("100,45", Double)
        Dim var6 As Decimal = CType("1000,67", Decimal)
        Dim var7 As Integer = CType("-30", Integer)
        Dim var8 As Long = CType("456", Long)
        Dim var9 As Short = CType("-14", Short)
        Dim var10 As Single = CType("56,78", Single)
        Dim var11 As String = CType("47,89", String)
        Dim var12 As String = 47.89.ToString
        Dim var13 As String = "" & 47.89
        Console.Out.WriteLine("var1=" & var1)
        Console.Out.WriteLine("var2=" & var2)
        Console.Out.WriteLine("var3=" & var3)
        Console.Out.WriteLine("var4=" & var4)
        Console.Out.WriteLine("var5=" & var5)
        Console.Out.WriteLine("var6=" & var6)
        Console.Out.WriteLine("var7=" & var7)
        Console.Out.WriteLine("var8=" & var8)
        Console.Out.WriteLine("var9=" & var9)
        Console.Out.WriteLine("var10=" & var10)
        Console.Out.WriteLine("var11=" & var11)
        Console.Out.WriteLine("var12=" & var12)
        Console.Out.WriteLine("var13=" & var13)
    End Sub
End Module

que produz os seguintes resultados:

var1=True
var2=100
var3=A
var4=30/01/2004
var5=100,45
var6=1000,67
var7=-30
var8=456
var9=-14
var10=56,78
var11=47,89
var12=47,89
var13=47,89

2.4. Instruções para o controlo do andamento do programa

2.4.1. Parar

O método Exit, definido na classe Environment, permite interromper a execução de um programa:


[Visual Basic]
Public Shared Sub Exit(ByVal exitCode As Integer )

interrompe o processo em curso e devolve o valor exitCode ao processo pai. O valor de exitCode pode ser utilizado por este último. Em DOS, esta variável de estado é devolvida a DOS na variável de sistema ERRORLEVEL, cujo valor pode ser verificado num ficheiro batch. No Unix, é a variável $? que recupera o valor de exitCode.

    Environment.Exit(0)

interromperá a execução do programa com um valor de estado igual a 0.

2.4.2. Estrutura de escolha simples

if condition then
    actions_alors
else
    actions_sinon
end if
  • cada ação está numa linha
  • a cláusula else pode estar ausente.

É possível aninhar as estruturas de escolha, tal como mostra o exemplo seguinte:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module if1
    Sub main()
        Dim i As Integer = 10
        If i > 4 Then
            Console.Out.WriteLine(i & " est > " & 4)
        Else
            If i = 4 Then
                Console.Out.WriteLine(i & " est = " & 4)
            Else
                Console.Out.WriteLine(i & " est < " & 4)
            End If
        End If
    End Sub
End Module

O resultado obtido:

10 est > 4

2.4.3. Estrutura de casos

A sintaxe é a seguinte:

select case expression
    case liste_valeurs1
        actions1
case liste_valeurs2
        actions2
...
case else
        actions_sinon
end select
  • O tipo de [expression] deve ser um dos seguintes tipos:
Boolean, Byte, Char, Date, Decimal, Double, Integer, Long, Object, Short, Single et String
  • A cláusula [case else] pode estar ausente.
  • [liste_valeursi] são valores possíveis da expressão. [listes_valeursi] representa uma lista de condições: condição1, condição2, ..., condiçãox. Se [expression] verificar uma das condições, as ações associadas à cláusula [liste_valeursi] são executadas. As condições podem assumir a seguinte forma:
  • val1 to val2: verdadeiro se [expression] pertencer ao domínio [val1,val2]
  • val1: verdadeiro se [expression] for igual a val1
  • is > val1: verdadeiro se [expression] > val1. A palavra-chave [is] pode estar ausente
  • o mesmo se aplica aos operadores =, <, <=, >, >=, <>
  • apenas as ações relacionadas com a primeira condição verificada são executadas.

Consideremos o seguinte programa:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module selectcase1
    Sub main()
        Dim i As Integer = 10
        Select Case i
            Case 1 To 4, 7 To 8
                Console.Out.WriteLine("i est dans l'intervalle [1,4] ou [7,8]")
            Case Is > 12
                Console.Out.WriteLine("i est > 12")
            Case Is < 15
                Console.Out.WriteLine("i est < 15")
            Case Is < 20
                Console.Out.WriteLine("i est < 20")
        End Select
    End Sub
End Module

Este programa produz os seguintes resultados:

i est < 15

2.4.4. Estrutura de repetição

2.4.4.1. Número de repetições conhecido


For counter [ As datatype ] = start To end [ Step step ]
   actions
Next [ counter ]

As ações são executadas para cada um dos valores assumidos pela variável [counter]. Consideremos o seguinte programa:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module for1
    Sub main()
        Dim somme As Integer = 0
        Dim résultat As String = "somme("
        For i As Integer = 0 To 10 Step 2
            somme += i
            résultat += " " + i.ToString
        Next
        résultat += ")=" + somme.ToString
        Console.Out.WriteLine(résultat)
    End Sub
End Module

Os resultados:

somme( 0 2 4 6 8 10)=30

Outra estrutura de iteração com um número conhecido de iterações é a seguinte:


For Each element [ As datatype ] In groupe
   [ actions ]
Next [ element ]
  • groupe é uma coleção de objetos. A coleção de objetos que já conhecemos é o tabuleiro
  • datatype é o tipo dos objetos da coleção. No caso de um tabuuleiro, seria o tipo dos elementos do tabuuleiro
  • element é uma variável local do ciclo que irá assumir sucessivamente, como valor, todos os valores da coleção.

Assim, o código seguinte:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module foreach1
    Sub main()
        Dim amis() As String = {"paul", "hélène", "jacques", "sylvie"}
        For Each nom As String In amis
            Console.Out.WriteLine(nom)
        Next
    End Sub
End Module

exibiria:

paul
hélène
jacques
sylvie

2.4.4.2. Número de repetições desconhecido

Existem várias estruturas em VB.NET para este caso.


Do { While | Until } condition
   [ statements ]
Loop

O ciclo repete-se enquanto a condição for verdadeira (while) ou até que a condição seja verdadeira (until). O ciclo pode nunca ser executado.


Do
   [ statements ]
Loop { While | Until } condition

O ciclo repete-se enquanto a condição for verdadeira (while) ou até que a condição seja verdadeira (until). O ciclo é sempre executado pelo menos uma vez.


While condition
   [ statements ]
End While

O ciclo repete-se enquanto a condição for verdadeira. O ciclo pode nunca ser executado. Os ciclos seguintes calculam todos a soma dos primeiros 10 números inteiros.


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module
somme=55
somme=55
somme=55
somme=55

2.4.4.3. Instruções de gestão de ciclo

exit do
sai de um ciclo do ... loop
exit for
sai de um ciclo «for»

2.5. A estrutura de um programa VB.NET

Um programa VB.NET que não utilize uma classe definida pelo utilizador nem outras funções além da função principal Main poderá ter a seguinte estrutura:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports espace1
Imports ....

Module nomDuModule
    Sub main()
....
    End Sub
End Module
  • A diretiva [Option Explicit on] obriga à declaração das variáveis. Na VB.NET, tal não é obrigatório. Uma variável não declarada é, nesse caso, do tipo Object.
  • A diretiva [Option Strict on] proíbe qualquer conversão de tipos de dados que possa resultar em perda de dados, bem como qualquer conversão entre tipos numéricos e cadeias de caracteres. Nesse caso, é necessário utilizar explicitamente funções de conversão.
  • O programa importa todos os espaços de nomes de que necessita. Ainda não abordámos este conceito. Nos programas anteriores, deparámo-nos frequentemente com instruções do tipo:
        Console.Out.WriteLine(unechaine)

Na verdade, deveríamos ter escrito:

        System.Console.Out.WriteLine(unechaine)

onde System é o espaço de nomes que contém a classe [Console]. Ao importar o espaço de nomes [System] com uma instrução Imports, o VB.NET irá explorá-lo sistematicamente sempre que encontrar uma classe que não conheça. Irá repetir a pesquisa em todos os espaços de nomes declarados até encontrar a classe procurada. Escreve-se então:


' espaços de nomes
Imports System
....

        Console.Out.WriteLine(unechaine)

Um exemplo de programa poderia ser o seguinte:


' opções
Option Explicit On 
Option Strict On

'espaços de nomes
Imports System

' módulo principal
Module main1
    Sub main()
        Console.Out.WriteLine("main1")
    End Sub
End Module

O mesmo programa pode ser escrito da seguinte forma:


' opções
Option Explicit On 
Option Strict On

'espaços de nomes
Imports System

' classe de teste
Public Class main2
    Public Shared Sub main()
        Console.Out.WriteLine("main2")
    End Sub
End Class

Aqui, utilizamos o conceito de classe que será apresentado no capítulo seguinte. Quando uma classe deste tipo contém um procedimento estático (partilhado) chamado main, este é executado. Se introduzimos esta sintaxe aqui, é porque a linguagem gémea do VB.NET, que é o C#, só conhece o conceito de classe, c.a.d, segundo o qual todo o código executado pertence necessariamente a uma classe. A noção de classe pertence à programação orientada a objetos. Impô-la na conceção de qualquer programa é um pouco desajeitado. Vemo-lo aqui na versão 2 do programa anterior, onde somos levados a introduzir um conceito de classe e de método estático onde não há necessidade. Assim, daqui em diante, só introduziremos o conceito de classe quando for necessário. Nos restantes casos, utilizaremos o conceito de módulo, tal como na versão 1 acima.

2.6. Compilação e execução de um programa VB.NET

A compilação de um programa VB.NET requer apenas o SDK.NET. Consideremos o seguinte programa:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module boucles1
    Sub main()
        Dim i, somme As Integer
        i = 0 : somme = 0
        Do While i < 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do Until i = 11
            somme += i
            i += 1
        Loop
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop Until i = 11
        Console.Out.WriteLine("somme=" + somme.ToString)
        i = 0 : somme = 0
        Do
            somme += i
            i += 1
        Loop While i < 11
        Console.Out.WriteLine("somme=" + somme.ToString)
    End Sub
End Module

Suponhamos que se encontre num ficheiro chamado [boucles1.vb]. Para o compilar, procedemos da seguinte forma:

dos>dir boucles1.vb
11/03/2004  15:55                  583 boucles1.vb

dos>vbc boucles1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4
pour Microsoft (R) .NET Framework version 1.1.4322.573
Copyright (C) Microsoft Corporation 1987-2002. Tous droits réservés.

dos>dir boucles1.*
11/03/2004  16:04                  601 boucles1.vb
11/03/2004  16:04                3 584 boucles1.exe

O programa vbc.exe é o compilador VB.NET. Aqui, estava no PATH do DOS:


dos>path
PATH=E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE;E:\Program Files\Microsoft Visual Studio .NET 2003\VC7\BIN;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin\prerelease;E:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\bin;E:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\bin;E:\WINNT\Microsoft.NET\Framework\v1.1.4322;e:\winnt\system32;e:\winnt;

dos>dir E:\WINNT\Microsoft.NET\Framework\v1.1.4322\vbc.exe
21/02/2003  10:20              737 280 vbc.exe

O compilador [vbc] produz um ficheiro .exe executável pela máquina virtual .NET:

dos>boucles1
somme=55
somme=55
somme=55
somme=55

2.7. O exemplo IMPOTS

Propõe-se escrever um programa que permita calcular o imposto de um contribuinte. Consideramos o caso simplificado de um contribuinte que tenha apenas o seu salário para declarar:

  • calcula-se o número de quotas do trabalhador nbParts = nbEnfants/2 + 1 se não for casado, nbEnfants/2 + 2 se for casado, em que nbEnfants é o número de filhos que tem.
  • se tiver pelo menos três filhos, tem mais meia quota
  • calcula-se o seu rendimento tributável R = 0,72 * S, em que S é o seu salário anual
  • calcula-se o seu coeficiente familiar QF = R / nbParts
  • calcula-se o seu imposto I. Consideremos a seguinte tabela:
12620,0
0
0
13 190
0,05
631
15640
0,1
1290,5
24 740
0,15
2072,5
31 810
0,2
3309,5
39 970
0,25
4900
48 360
0,3
6898,5
55 790
0,35
9316,5
92 970
0,4
12106
127 860
0,45
16 754,5
151 250
0,50
23 147,5
172 040
0,55
30710
195 000
0,60
39312
0
0,65
49062

Cada linha tem 3 campos. Para calcular o imposto I, procura-se a primeira linha em que QF <= campo1. Por exemplo, se QF = 23000, encontrar-se-á a linha

    24740        0.15        2072.5

O imposto I é, então, igual a 0,15*R - 2072,5*nbParts. Se QF for tal que a relação QF<=campo1 nunca for verificada, então são utilizados os coeficientes da última linha. Neste caso:

    0                0.65        49062

o que resulta no imposto I = 0,65*R - 49062*nbParts. O programa VB.NET correspondente é o seguinte:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module impots
    ' ------------ principal
    Sub Main()

        ' tabelas de dados necessárias para o cálculo do imposto
        Dim Limites() As Decimal = {12620D, 13190D, 15640D, 24740D, 31810D, 39970D, 48360D, 55790D, 92970D, 127860D, 151250D, 172040D, 195000D, 0D}
        Dim CoeffN() As Decimal = {0D, 631D, 1290.5D, 2072.5D, 3309.5D, 4900D, 6898.5D, 9316.5D, 12106D, 16754.5D, 23147.5D, 30710D, 39312D, 49062D}

        ' obtém-se o estado civil
        Dim OK As Boolean = False
        Dim reponse As String = Nothing
        While Not OK
            Console.Out.Write("Etes-vous marié(e) (O/N) ? ")
            reponse = Console.In.ReadLine().Trim().ToLower()
            If reponse <> "o" And reponse <> "n" Then
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            Else
                OK = True
            End If
        End While
        Dim Marie As Boolean = reponse = "o"

        ' número de filhos
        OK = False
        Dim NbEnfants As Integer = 0
        While Not OK
            Console.Out.Write("Nombre d'enfants : ")
            reponse = Console.In.ReadLine()
            Try
                NbEnfants = Integer.Parse(reponse)
                If NbEnfants >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' salário
        OK = False
        Dim Salaire As Integer = 0
        While Not OK
            Console.Out.Write("Salaire annuel : ")
            reponse = Console.In.ReadLine()
            Try
                Salaire = Integer.Parse(reponse)
                If Salaire >= 0 Then
                    OK = True
                Else
                    Console.Error.WriteLine("Réponse incorrecte. Recommencez")
                End If
            Catch
                Console.Error.WriteLine("Réponse incorrecte. Recommencez")
            End Try
        End While
        ' cálculo do número de quotas
        Dim NbParts As Decimal
        If Marie Then
            NbParts = CDec(NbEnfants) / 2 + 2
        Else
            NbParts = CDec(NbEnfants) / 2 + 1
        End If
        If NbEnfants >= 3 Then
            NbParts += 0.5D
        End If
        ' rendimento tributável
        Dim Revenu As Decimal
        Revenu = 0.72D * Salaire

        ' quociente familiar
        Dim QF As Decimal
        QF = Revenu / NbParts

        ' determinação da faixa de imposto correspondente a QF
        Dim i As Integer
        Dim NbTranches As Integer = Limites.Length
        Limites((NbTranches - 1)) = QF
        i = 0
        While QF > Limites(i)
            i += 1
        End While
        ' o imposto
        Dim impots As Integer = CInt(i * 0.05D * Revenu - CoeffN(i) * NbParts)

        ' é apresentado o resultado
        Console.Out.WriteLine(("Impôt à payer : " & impots))
    End Sub
End Module

O programa é compilado numa janela do DOS através de:

dos>vbc impots1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573

dos>dir impots1.exe
24/02/2004  15:42                5 632 impots1.exe

A compilação produz um executável impots.exe. É importante referir que o impots.exe não é diretamente executável pelo processador. Na realidade, contém código intermédio que só é executável numa plataforma .NET. Os resultados obtidos são os seguintes:

dos>impots1
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
dos>impots1
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
dos>impots1
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0

2.8. Argumentos do programa principal

A rotina principal Main pode aceitar como parâmetro uma matriz de cadeias de caracteres:


    Sub main(ByVal args() As String)

O parâmetro args é uma matriz de cadeias de caracteres que recebe os argumentos passados na linha de comandos aquando da chamada do programa.

  • args.Length é o número de elementos da matriz args
  • args(i) é o elemento i da matriz

Se executarmos o programa P com o comando: P arg0 arg1 … argn e se a rotina Main do programa P estiver declarada da seguinte forma:


    Sub main(ByVal args() As String)

teremos arg(0)="arg0", arg(1)="arg1" … Eis um exemplo:


' diretrizes
Option Strict On
Option Explicit On 

' espaços de nomes
Imports System

Module arg
    Sub main(ByVal args() As String)
        ' número de argumentos
        console.out.writeline("Il y a " & args.length & " arguments")
        Dim i As Integer
        For i = 0 To args.Length - 1
            Console.Out.WriteLine("argument n° " & i & "=" & args(i))
        Next
    End Sub
End Module

A execução produz os seguintes resultados:

dos>arg1 a b c
Il y a 3 arguments
argument n° 0=a
argument n° 1=b
argument n° 2=c

2.9. As enumerações

Uma enumeração é um tipo de dados cujo domínio de valores é um conjunto de constantes inteiras. Consideremos um programa que tem de gerir as classificações de um exame. Seriam cinco: Passável, AssezBien, Bom, TrèsBien, Excelente. Poderíamos, então, definir uma enumeração para estas cinco constantes:


    Enum mention
        Passable
        AssezBien
        Bien
        TrésBien
        Excellent
    End Enum

Internamente, estas cinco constantes são codificadas por números inteiros consecutivos, começando por 0 para a primeira constante, 1 para a seguinte, etc. Uma variável pode ser declarada para assumir estes valores na enumeração:


         ' uma variável que obtém os seus valores da enumeração mencionada
        Dim maMention As mention = mention.Passable

É possível comparar uma variável com os diferentes valores possíveis da enumeração:


         ' teste com valor da enumeração
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

É possível obter todos os valores da enumeração:


        For Each m In mention.GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next

Da mesma forma que o tipo simples Integer é equivalente à estrutura Int32, o tipo simples Enum é equivalente à estrutura Enum. Esta classe possui um método estático GetValues que permite obter todos os valores de um tipo enumerado que seja passado como parâmetro. Este deve ser um objeto do tipo Type, que é uma classe de informação sobre o tipo de um dado. O tipo de uma variável v é obtido através de v.GetType(). Assim, neste caso, a função maMention.GetType() devolve o objeto Type da enumeração mentions e a função Enum.GetValues(maMention.GetType()) a lista de valores da enumeração mentions.

É isso que o programa seguinte demonstra:


' diretivas
Option Strict On
Option Explicit On 

' espaços de nomes
Imports System

Public Module enum2

    ' uma enumeração
    Enum mention
        Passable
        AssezBien
        Bien
        TrèsBien
        Excellent
    End Enum

    ' página de teste
    Sub Main()

        ' uma variável que obtém os seus valores da enumeração mencionada
        Dim maMention As mention = mention.Passable

        ' exibição do valor da variável
        Console.Out.WriteLine("mention=" & maMention)

        ' teste com o valor da enumeração
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

        ' lista de menções literais
        For Each m As mention In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m.ToString)
        Next

        ' lista de menções completas
        For Each m As Integer In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next
    End Sub
End Module

Os resultados da execução são os seguintes:

dos>enum2
mention=0
Peut mieux faire
Passable
AssezBien
Bien
TrèsBien
Excellent
0
1
2
3
4

2.10. Gestão de exceções

Muitas funções VB.NET podem gerar exceções, ou seja, erros. Quando uma função é suscetível de gerar uma exceção, o programador deve gerir essa exceção com o objetivo de obter programas mais resistentes a erros: deve-se evitar sempre o «bloqueio» inesperado de uma aplicação.

A gestão de uma exceção é feita de acordo com o seguinte esquema:

try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception e)
    traiter l'exception e
end try
instruction suivante

Se a função não gerar uma exceção, passa-se então para a instrução seguinte; caso contrário, passa-se para o corpo da cláusula catch e, em seguida, para a instrução seguinte. É importante notar os seguintes pontos:

  • e é um objeto derivado do tipo Exception. É possível ser mais preciso utilizando tipos como IOException, SystemException, etc.: existem vários tipos de exceções. Ao escrever catch e as Exception, indica-se que se pretende gerir todos os tipos de exceções. Se o código da cláusula try for suscetível de gerar vários tipos de exceções, pode ser desejável ser mais preciso, gerindo a exceção com várias cláusulas catch:
try
    appel de la fonction susceptible de générer l'exception
catch e as IOException 
    traiter l'exception e
catch  e as SystemException
    traiter l'exception e
end try
instruction suivante
  • É possível adicionar uma cláusula «finally» às cláusulas try/catch:
try
    appel de la fonction susceptible de générer l'exception
catch  e as Exception
    traiter l'exception e
finally
    code exécuté après try ou catch
end try
instruction suivante

Quer haja ou não uma exceção, o código da cláusula finally será sempre executado.

  • Na cláusula catch, pode não se querer utilizar o objeto Exception disponível. Em vez de escrever `catch e as Exception`, escreve-se então `catch`.
  • A classe Exception possui uma propriedade Message que contém uma mensagem detalhando o erro que ocorreu. Assim, se se pretender exibir essa mensagem, escrever-se-á:
catch e as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+e.Message);
    ...
end try
  • A classe Exception possui um método ToString que devolve uma cadeia de caracteres indicando o tipo da exceção, bem como o valor da propriedade Message. Assim, poderemos escrever:
catch  ex as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString)
    ...
end try

O exemplo seguinte mostra uma exceção gerada pela utilização de um elemento de tabela inexistente:


' opções
Option Explicit On 
Option Strict On

' espaços de nomes
Imports System

Module tab1
    Sub Main()
        ' declaração e inicialização de um tabuleiro
        Dim tab() As Integer = {0, 1, 2, 3}
        Dim i As Integer

        ' exibição de um tabuleiro com um «for»
        For i = 0 To tab.Length - 1
            Console.Out.WriteLine(("tab[" & i & "]=" & tab(i)))
        Next i

        ' exibição de um tabuleiro com um for each
        Dim élmt As Integer
        For Each élmt In tab
            Console.Out.WriteLine(élmt)
        Next élmt

        ' geração de uma exceção
        Try
            tab(100) = 6
        Catch e As Exception
            Console.Error.WriteLine(("L'erreur suivante s'est produite : " & e.Message))
        End Try
    End Sub
End Module

A execução do programa produz os seguintes resultados:

dos>exception1
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
0
1
2
3
L'erreur suivante s'est produite : L'index se trouve en dehors des limites du tableau.

Eis outro exemplo em que se trata a exceção provocada pela atribuição de uma cadeia de caracteres a um número, quando a cadeia não representa um número:


' opções
Option Strict On
Option Explicit On 

'importações
Imports System

Public Module console1
  Public Sub Main()
    ' Solicita-se o nome
    System.Console.Write("Nom : ")

        ' leitura da resposta
    Dim nom As String = System.Console.ReadLine()

        ' solicitação da idade
    Dim age As Integer
    Dim ageOK As Boolean = False
    Do While Not ageOK
      ' pergunta
      Console.Out.Write("âge : ")
      ' Leitura e verificação da resposta
      Try
        age = Int32.Parse(System.Console.ReadLine())
        If age < 0 Then Throw New Exception
        ageOK = True
      Catch
        Console.Error.WriteLine("Age incorrect, recommencez...")
      End Try
    Loop

        ' exibição final
    Console.Out.WriteLine("Vous vous appelez [" & nom & "] et vous avez [" & age & "] ans")
  End Sub
End Module

Alguns resultados da execução:

dos>console1
Nom : dupont
âge : 23
Vous vous appelez dupont et vous avez 23 ans
dos>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans

2.11. Passagem de parâmetros para uma função

Vamos analisar aqui a forma como os parâmetros são passados a uma função. Consideremos a função:


    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub    

Na definição da função, a é designado como um parâmetro formal. Este parâmetro existe apenas para efeitos da definição da função changeInt. Poderia muito bem ter sido denominado b. Consideremos agora uma utilização desta função:


    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

Aqui, na instrução changeInt(idade), age é o parâmetro efetivo que irá transmitir o seu valor ao parâmetro formal a. Estamos interessados na forma como um parâmetro formal recupera o valor do parâmetro efetivo que lhe corresponde.

2.11.1. Passagem por valor

O exemplo seguinte mostra-nos que os parâmetros de uma função/procedimento são, por predefinição, passados por valor: ou seja, o valor do parâmetro efetivo é copiado para o parâmetro formal correspondente. Temos duas entidades distintas. Se a função alterar o parâmetro formal, o parâmetro efetivo não sofre qualquer alteração.


' opções
Option Explicit On 
Option Strict On

' passagem de parâmetros por valor para uma função
Imports System

Module param1
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

    Sub changeInt(ByVal a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

Os resultados obtidos são os seguintes:

Paramètre formel a=30
Paramètre effectif age=20

O valor 20 do parâmetro efetivo foi copiado para o parâmetro formal a. Este foi posteriormente alterado. O parâmetro efetivo, por sua vez, permaneceu inalterado. Este modo de passagem é adequado para os parâmetros de entrada de uma função.

2.11.2. Passagem por referência

Numa passagem por referência, o parâmetro efetivo e o parâmetro formal são uma única e mesma entidade. Se a função alterar o parâmetro formal, o parâmetro efetivo também é alterado. Em VB.NET, o parâmetro formal deve ser precedido pela palavra-chave ByRef. Eis um exemplo:


' opções
Option Explicit On 
Option Strict On

' passagem de parâmetros por valor para uma função
Imports System

Module param2
    Sub Main()
        Dim age As Integer = 20
        changeInt(age)
        Console.Out.WriteLine(("Paramètre effectif age=" & age))
    End Sub

    Sub changeInt(ByRef a As Integer)
        a = 30
        Console.Out.WriteLine(("Paramètre formel a=" & a))
    End Sub
End Module

e os resultados da execução:

Paramètre formel a=30
Paramètre effectif age=30

O parâmetro efetivo acompanhou a alteração do parâmetro formal. Este modo de passagem é adequado para os parâmetros de saída de uma função.