Skip to content

2. Основи мови VB.NET

2.1. Вступ

Спочатку ми розглядаємо VB.NET як класичну мову програмування. Про об’єкти ми поговоримо пізніше.

У програмі містяться дві складові

  • дані
  • інструкції, що оперують ними

Зазвичай намагаються відокремити дані від інструкцій:

2.2. Дані VB.NET

VB.NET використовують такі типи даних:

  1. цілі, дійсні та десяткові числа
  1. символи та символьні рядки
  2. логічні значення
  3. дати
  4. об’єкти

2.2.1. Заздалегідь визначені типи даних

Тип VB
Еквівалентний тип .NET
Розмір
Діапазон значень
Логічний
System.Boolean
2 байти
True або False.
Байт
System.Byte
1 байт
Від 0 до 255 (без знака).
Символ
System.Char
2 байти
Від 0 до 65 535 (без знака).
Дата
System.DateTime
8 байт
від 0:00:00 1 січня 0001 року до 23:59:59 31 грудня 9999 року.
Десятичний
System.Decimal
16 байт
від 0 до +/-79 228 162 514 264 337 593 543 950 335 без десяткових знаків; від 0 до +/-7,9228162514264337593543950335 з 28 десятковими знаками; найменше число, відмінне від нуля, становить +/-0,0000000000000000000000000001 (+/-1E-28).
Double
System.Double
8 байт
від -1,79769313486231E+308 до
-4,94065645841247E-324 для від’ємних значень; від 4,94065645841247E-324 до 1,79769313486231E+308 для додатних значень.
Ціле число
System.Int32
4 байти
від -2 147 483 648 до 2 147 483 647.
Довге
System.Int64
8 байт
від -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807.
Об’єкт
System.Object
4 байти
У змінній типу Object можна зберігати будь-який тип даних.
Short
System.Int16
2 байти
Від -32 768 до 32 767.
Single
System.Single
4 байти
від -3,402823E+38 до -1,401298E-45 для від’ємних значень; від 1,401298E-45 до 3,402823E+38 для додатних значень.
Рядок
System.String (клас)
 
Від 0 до приблизно 2 мільярдів символів Unicode.

У таблиці вище можна побачити, що для 32-бітного цілого числа існує два можливі типи: Integer та System.Int32. Обидва типи є взаємозамінними. Те саме стосується й інших типів VB та їхніх еквівалентів на платформі .NET. Ось приклад програми:


Module types
    Sub Main()
        ' цілі числа
        Dim var1 As Integer = 100
        Dim var2 As Long = 10000000000L
        Dim var3 As Byte = 100
        Dim var4 As Short = 4
        ' дійсні числа
        Dim var5 As Decimal = 4.56789D
        Dim var6 As Double = 3.4
        Dim var7 As Single = -0.000103F
        ' дата
        Dim var8 As Date = New Date(2003, 1, 1, 12, 8, 4)
        ' логічне значення
        Dim var9 As Boolean = True
        ' символ
        Dim var10 As Char = "A"c
        ' рядок символів
        Dim var11 As String = "abcde"
        ' об'єкт
        Dim var12 As Object = New Object
        ' відображення
        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

Виконання дає такі результати:

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. Запис літеральних даних

Integer
145, -7, &FF (шестнадцяткове)
Long
100000L
Double
134,789, -45E-18 (-45 × 10⁻¹⁸)
Single
134.789F, -45E-18F (-45 10⁻¹⁸)
Decimal
100000D
Char
"A"c
String
"сьогодні"
Boolean
true, false
date
New Date(2003, 1, 1) для 01.01.2003

Зверніть увагу на наступні моменти:

  • 100000L, літера L означає, що число розглядається як ціле число великої довжини
  • 134.789F, літера F означає, що число розглядається як число з простою точністю
  • 100000D, літера D означає, що число розглядається як десяткове дійсне число
  • "A"c — для перетворення символьного рядка "A" у символ 'A'
  • рядок символів оточений символом ". Якщо рядок має містити символ ", його потрібно повторити двічі, як у "abcd""e", щоб зобразити рядок [abcd"e].

2.2.3. Оголошення даних

2.2.3.1. Роль оголошень

Програма оперує даними, що характеризуються іменем та типом. Ці дані зберігаються в пам’яті. Під час компіляції програми компілятор призначає кожному елементу даних місце в пам’яті, що характеризується адресою та розміром. Він робить це, спираючись на оголошення, зроблені програмістом. Крім того, ці оголошення дозволяють компілятору виявляти помилки в програмі. Так, операція x=x*2 буде визнана помилковою, якщо, наприклад, x є символьним рядком.

2.2.3.2. Оголошення констант

Синтаксис оголошення константи такий:

const ідентифікатор as тип=значення

наприклад, [const PI as double=3.141592]. Навіщо оголошувати константи?

  1. Читати програму буде простіше, якщо константі надати змістовне ім’я: [const taux_tva as single=0.186F]
  2. Внесення змін до програми буде простішим, якщо «константа» зміниться. Так, у наведеному вище прикладі, якщо ставка ПДВ зміниться на 33%, єдиною зміною, яку потрібно буде внести, буде зміна оператора, що визначає її значення: [const taux_tva as single=0.336F]. Якби в програмі явно використовувалося значення 0,186, то довелося б змінювати безліч команд.

2.2.3.3. Оголошення змінних

Змінна ідентифікується за іменем і відноситься до певного типу даних. VB.NET не розрізняє великі та малі літери. Отже, змінні FIN та fin є ідентичними. Змінні можна ініціалізувати під час їх оголошення. Синтаксис оголошення однієї або декількох змінних такий:

dim variable1,variable2,...,variablen as identifier_of_type

де identificateur_de_type — це попередньо визначений тип або тип, визначений програмістом.

2.2.4. Перетворення між числами та рядками символів

nombre -> chaîne
nombre.ToString або "" & число або CType(число, String)
objet -> chaîne
objet.ToString
chaine -> Integer
Integer.Parse(рядок) або Int32.Parse
chaîne -> Long
Long.Parse (ланцюг) або Int64.Parse
chaîne -> Double
Double.Parse (рядок)
chaîne -> Single
Single.Parse (рядок)

Перетворення рядка на число може завершитися невдачею, якщо рядок не є дійсним числом. У цьому випадку генерується фатальна помилка, яка в VB.NET називається винятком. Цю помилку можна обробити за допомогою наступного оператора 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

Якщо функція не генерує винятку, то виконується наступна інструкція, інакше виконується тіло блоку catch, а потім — наступна інструкція. Ми повернемося до питання обробки винятків пізніше. Ось програма, що демонструє основні методи перетворення чисел у символьні рядки та навпаки. У цьому прикладі функція виводить на екран значення свого параметра. Таким чином, affiche(S) виводить значення S на екран.


' директиви
Option Strict On

' імпортовані простори імен
Imports System

' тестовий модуль
Module Module1

    Sub Main()
        ' головна процедура
        ' локальні дані
        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

        ' число --> рядок
        affiche(CType(i, String))
        affiche(CType(l, String))
        affiche(CType(f, String))
        affiche(CType(d, String))

        'логічне значення --> рядок
        Const b As Boolean = False
        affiche(b.ToString)

        ' рядок --> ціле
        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

        ' рядок --> long
        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

        ' рядок --> double
        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

        ' рядок --> 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

    ' виводить
    Public Sub affiche(ByVal S As String)
        Console.Out.WriteLine("S=" + S)
    End Sub
End Module

Отримано такі результати:

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.

Слід зауважити, що дійсні числа у вигляді символьного рядка повинні містити кому, а не крапку. Отже, слід написати Dim d As Double = -14.98, але Dim d1 As Double = Double.Parse("100,87")

2.2.5. Масиви даних

Масив VB.NET — це об’єкт, що дозволяє об’єднати дані одного типу під одним ідентифікатором. Його оголошення має такий вигляд:

Dim Tableau(n) as type або Dim Tableau() as type=New type(n) {}

де n — індекс останнього елемента масиву. Синтаксис Tableau(i) позначає дані № i, де i належить до інтервалу [0,n]. Будь-яке посилання на елемент Tableau(i), де i не належить до інтервалу [0,n], спричинить виняток. Масив можна ініціалізувати одночасно з його оголошенням. У цьому випадку не потрібно вказувати номер останнього елемента.


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

Масиви мають властивість Length, яка позначає кількість елементів масиву. Ось приклад програми:


Module tab0
    Sub Main()
        ' першу таблицю
        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

        ' друга таблиця
        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

та її виконання:

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

Двовимірний масив можна оголосити наступним чином:

Dim Масив(n,m) as Тип або Dim Масив(,) as Тип = New Тип(n,m) {}

де n+1 — кількість рядків, m+1 — кількість стовпців. Синтаксис Tableau(i,j) позначає елемент j у рядку i масиву Tableau. Двовимірний масив також можна ініціалізувати одночасно з його оголошенням:


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

Кількість елементів у кожному з вимірів можна отримати за допомогою методу GetLenth(i), де i=0 позначає вимір, що відповідає першому індексу, i=1 — вимір, що відповідає другому індексу, … Ось приклад програми:


Module Module2
    Sub Main()
        ' перша таблиця
        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

        ' друга таблиця
        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

та результати її виконання:

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

Масив масивів оголошується наступним чином:

Dim Tableau(n)() as Type або Dim Tableau()() as Type=new Type(n)()

Вищезазначене оголошення створює масив із n+1 рядків. Кожен елемент Tableau(i) є посиланням на одновимірний масив. Ці масиви не створюються під час вищезазначеного оголошення. Наведений нижче приклад ілюструє створення масиву масивів:


         ' масив масивів
        Dim noms()() As String = New String(3)() {}
         ' ініціалізація
        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

Тут noms(i) — це масив із i+1 елементів. Оскільки noms(i) є масивом, noms(i).Length — це кількість його елементів. Ось приклад, що об’єднує три типи масивів, які ми щойно розглянули:


' директиви
Option Strict On
Option Explicit On 

' імпорт
Imports System

' тестовий клас
Module test
    Sub main()
        ' ініціалізований одновимірний масив
        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

        ' ініціалізований двовимірний масив
        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

        ' масив масивів
        Dim noms()() As String = New String(3)() {}

        ' ініціалізація
        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

        ' виведення
        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

Під час виконання ми отримуємо такі результати:

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. Основні інструкції щодо VB.NET

Розрізняють

1 елементарні інструкції, що виконуються комп’ютером.

2 команди, що керують ходом виконання програми.

Елементарні інструкції стають очевидними, якщо розглянути структуру мікрокомп’ютера та його периферійних пристроїв.

  1. зчитування інформації з клавіатури

  2. обробка інформації

  3. виведення інформації на екран

  4. зчитування інформації з файлу на диску

  5. запис інформації у файл на диску

2.3.1. Виведення інформації на екран

Існують різні оператори виведення інформації на екран:

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

де expression — це будь-який тип даних, який можна перетворити на рядок символів для відображення на екрані. У прикладах, розглянутих до цього моменту, ми використовували лише інструкцію Console.Out.WriteLine(вираз).

Клас System.Console надає доступ до операцій запису на екран (Write, WriteLine). Клас Console має дві властивості Out та Error, які є потоками запису типу StreamWriter:

  • Console.WriteLine() еквівалентна Console.Out.WriteLine() і записує в потік Out, який зазвичай пов’язаний з екраном.
  • Console.Error.WriteLine() записує дані у потік Error, який зазвичай також пов’язаний з екраном.

Потоки Out та Error за замовчуванням пов’язані з екраном. Однак їх можна перенаправити у текстові файли під час виконання програми, як ми побачимо незабаром.

2.3.2. Зчитування даних, введених з клавіатури

Потік даних, що надходить з клавіатури, позначається об’єктом Console.In типу StreamReader. Цей тип об’єктів дозволяє зчитувати рядок тексту за допомогою методу ReadLine:


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

Рядок, введений з клавіатури, зберігається у змінній ligne і потім може бути оброблений об’єктом programme.Le. Потік In можна перенаправити у файл, так само як потоки Out та Error.

2.3.3. Приклад вводу-виводу

Ось коротка програма, що ілюструє операції введення-виведення з клавіатури та на екран:


' параметри
Option Explicit On 
Option Strict On

' простори імен
Imports System

' модуль
Module io1
    Sub Main()
        ' запис у потік Out
        Dim obj As New Object
        Console.Out.WriteLine(("" & obj.ToString))

        ' запис у потік Error
        Dim i As Integer = 10
        Console.Error.WriteLine(("i=" & i))

        ' читання рядка, введеного з клавіатури
        Console.Out.Write("Tapez une ligne : ")
        Dim ligne As String = Console.In.ReadLine()
        Console.Out.WriteLine(("ligne=" + ligne))
    End Sub
End Module

та результати виконання:

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

Інструкції


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

наведені лише для того, щоб показати, що будь-який об’єкт може бути відображений. Ми не будемо тут пояснювати значення того, що відображається.

2.3.4. Перенаправлення вводу-виводу

У DOS/Windows існують три стандартні периферійні пристрої, які називаються:

  1. стандартний пристрій введення — за замовчуванням позначає клавіатуру та має номер 0
  2. стандартний пристрій виводу — за замовчуванням позначає екран і має номер 1
  3. стандартний пристрій помилок — за замовчуванням позначає екран і має номер 2

У VB.NET потік запису Console.Out записує дані на пристрій 1, потік запису Console.Error записує дані на пристрій 2, а потік читання Console.In зчитує дані з пристрою 0. Запускаючи програму у вікні DOS під Windows, можна вказати, які саме пристрої 0, 1 та 2 будуть використовуватися для запущеної програми. Розглянемо такий рядок команд:

pg arg1 arg2 .. argn

За допомогою аргументів argi програми pg можна перенаправити стандартні пристрої вводу-виводу у файли:

0<in.txt
стандартний вхідний потік № 0 перенаправляється у файл in.txt. Отже, у програмі потік Console.In отримуватиме дані з файлу in.txt.
 
1>out.txt
перенаправляє вихід № 1 у файл out.txt. Це означає, що в програмі потік Console.Out запише свої дані у файл out.txt
  
1>>out.txt
те саме, але записані дані додаються до поточного вмісту файлу out.txt.
  
2>error.txt
перенаправляє вихід № 2 у файл error.txt. Це означає, що в програмі потік Console.Error запише свої дані у файл error.txt
  
2>>error.txt
те саме, але записані дані додаються до поточного вмісту файлу error.txt.
  
1>out.txt 2>error.txt
Пристрої 1 і 2 перенаправляються до файлів
  

Слід зауважити, що для перенаправлення потоків вводу-виводу програми pg у файли програму pg змінювати не потрібно. Саме програма OS визначає тип пристроїв 0, 1 та 2. Розглянемо таку програму:


' параметри
Option Explicit On 
Option Strict On

' простори імен
Imports System

' перенаправлення
Module console2
    Sub Main()
        ' читання потоку In
        Dim data As String = Console.In.ReadLine()
        ' запис потоку Out
        Console.Out.WriteLine(("écriture dans flux Out : " + data))
        ' запис потоку Error
        Console.Error.WriteLine(("écriture dans flux Error : " + data))
    End Sub
End Module

Скомпілюємо цю програму:

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

Давайте виконаємо перший запуск:

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

Попереднє виконання не перенаправляє жодного зі стандартних потоків вводу-виводу In, Out, Error. Тепер перенаправимо всі три потоки. Потік In буде перенаправлено до файлу in.txt, потік Out — у файл out.txt, а потік Error — у файл error.txt. Це перенаправлення виконується в командному рядку у вигляді

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

Виконання дає такі результати:

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

Чітко видно, що потоки Out та Error не записують дані на ті самі периферійні пристрої.

2.3.5. Присвоєння значення виразу змінній

Тут нас цікавить операція variable=expression. Вираз може бути такого типу: арифметичний, відносний, булевий, символьний.

2.3.5.1. Список операторів

Дія
Елемент мови
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. Арифметичний вираз

Оператори арифметичних виразів такі:

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

+: додавання, -: віднімання, *: множення, /: ділення з точністю до десятих, \,: частка при цілочисельному діленні, Mod: залишок при цілочисельному діленні, ^: піднесення до степеня. Отже, така програма:


' арифметичні оператори
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

дає такі результати:

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

Існують різні математичні функції. Ось деякі з них:


Public Shared Function Sqrt(ByVal d As Double ) As Double
квадратний корінь

[Visual Basic]
Public Shared Function Cos(ByVal d As Double ) As Double
Косинус

Public Shared Function Sin(ByVal a As Double) As Double
Синус

[Visual Basic]
Public Shared Function Tan(ByVal a As Double) As Double
Тангенс

[Visual Basic]
Public Shared Function Pow(ByVal x As Double,ByVal y As Double) As Double
x у степені y (x>0)

[Visual Basic]
Public Shared Function Exp(ByVal d As Double) As Double
Експонента

[Visual Basic]
Overloads Public Shared Function Log( ByVal d As Double ) As Double
Неперів логарифм

Overloads Public Shared Function Abs(ByVal value As Double ) As Double
абсолютне значення
....
 

Усі ці функції визначені в класі .NET під назвою Math. При їх використанні перед ними слід ставити префікс із назвою класу, в якому вони визначені. Отже, писатимемо так:

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

Повне визначення класу Math виглядає так:

E 
Позначає основу натурального логарифма, задану константою e.
  
PI 
Позначає відношення довжини кола до його діаметра, яке визначається константою π.
  
Abs 
Перевантажено. Повертає абсолютне значення вказаного числа.
 
Acos 
Повертає кут, косинус якого дорівнює вказаному числу.
 
Asin 
Повертає кут, синус якого дорівнює вказаному числу.
 
Atan 
Повертає кут, тангенс якого дорівнює вказаному числу.
 
Atan2 
Повертає кут, тангенс якого дорівнює частці двох вказаних чисел.
 
BigMul
Обчислює цілочисельний добуток двох 32-бітних чисел.
 
Ceiling 
Повертає найменше ціле число, яке не менше за вказане число.
 
Cos 
Повертає косинус заданого кута.
 
Cosh 
Повертає гіперболічний косинус заданого кута.
 
DivRem
Перевантажена функція. Повертає частку двох чисел, передаючи залишок як вихідний параметр.
 
Exp 
Повертає e, піднесений до вказаного степеня.
 
Floor 
Повертає найбільше ціле число, яке не перевищує вказаного числа.
 
IEEERemainder 
Повертає залишок від ділення одного числа на інше.
 
Log 
Перевантажена. Повертає логарифм заданого числа.
 
Log10 
Повертає логарифм за основою 10 заданого числа.
 
Max 
Перевантажена. Повертає більше з двох вказаних чисел.
 
Min 
Перевантажено. Повертає менше з двох чисел.
 
Pow 
Повертає вказане число, піднесене до вказаного степеня.
 
Round 
Перевантажена. Повертає число, найближче до вказаного значення.
 
Sign 
Перевантажена. Повертає значення, що вказує на знак числа.
 
Sin 
Повертає синус заданого кута.
 
Sinh 
Повертає гіперболічний синус заданого кута.
 
Sqrt 
Повертає квадратний корінь із заданого числа.
 
Tan 
Повертає тангенс заданого кута.
 
Tanh 
Повертає гіперболічну тангенсу заданого кута.
 

Коли функція оголошується «перевантаженою», це означає, що вона існує для різних типів параметрів. Наприклад, функція Abs(x) існує для x типу Integer, Long, Decimal, Single, Float. Для кожного з цих типів існує окреме визначення функції Abs. У такому випадку кажуть, що вона перевантажена.

2.3.5.3. Пріоритети при обчисленні арифметичних виразів

Пріоритет операторів під час обчислення арифметичного виразу є таким (від найвищого до найнижчого):

Категорія
Оператори
Primaire
Усі вирази без операторів: функції, дужки
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Модифікація
Addition
+, -

2.3.5.4. Реляційні вирази

Використовуються такі оператори:

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

=: дорівнює, <>: не дорівнює, <: менше (строго), >: більше (строго), <=: менше або дорівнює, >=: більше або дорівнює, Like: відповідає шаблону, Is: тотожність об’єктів. Усі ці оператори мають однаковий пріоритет. Вони обчислюються зліва направо. Результатом відносного виразу є булеве значення.

Порівняння символьних рядків: розглянемо таку програму:


' простори імен
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

та результат її виконання:

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

Нехай є два символи C1 та C2. Їх можна порівнювати за допомогою операторів: <, <=, =, <>, >, >=. У цьому випадку порівнюються їхні значення в кодуванні Unicode, які є числами. Згідно з порядком Unicode, маємо такі співвідношення:

пробіл < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'

Строки порівнюються символ за символом. Перша нерівність, що зустрічається між двома символами, зумовлює нерівність того самого знака для строк. З огляду на ці пояснення, читачеві пропонується проаналізувати результати попередньої програми.

2.3.5.5. Булеві вирази

Використовуються такі оператори:

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

Not: логічне «і», Or: логічне «або», Not: заперечення, Xor: виключне «або».

op1 AndAlso op2: якщо op1 є хибним, op2 не обчислюється, і результат є хибним.

op1 OrElse op2: якщо op1 істинне, op2 не обчислюється, і результат є істинним.

Пріоритет цих операторів між собою такий:

NOT logique
Not
AND logique
And, AndAlso
OR logique
Або, OrElse
XOR logique
Xor

Результатом булевого виразу є булеве значення.

2.3.5.6. Бітова обробка

З одного боку, тут використовуються ті самі оператори, що й у булевій логіці, з тим самим порядком пріоритету. Також є два оператори зсуву: << та >>. Нехай i та j — два цілі числа.

i<<n
зсуває i на n бітів вліво. Біти, що зсуваються, дорівнюють нулю.
i>>n
зсуває i на n бітів вправо. Якщо i є цілим числом зі знаком (signed char, int, long), біт знака зберігається.
i & j
виконує побітове логічне АБО i та j.
i | j
виконує побітову логічну операцію «і» над i та j.
~i
додає i до 1
i^j
створює OU EXCLUSIF з i та j

Нехай програма має такий вигляд:


Module operationsbit
    Sub main()
        ' операції з бітами
        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

Її виконання дає такі результати:

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

2.3.5.7. Оператор, пов'язаний з присвоюванням

Можна записати a+=b, що означає a=a+b. Список операторів, які можна поєднувати з операцією присвоювання, є таким:

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

2.3.5.8. Загальний порядок пріоритету операторів

Категорія
Оператори
Primaire
Усі вирази без операторів
Élévation à la puissance
^
Négation unaire
+, -
Multiplication
*, /
Division par un entier
\
Modulo
Модифікація
Addition
+, -
Concaténation
&
Déplacement
<<, >>
Relationnel
=, <>, <, >, <=, >=, Like, Is, TypeOf...Is
NOT logique
Не
AND logique
And, AndAlso
OR logique
Або, OrElse
XOR logique
XOR

Коли операнд розміщений між двома операторами однакової пріоритетності, порядок виконання операцій визначається асоціативністю операторів. Усі оператори є лівоасоціативними, що означає, що операції виконуються зліва направо. Пріоритет та асоціативність можна контролювати за допомогою виразів у дужках.

2.3.5.9. Перетворення типів

Існує низка попередньо визначених функцій, що дозволяють переходити від одного типу даних до іншого. Їхній перелік такий:

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

Ці функції приймають як аргумент числовий вираз або рядок символів. Тип результату вказано в наступній таблиці:

функція
результат
Діапазон значень параметра функції
CBool
Boolean
Будь-який допустимий рядок або числовий вираз.
CByte
Байт
Від 0 до 255; дроби округлюються.
CChar
Символ
Будь-який допустимий рядок; значення може бути в діапазоні від 0 до 65 535.
CDate
Дата
Будь-яке допустиме представлення дати та часу.
CDbl
Double
-1,79769313486231E+308 до
-4,94065645841247E-324 для від’ємних значень; від 4,94065645841247E-324 до 1,79769313486231E+308 для додатних значень.
CDec
Decimal
+/-79 228 162 514 264 337 593 543 950 335 для чисел без десяткових знаків. Діапазон значень чисел з 28 десятковими знаками становить
+/-7,9228162514264337593543950335. Найменше число, відмінне від нуля, дорівнює 0,0000000000000000000000000001.
CInt
Ціле число
від -2 147 483 648 до 2 147 483 647; дроби округлюються.
CLng
Довге число
Від -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807; дроби округлюються.

CObj 
Об’єкт
Будь-який допустимий вираз.
CShort
Короткий
Від -32 768 до 32 767; дроби округлюються.
CSng
Одинарний
від -3,402823E+38 до -1,401298E-45 для від’ємних значень; від 1,401298E-45 до 3,402823E+38 для додатних значень.
CStr
String
Значення, що повертаються функцією Cstr, залежать від аргументу expression.

Ось приклад програми:


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

та результати її виконання:

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

Також можна використовувати функцію CType(expression, type), як показано в наступній програмі:


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

що дає такі результати:

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. Інструкції щодо контролю за ходом виконання програми

2.4.1. Зупинка

Метод Exit, визначений у класі Environment, дозволяє зупинити виконання програми:


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

зупиняє поточний процес і повертає значення exitCode батьківському процесу. Цей процес може використовувати значення exitCode. У DOS ця змінна status повертається до DOS у системній змінній ERRORLEVEL, значення якої можна перевірити у командному файлі. У Unix значення exitCode зберігається у змінній $?.

    Environment.Exit(0)

припинить виконання програми зі статусом 0.

2.4.2. Проста структура вибору

if condition then
    actions_alors
else
    actions_sinon
end if
  • кожна дія знаходиться в окремому рядку
  • умова else може бути відсутньою.

Структури вибору можна вкладати одна в одну, як показано в наступному прикладі:


' параметри
Option Explicit On 
Option Strict On

' простори імен
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

Отриманий результат:

10 est > 4

2.4.3. Структура випадків

Синтаксис такий:

select case expression
    case liste_valeurs1
        actions1
case liste_valeurs2
        actions2
...
case else
        actions_sinon
end select
  • тип [expression] повинен відповідати одному з таких типів:
Boolean, Byte, Char, Date, Decimal, Double, Integer, Long, Object, Short, Single et String
  • умова [case else] може бути відсутньою.
  • [liste_valeursi] — можливі значення виразу. [listes_valeursi] представляє список умов condition1, condition2, ..., conditionx. Якщо [expression] задовольняє одну з умов, виконуються дії, визначені у клаузулі [liste_valeursi]. Умови можуть мати такий вигляд:
  • val1 to val2: істинне, якщо [expression] належить до області [val1,val2]
  • val1: істинне, якщо [expression] дорівнює val1
  • is > val1: істинне, якщо [expression] > val1. Ключове слово [is] може бути відсутнім
  • те саме стосується операторів =, <, <=, >, >=, <>
  • виконуються лише дії, пов’язані з першою перевіреною умовою.

Розглянемо таку програму:


' опції
Option Explicit On 
Option Strict On

' простори імен
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

Вона дає такі результати:

i est < 15

2.4.4. Структура повторення

2.4.4.1. Відома кількість повторень


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

Дії виконуються для кожного значення, яке приймає змінна [counter]. Розглянемо таку програму:


' параметри
Option Explicit On 
Option Strict On

' простори імен
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

Результати:

somme( 0 2 4 6 8 10)=30

Інша структура ітерації з відомим числом ітерацій виглядає так:


For Each element [ As datatype ] In groupe
   [ actions ]
Next [ element ]
  • groupe — це колекція об’єктів. Колекція об’єктів, яку ми вже знаємо, — це масив
  • datatype — це тип об’єктів колекції. Для масиву це був би тип елементів масиву
  • element — це локальна змінна циклу, яка послідовно прийматиме в якості значення всі значення колекції.

Отже, такий код:


' параметри
Option Explicit On 
Option Strict On

' простори імен
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

виведе:

paul
hélène
jacques
sylvie

2.4.4.2. Кількість повторень невідома

Для цього випадку існує багато структур у форматі VB.NET.


Do { While | Until } condition
   [ statements ]
Loop

Цикл виконується, доки виконується умова (while) або доки умова не буде виконана (until). Цикл може ніколи не виконатися.


Do
   [ statements ]
Loop { While | Until } condition

Цикл виконується, доки виконується умова (while) або доки умова не буде виконана (until). Цикл завжди виконується принаймні один раз.


While condition
   [ statements ]
End While

Цикл виконується, доки умова справджується. Цикл може ніколи не виконатися. Усі наведені нижче цикли обчислюють суму перших 10 цілих чисел.


' параметри
Option Explicit On 
Option Strict On

' простори імен
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. Інструкції з управління циклом

exit do
виходить із циклу do ... loop
exit for
виходить із циклу for

2.5. Структура програми VB.NET

Програма VB.NET, яка не використовує класів, визначених користувачем, та функцій, окрім головної функції Main, може мати таку структуру:


' параметри
Option Explicit On 
Option Strict On

' простори імен
Imports espace1
Imports ....

Module nomDuModule
    Sub main()
....
    End Sub
End Module
  • Директива [Option Explicit on] вимагає оголошення змінних. У VB.NET це не є обов’язковим. Неоголошена змінна має тип Object.
  • Директива [Option Strict on] забороняє будь-яке перетворення типів даних, яке може призвести до втрати даних, а також будь-яке перетворення між числовими типами та рядками. У такому випадку необхідно явно використовувати функції перетворення.
  • Програма імпортує всі необхідні їй простори імен. Ми ще не розглядали це поняття. У попередніх програмах ми часто зустрічали такі оператори:
        Console.Out.WriteLine(unechaine)

Насправді ми мали б написати:

        System.Console.Out.WriteLine(unechaine)

де System — це простір імен, що містить клас [Console]. Імпортуючи простір імен [System] за допомогою оператора Imports, VB.NET буде систематично обшукувати його, коли зустріне невідомий йому клас. Він повторюватиме пошук у всіх оголошених просторах імен, доки не знайде потрібний клас. Тоді ми пишемо:


' простори імен
Imports System
....

        Console.Out.WriteLine(unechaine)

Приклад програми може виглядати так:


' параметри
Option Explicit On 
Option Strict On

'простори імен
Imports System

' головний модуль
Module main1
    Sub main()
        Console.Out.WriteLine("main1")
    End Sub
End Module

Цю ж програму можна написати таким чином:


' параметри
Option Explicit On 
Option Strict On

'простори імен
Imports System

' тестовий клас
Public Class main2
    Public Shared Sub main()
        Console.Out.WriteLine("main2")
    End Sub
End Class

Тут ми використовуємо поняття класу, яке буде представлено в наступному розділі. Коли такий клас містить статичну (shared) процедуру з іменем main, вона виконується. Ми використовуємо такий запис тут тому, що мова C#, яка є аналогом VB.NET, знає лише поняття класу, c.a.d, згідно з яким будь-який код, що виконується, обов’язково належить до класу. Поняття класу належить до об’єктного програмування. Нав’язувати його при розробці будь-якої програми є дещо недоречним. Це видно тут, у версії 2 попередньої програми, де доводиться вводити поняття класу та статичного методу там, де в цьому немає потреби. Тому надалі ми будемо вводити поняття класу лише тоді, коли це буде необхідно. В інших випадках ми використовуватимемо поняття модуля, як у версії 1, наведеній вище.

2.6. Компіляція та виконання програми VB.NET

Для компіляції програми VB.NET потрібен лише файл SDK.NET. Розглянемо таку програму:


' параметри
Option Explicit On 
Option Strict On

' простори імен
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

Припустимо, що вона міститься у файлі з назвою [boucles1.vb]. Щоб її скомпілювати, ми робимо наступне:

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

Програма vbc.exe є компілятором VB.NET. Тут вона була в PATH з 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

Компілятор [vbc] створює виконуваний файл .exe для віртуальної машини .NET:

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

2.7. Приклад IMPOTS

Задамося метою написати програму, яка дозволить обчислити податок платника податків. Розглянемо спрощений випадок, коли платник податків має задекларувати лише свою заробітну плату:

  • розраховуємо кількість часткок працівника nbParts=nbEnfants/2 +1, якщо він не одружений, nbEnfants/2+2, якщо він одружений, де nbEnfants — кількість його дітей.
  • якщо у нього щонайменше троє дітей, він отримує на півчастини більше
  • розраховується його оподатковуваний дохід R = 0,72 * S, де S — його річна заробітна плата
  • розраховується його сімейний коефіцієнт QF = R / nbParts
  • розраховується його податок I. Розглянемо таку таблицю:
12620,0
0
0
13190
0,05
631
15640
0,1
1290,5
24740
0,15
2072,5
31810
0,2
3309,5
39970
0,25
4900
48360
0,3
6898,5
55790
0,35
9316,5
92970
0,4
12106
127860
0,45
16754,5
151250
0,50
23147,5
172040
0,55
30710
195 000
0,60
39312
0
0,65
49062

Кожен рядок має 3 поля. Щоб обчислити податок I, шукаємо перший рядок, у якому QF <= поле1. Наприклад, якщо QF = 23000, то знайдемо рядок

    24740        0.15        2072.5

Тоді податок I дорівнює 0,15*R - 2072,5*nbParts. Якщо QF є таким, що співвідношення QF<=поле1 ніколи не виконується, то використовуються коефіцієнти останнього рядка. У даному випадку:

    0                0.65        49062

що дає податок I=0,65*R - 49062*nbParts. Відповідна програма VB.NET має такий вигляд:


' параметри
Option Explicit On 
Option Strict On

' простори імен
Imports System

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

        ' таблиці даних, необхідні для розрахунку податку
        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}

        ' визначається сімейний стан
        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"

        ' кількість дітей
        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
        ' заробітна плата
        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
        ' розрахунок кількості часток
        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
        ' оподатковуваний дохід
        Dim Revenu As Decimal
        Revenu = 0.72D * Salaire

        ' сімейний коефіцієнт
        Dim QF As Decimal
        QF = Revenu / NbParts

        ' пошук податкової групи, що відповідає 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
        ' податок
        Dim impots As Integer = CInt(i * 0.05D * Revenu - CoeffN(i) * NbParts)

        ' відображається результат
        Console.Out.WriteLine(("Impôt à payer : " & impots))
    End Sub
End Module

Програма компілюється у вікні DOS за допомогою команди:

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

В результаті компіляції створюється виконуваний файл impots.exe. Слід зауважити, що файл impots.exe не може бути безпосередньо виконаний процесором. Насправді він містить проміжний код, який може бути виконаний лише на платформі .NET. Отримано такі результати:

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. Аргументи головної програми

Головна процедура Main може приймати як параметр масив рядків:


    Sub main(ByVal args() As String)

Параметр args — це масив символьних рядків, який приймає аргументи, передані в командному рядку під час виклику програми.

  • args.Length — кількість елементів масиву args
  • args(i) — це i-й елемент масиву

Якщо запустити програму P за допомогою команди: P arg0 arg1 … argn і якщо процедура Main програми P оголошена наступним чином:


    Sub main(ByVal args() As String)

то отримаємо arg(0)="arg0", arg(1)="arg1" … Ось приклад:


' інструкції
Option Strict On
Option Explicit On 

' простори імен
Imports System

Module arg
    Sub main(ByVal args() As String)
        ' кількість аргументів
        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

Виконання дає такі результати:

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

2.9. Переліки

Перелік — це тип даних, область значень якого складається з набору цілочисельних констант. Розглянемо програму, яка має обробляти оцінки за іспитом. Їх може бути п’ять: «Задовільно», AssezBien, «Добре», TrèsBien, «Відмінно». Тоді для цих п’яти констант можна визначити перелік:


    Enum mention
        Passable
        AssezBien
        Bien
        TrésBien
        Excellent
    End Enum

Внутрішньо ці п'ять констант кодуються послідовними цілими числами, починаючи з 0 для першої константи, 1 для наступної тощо. Змінну можна оголосити такою, що приймає ці значення з переліку:


         ' змінна, яка приймає значення з переліку
        Dim maMention As mention = mention.Passable

Змінну можна порівнювати з різними можливими значеннями переліку:


         ' перевірка зі значенням з переліку
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

Можна отримати всі значення переліку:


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

Так само, як простий тип Integer еквівалентний структурі Int32, простий тип Enum еквівалентний структурі Enum. Цей клас має статичний метод GetValues, який дозволяє отримати всі значення переліченого типу, що передається як параметр. Цей параметр повинен бути об’єктом типу Type, який є класом, що містить інформацію про тип даних. Тип змінної v отримується за допомогою v.GetType(). Отже, тут maMention.GetType() повертає об’єкт Type з переліку mentions, а Enum.GetValues(maMention.GetType()) — список значень переліку mentions.

Це ілюструє наступна програма:


' директиви
Option Strict On
Option Explicit On 

' простори імен
Imports System

Public Module enum2

    ' перелік
    Enum mention
        Passable
        AssezBien
        Bien
        TrèsBien
        Excellent
    End Enum

    ' тестова сторінка
    Sub Main()

        ' змінна, яка приймає значення з переліку
        Dim maMention As mention = mention.Passable

        ' виведення значення змінної
        Console.Out.WriteLine("mention=" & maMention)

        ' тест із значенням з переліку
        If (maMention = mention.Passable) Then
            Console.Out.WriteLine("Peut mieux faire")
        End If

        ' список літеральних позначень
        For Each m As mention In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m.ToString)
        Next

        ' список цілих згадок
        For Each m As Integer In [Enum].GetValues(maMention.GetType)
            Console.Out.WriteLine(m)
        Next
    End Sub
End Module

Результати виконання такі:

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

2.10. Обробка винятків

Багато функцій VB.NET можуть генерувати винятки, тобто помилки. Якщо функція може генерувати виняток, програміст повинен його обробляти, щоб зробити програми більш стійкими до помилок: завжди слід уникати неконтрольованого «зависання» програми.

Обробка винятку здійснюється за такою схемою:

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

Якщо функція не генерує винятку, то виконується наступна інструкція; в іншому випадку виконується тіло блоку catch, а потім — наступна інструкція. Звернімо увагу на наступні моменти:

  • e — це об’єкт, похідний від типу Exception. Можна бути точнішим, використовуючи такі типи, як IOException, SystemException тощо: існує кілька типів винятків. Записуючи catch e as Exception, ми вказуємо, що хочемо обробляти всі типи винятків. Якщо код блоку try може генерувати кілька типів винятків, можна бути більш точним, обробляючи виняток за допомогою кількох блоків 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
  • До умов try/catch можна додати умову finally:
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

Незалежно від того, чи є виняток, код у клаузулі finally завжди буде виконано.

  • У клаузулі catch може виникнути ситуація, коли не потрібно використовувати доступний об’єкт Exception. Замість того, щоб писати catch e as Exception, слід написати catch.
  • Клас Exception має властивість Message, яка містить детальне повідомлення про помилку, що сталася. Отже, якщо потрібно вивести це повідомлення, слід написати:
catch e as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+e.Message);
    ...
end try
  • Клас Exception має метод ToString, який повертає рядок, що вказує тип винятку, а також значення властивості Message. Таким чином, можна написати:
catch  ex as Exception
    Console.Error.WriteLine("L'erreur suivante s'est produite : "+ex.ToString)
    ...
end try

Наступний приклад ілюструє виняток, що виникає внаслідок використання елемента масиву, який не існує:


' параметри
Option Explicit On 
Option Strict On

' простори імен
Imports System

Module tab1
    Sub Main()
        ' оголошення та ініціалізація масиву
        Dim tab() As Integer = {0, 1, 2, 3}
        Dim i As Integer

        ' виведення масиву за допомогою циклу for
        For i = 0 To tab.Length - 1
            Console.Out.WriteLine(("tab[" & i & "]=" & tab(i)))
        Next i

        ' виведення масиву за допомогою циклу for each
        Dim élmt As Integer
        For Each élmt In tab
            Console.Out.WriteLine(élmt)
        Next élmt

        ' генерація винятку
        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

Виконання програми дає такі результати:

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.

Ось ще один приклад, де обробляється виняток, спричинений присвоєнням рядка символів числу, коли цей рядок не є числом:


' параметри
Option Strict On
Option Explicit On 

'імпорт
Imports System

Public Module console1
  Public Sub Main()
    ' Запитується ім'я
    System.Console.Write("Nom : ")

        ' читання відповіді
    Dim nom As String = System.Console.ReadLine()

        ' запитується вік
    Dim age As Integer
    Dim ageOK As Boolean = False
    Do While Not ageOK
      ' питання
      Console.Out.Write("âge : ")
      ' читання та перевірка відповіді
      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

        ' остаточне відображення
    Console.Out.WriteLine("Vous vous appelez [" & nom & "] et vous avez [" & age & "] ans")
  End Sub
End Module

Деякі результати виконання:

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. Передача параметрів у функцію

Тут ми розглянемо спосіб передачі параметрів у функцію. Розглянемо таку функцію:


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

У визначенні функції a називається формальним параметром. Він використовується виключно для потреб визначення функції changeInt. Його так само можна було б назвати b. Тепер розглянемо використання цієї функції:


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

Тут, у інструкції changeInt(age), age є фактичним параметром, який передасть своє значення формальному параметру a. Нас цікавить, як формальний параметр отримує значення відповідного йому фактичного параметра.

2.11.1. Передача за значенням

Наступний приклад показує, що параметри функції/процедури за замовчуванням передаються за значенням: тобто значення фактичного параметра копіюється у відповідний формальний параметр. Ми маємо дві окремі сутності. Якщо функція змінює формальний параметр, фактичний параметр при цьому ніяк не змінюється.


' опції
Option Explicit On 
Option Strict On

' передача параметрів за значенням у функцію
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

Отримано такі результати:

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

Значення 20 фактичного параметра було скопійовано у формальний параметр a. Потім цей параметр було змінено. Фактичний параметр залишився незмінним. Цей спосіб передачі підходить для вхідних параметрів функції.

2.11.2. Передача за посиланням

При передачі за посиланням фактичний параметр і формальний параметр є одним і тим самим об’єктом. Якщо функція змінює формальний параметр, фактичний параметр також змінюється. У VB.NET перед формальним параметром має стояти ключове слово ByRef. Ось приклад:


' опції
Option Explicit On 
Option Strict On

' передача параметрів за значенням у функцію
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

та результати виконання:

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

Фактичний параметр змінився відповідно до зміни формального параметра. Цей спосіб передачі підходить для вихідних параметрів функції.