Skip to content

4. Поширені класи .NET

Тут ми представимо кілька класів платформи .NET, які можуть бути цікавими навіть для початківців. Спочатку ми покажемо, як отримати інформацію про сотні доступних класів.

4.1. Пошук допомоги з SDK.NET

4.1.1. wincv

Якщо встановлено лише SDK, а не Visual Studio.NET, можна скористатися програмою wincv.exe, яка зазвичай знаходиться в каталозі SDK, наприклад, C:\Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1. При запуску цієї утиліти з’являється такий інтерфейс:

У полі (1) вводимо назву потрібного класу. У полі (2) з’являються різні можливі варіанти. Вибираємо відповідний, і в полі (3) отримуємо результат — у даному випадку клас HashTable. Цей метод підходить, якщо відома назва класу, який шукаємо. Якщо ж хочемо переглянути перелік можливостей, що пропонує платформа .NET, можна скористатися файлами HTML та StartHere.htm, які також знаходяться безпосередньо в папці інсталяції SSK.Net, наприклад C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

Image

Посилання .NET Framework SDK Documentation — це те, за яким слід перейти, щоб отримати загальний огляд класів .NET:

Image

Тут слід перейти за посиланням [Bibliothèque de classes]. Там міститься перелік усіх класів .NET:

Image

Перейдемо, наприклад, за посиланням System.Collections. Цей простір імен об’єднує різні класи, що реалізують колекції, серед яких клас HashTable:

Image

Перейдемо за посиланням HashTable нижче:

Image

Ми потрапляємо на таку сторінку:

Image

Зверніть увагу на положення курсора нижче. Він вказує на посилання, яке дозволяє вказати бажану мову програмування, в даному випадку Visual Basic.

Там міститься прототип класу, а також приклади його використання. Перейдімо за посиланням [Hashtable, membres] нижче:

Image

Ми отримуємо повний опис класу:

Image

Цей метод є найкращим для ознайомлення з SDK та його класами. Інструмент WinCV виявляється корисним, коли ви вже трохи знайомі з класом, але забули деякі з його членів. WinCV дозволяє швидко знайти клас та його члени.

4.2. Пошук допомоги щодо класів за допомогою VS.NET

Тут ми наводимо кілька вказівок щодо пошуку допомоги з Visual Studio.NET

4.2.1. Пункт меню «Довідка»

Виберімо пункт [?] у меню.

Image

З’явиться таке вікно:

Image

У випадаючому списку можна вибрати фільтр довідки. Тут ми виберемо фільтр [Visual Basic].

Image

Корисні дві довідки:

  • довідка щодо самої мови VB.NET (синтаксис)
  • довідка щодо classes.NET, які можна використовувати в мові VB.NET

Довідку щодо мови VB.NET можна переглянути через [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic]:

Image

Відкриється така сторінка довідки:

Image

Звідти за допомогою різних підрозділів можна отримати довідку з різних тем, пов’язаних із VB.NET. Зверніть увагу на навчальні матеріали щодо VB.NET:

Image

Щоб отримати доступ до різних класів платформи .NET, слід вибрати довідку [Visual Studio.NET/.NET Framework].

Image

Зокрема, звернемо увагу на розділ [Référence/Bibliothèque de classes]:

Image

Припустимо, що нас цікавить клас [ArrayList]. Він знаходиться в просторі імен [System.Collections]. Це потрібно знати, інакше краще скористатися методом пошуку, описаним нижче. Ми отримаємо таку довідку:

Image

Посилання [ArrayList, classe] надає загальний огляд класу:

Image

Такі сторінки існують для всіх класів. Вони містять короткий опис класу з прикладами. Щоб ознайомитися з описом членів класу, перейдіть за посиланням [ArrayList, membres]:

Image

4.2.2. Довідка/Індекс

Image

Опція [Aide/index] дозволяє знайти допомогу, яка є більш цілеспрямованою, ніж попередня. Достатньо ввести ключове слово, яке шукаєте:

Image

Перевага цього методу порівняно з попереднім полягає в тому, що не потрібно знати, де саме в системі довідки знаходиться те, що ви шукаєте. Ймовірно, цей метод є кращим для цілеспрямованого пошуку, тоді як інший метод більше підходить для ознайомлення з усім, що пропонує довідка.

4.3. Клас String

Клас String має багато властивостей і методів. Ось деякі з них:

Public ReadOnly Property Length As Integer
кількість символів у рядку
Public Default ReadOnly Property 
Chars(ByVal index As Integer) As Char
властивість, індексована за замовчуванням. [String].Chars(i) — це символ № i у рядку
Public Function EndsWith(ByVal value As String) 
As Boolean
повертає «true», якщо рядок закінчується значенням
Public Function StartsWith(ByVal value As String) 
As Boolean
повертає «true», якщо рядок починається зі значення
Overloads Public Function Equals(ByVal value 
As String) As Boolean
повертає «true», якщо рядок дорівнює value
Overloads Public Function IndexOf(ByVal value 
As String) As Integer
повертає першу позицію в рядку value — пошук починається з символу № 0
Overloads Public Function IndexOf(ByVal value 
As String,ByVal startIndex As Integer) As Integer
повертає першу позицію в рядку value — пошук починається з символу № startIndex
Overloads Public Shared Function 
Join(ByVal separator As String,ByVal value() 
As String) As String
метод класу — повертає рядок, що є результатом об'єднання елементів масиву value з роздільником separator
Overloads Public Function Replace(ByVal oldChar 
As Char,ByVal newChar As Char) As String
повертає копію поточного рядка, в якому символ oldChar замінено на символ newChar
Overloads Public Function Split(ByVal ParamArray
separator() As Char) As String()
рядок розглядається як послідовність полів, розділених символами, що містяться в масиві separator. Результатом є масив цих полів
Overloads Public Function Substring(
ByVal startIndex As Integer,ByVal length As Integer) 
As String
підрядок поточного рядка, що починається з позиції startIndex і має довжину length символів
Overloads Public Function ToLower() 
As String
перетворює поточний рядок на малі літери
Overloads Public Function ToUpper() 
As String
перетворює поточний рядок на великі літери
Overloads Public Function Trim() 
As String
видаляє пробіли на початку та в кінці поточного рядка

Рядок C можна розглядати як масив символів. Отже

  • C.Chars(i) — це i-й символ у C
  • C.Length — кількість символів у C

Розглянемо такий приклад:


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

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

Module test
    Sub Main()
        Dim uneChaine As String = "l'oiseau vole au-dessus des nuages"
        affiche("uneChaine=" + uneChaine)
        affiche("uneChaine.Length=" & uneChaine.Length)
        affiche("chaine[10]=" + uneChaine.Chars(10))
        affiche("uneChaine.IndexOf(""vole"")=" & uneChaine.IndexOf("vole"))
        affiche("uneChaine.IndexOf(""x"")=" & uneChaine.IndexOf("x"))
        affiche("uneChaine.LastIndexOf('a')=" & uneChaine.LastIndexOf("a"c))
        affiche("uneChaine.LastIndexOf('x')=" & uneChaine.LastIndexOf("x"c))
        affiche("uneChaine.Substring(4,7)=" + uneChaine.Substring(4, 7))
        affiche("uneChaine.ToUpper()=" + uneChaine.ToUpper())
        affiche("uneChaine.ToLower()=" + uneChaine.ToLower())
        affiche("uneChaine.Replace('a','A')=" + uneChaine.Replace("a"c, "A"c))
        Dim champs As String() = uneChaine.Split(Nothing)
        Dim i As Integer
        For i = 0 To champs.Length - 1
            affiche("champs[" & i & "]=[" & champs(i) & "]")
        Next i
        affiche("Join("":"",champs)=" + System.String.Join(":", champs))
        affiche("(""  abc  "").Trim()=[" + "  abc  ".Trim() + "]")
    End Sub

    ' виводить
    Sub affiche(ByVal msg As [String])
        ' відображає повідомлення
        Console.Out.WriteLine(msg)
    End Sub
End Module

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

dos>vbc string1.vb

dos>string1
uneChaine=l'oiseau vole au-dessus des nuages
uneChaine.Length=34
chaine[10]=o
uneChaine.IndexOf("vole")=9
uneChaine.IndexOf("x")=-1
uneChaine.LastIndexOf('a')=30
uneChaine.LastIndexOf('x')=-1
uneChaine.Substring(4,7)=seau vo
uneChaine.ToUpper()=L'OISEAU VOLE AU-DESSUS DES NUAGES
uneChaine.ToLower()=l'oiseau vole au-dessus des nuages
uneChaine.Replace('a','A')=l'oiseAu vole Au-dessus des nuAges
champs[0]=[l'oiseau]
champs[1]=[vole]
champs[2]=[au-dessus]
champs[3]=[des]
champs[4]=[nuages]
Join(":",champs)=l'oiseau:vole:au-dessus:des:nuages
("  abc  ").Trim()=[abc]

Розглянемо новий приклад:


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

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

Module string2
    Sub Main()
        ' рядок для аналізу
        Dim ligne As String = "un:deux::trois:"
        ' роздільники полів
        Dim séparateurs() As Char = {":"c}
        ' розділення
        Dim champs As String() = ligne.Split(séparateurs)
        Dim i As Integer
        For i = 0 To champs.Length - 1
            Console.Out.WriteLine(("Champs[" & i & "]=" & champs(i)))
        Next i
        ' об'єднання
        Console.Out.WriteLine(("join=[" + System.String.Join(":", champs) + "]"))
    End Sub
End Module

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

Champs[0]=un
Champs[1]=deux
Champs[2]=
Champs[3]=trois
Champs[4]=
join=[un:deux::trois:]

Метод Split класу String дозволяє розмістити поля символьного рядка в масиві. Визначення методу, що використовується тут, є таким:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()
separator
масив символів. Ці символи відповідають тим, що використовуються для розділення полів у символьному рядку. Так, якщо рядок має вигляд [champ1, champ2, champ3], можна використовувати separator=new char() {","c}. Якщо роздільником є послідовність пробілів, слід використовувати separator=nothing.
résultat
масив рядків, де кожен елемент є полем рядка.

Метод Join є статичним методом класу String:

Overloads Public Shared Function Join(ByVal separator As String,ByVal value() As String) As String
value
масив символьних рядків
separator
рядок, який слугуватиме роздільником полів
résultat
рядок, утворений об'єднанням елементів масиву value, розділених рядком separator.

4.4. Клас Array

Клас Array реалізує масив. У нашому прикладі ми будемо використовувати такі властивості та методи:

Public ReadOnly Property Length As Integer
властивість — кількість елементів масиву
Overloads Public Shared Function BinarySearch
(ByVal array As Array,ByVal index As Integer,
ByVal length As Integer,ByVal value As Object) As Integer
метод класу — повертає позицію value у відсортованому масиві array — шукає, починаючи з позиції index, і з length елементами
Overloads Public Shared Sub Copy(ByVal sourceArray 
As Array,ByVal destinationArray As Array,
ByVal length As Integer)
метод класу — копіює елементи length з sourceArray у destinationArray — при цьому створюється destinationArray
Overloads Public Shared Sub Sort(ByVal array As Array)
метод класу — сортує масив array — він повинен містити тип даних із функцією сортування за замовчуванням (рядки, числа).

Наступна програма ілюструє використання класу Array:


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

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

Module test
    Sub Main()
        ' зчитування елементів масиву, введених з клавіатури
        Dim terminé As [Boolean] = False
        Dim i As Integer = 0
        Dim éléments1 As Double() = Nothing
        Dim éléments2 As Double() = Nothing
        Dim élément As Double = 0
        Dim réponse As String = Nothing
        Dim erreur As [Boolean] = False

        While Not terminé
            ' запитання
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' зчитування відповіді
            réponse = Console.ReadLine().Trim()
            ' завершення введення, якщо рядок порожній
            If réponse.Equals("") Then
                Exit While
            End If
            ' перевірка введених даних
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' якщо помилок немає
            If Not erreur Then
                ' створення нового масиву для нового елемента
                éléments2 = New Double(i) {}
                ' копіювання старого масиву в новий масив
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' новий масив стає старим масивом
                éléments1 = éléments2
                ' новий масив більше не потрібен
                éléments2 = Nothing
                ' вставлення нового елемента
                éléments1(i) = élément
                ' ще один елемент у масиві
                i += 1
            End If
        End While
        ' відображення несортованого масиву
        System.Console.Out.WriteLine("Tableau non trié")
        For i = 0 To éléments1.Length - 1
            Console.Out.WriteLine(("éléments[" & i & "]=" & éléments1(i)))
        Next i
        ' сортування таблиці
        System.Array.Sort(éléments1)
        ' відображення відсортованої таблиці
        System.Console.Out.WriteLine("Tableau trié")
        For i = 0 To éléments1.Length - 1
            Console.Out.WriteLine(("éléments[" & i & "]=" & éléments1(i)))
        Next i
        ' Пошук
        While Not terminé
            ' запитання
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' прочитати та перевірити відповідь
            réponse = Console.ReadLine().Trim()
            ' закінчено?
            If réponse.Equals("") Then
                Exit While
            End If
            ' перевірка
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' якщо помилок немає
            If Not erreur Then
                ' шукаємо елемент у відсортованому масиві
                i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
                ' Виведення відповіді
                If i >= 0 Then
                    Console.Out.WriteLine(("Trouvé en position " & i))
                Else
                    Console.Out.WriteLine("Pas dans le tableau")
                End If
            End If
        End While
    End Sub
End Module

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

Elément (réel) 0 du tableau (rien pour terminer) : 10,4
Elément (réel) 1 du tableau (rien pour terminer) : 5,2
Elément (réel) 2 du tableau (rien pour terminer) : 8,7
Elément (réel) 3 du tableau (rien pour terminer) : 3,6
Elément (réel) 4 du tableau (rien pour terminer) :
Tableau non trié
éléments[0]=10,4
éléments[1]=5,2
éléments[2]=8,7
éléments[3]=3,6
Tableau trié
éléments[0]=3,6
éléments[1]=5,2
éléments[2]=8,7
éléments[3]=10,4
Elément cherché (rien pour arrêter) : 8,7
Trouvé en position 2
Elément cherché (rien pour arrêter) : 11
Pas dans le tableau
Elément cherché (rien pour arrêter) : a
Saisie incorrecte, recommencez
Elément cherché (rien pour arrêter) :

У першій частині програми створюється масив на основі числових даних, введених з клавіатури. Розмір масиву неможливо визначити заздалегідь, оскільки невідомо, скільки елементів введе користувач. Тому ми працюємо з двома масивами éléments1 та éléments2.


                ' новий масив для розміщення нового елемента
                éléments2 = New Double(i) {}
                ' копіювання старого масиву в новий масив
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' новий масив стає старим масивом
                éléments1 = éléments2
                ' новий масив більше не потрібен
                éléments2 = Nothing
                ' вставлення нового елемента
                éléments1(i) = élément
                ' ще один елемент у таблиці
                i += 1

Масив éléments1 містить значення, введені на даний момент. Коли користувач додає нове значення, створюється масив éléments2, який має на один елемент більше, ніж éléments1, вміст éléments1 копіюється в éléments2 (Array.Copy), направляємо «посилання» éléments1 на éléments2 і, нарешті, додаємо новий елемент до éléments1. Це складний процес, який можна спростити, якщо замість масиву фіксованого розміру (Array) використовувати масив змінного розміру (ArrayList).

Масив сортується за допомогою методу Array.Sort. Цей метод можна викликати з різними параметрами, що визначають правила сортування. Без параметрів за замовчуванням виконується сортування за зростанням. Нарешті, метод Array.BinarySearch дозволяє шукати елемент у відсортованому масиві.

4.5. Клас ArrayList

Клас ArrayList дозволяє реалізовувати масиви змінного розміру під час виконання програми, чого не дозволяє попередній клас Array. Ось деякі з поширених властивостей та методів:

Public Sub New()
створює порожній список
Public Overridable ReadOnly Property Count 
As Integer  Implements ICollection.Count
кількість елементів у колекції
Public Overridable Function Add(ByVal value 
As Object) As Integer Implements IList.Add
додає об’єкт value в кінець колекції
Public Overridable Sub Clear() 
Implements IList.Clear
очищає список
Overloads Public Overridable Function 
IndexOf(ByVal value As Object) As Integer 
Implements IList.IndexOf
індекс елемента value у списку або -1, якщо його немає
Overloads Public Overridable Function 
IndexOf(ByVal value As Object, ByVal startIndex 
As Integer) As Integer
те саме, але з пошуком, починаючи з елемента № startIndex
Overloads Public Overridable Function 
LastIndexOf(ByVal value As Object) As Integer
те саме, але повертає індекс останнього входження значення у списку
Overloads Public Overridable Function 
LastIndexOf(ByVal value As Object, ByVal startIndex As Integer) As Integer
те саме, але з пошуком, починаючи з елемента № startIndex
Public Overridable Sub Remove( ByVal obj As Object)
Implements IList.Remove
видалити об’єкт obj, якщо він є у списку
Public Overridable Sub RemoveAt(ByVal index As Integer) 
Implements IList.RemoveAt
видаляє елемент з індексом із списку
Overloads Public Overridable Function 
BinarySearch(ByVal value As Object) As Integer
повертає позицію об’єкта value у списку або -1, якщо його там немає. Список має бути відсортований
Overloads Public Overridable Sub Sort()
сортує список. Список повинен містити об’єкти з попередньо визначеним порядком (рядки, числа)
Overloads Public Overridable Sub 
Sort(ByVal comparer As IComparer)
сортує список відповідно до порядку, встановленого функцією порівняння

Повернемося до прикладу, розглянутого з об’єктами типу Array, і розглянемо його з об’єктами типу ArrayList:


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

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

Module test
    Sub Main()
        ' читання елементів масиву, введених з клавіатури
        Dim terminé As [Boolean] = False
        Dim i As Integer = 0
        Dim éléments As New ArrayList
        Dim élément As Double = 0
        Dim réponse As String = Nothing
        Dim erreur As [Boolean] = False

        While Not terminé
            ' питання
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' зчитування відповіді
            réponse = Console.ReadLine().Trim()
            ' завершення введення, якщо рядок порожній
            If réponse.Equals("") Then
                Exit While
            End If
            ' перевірка введених даних
            Try
                élément = Double.Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' якщо помилок немає
            If Not erreur Then
                ' ще один елемент у масиві
                éléments.Add(élément)
            End If
        End While
        ' виведення несортованого масиву
        System.Console.Out.WriteLine("Tableau non trié")
        For i = 0 To éléments.Count - 1
            Console.Out.WriteLine(("éléments[" & i & "]=" & éléments(i).ToString))
        Next i        ' tri du tableau
        éléments.Sort()
        ' виведення відсортованого масиву
        System.Console.Out.WriteLine("Tableau trié")
        For i = 0 To éléments.Count - 1
            Console.Out.WriteLine(("éléments[" & i & "]=" & éléments(i).ToString))
        Next i
        ' Пошук
        While Not terminé
            ' питання
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' прочитати та перевірити відповідь
            réponse = Console.ReadLine().Trim()
            ' закінчено?
            If réponse.Equals("") Then
                Exit While
            End If
            ' перевірка
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' якщо помилок немає
            If Not erreur Then
                ' шукаємо елемент у відсортованому масиві
                i = éléments.BinarySearch(élément)
                ' Виведення відповіді
                If i >= 0 Then
                    Console.Out.WriteLine(("Trouvé en position " & i))
                Else
                    Console.Out.WriteLine("Pas dans le tableau")
                End If
            End If
        End While
    End Sub
End Module

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

Elément (réel) 0 du tableau (rien pour terminer) : 10,4
Elément (réel) 0 du tableau (rien pour terminer) : 5,2
Elément (réel) 0 du tableau (rien pour terminer) : a
Saisie incorrecte, recommencez
Elément (réel) 0 du tableau (rien pour terminer) : 3,7
Elément (réel) 0 du tableau (rien pour terminer) : 15
Elément (réel) 0 du tableau (rien pour terminer) :
Tableau non trié
éléments[0]=10,4
éléments[1]=5,2
éléments[2]=3,7
éléments[3]=15
Tableau trié
éléments[0]=3,7
éléments[1]=5,2
éléments[2]=10,4
éléments[3]=15
Elément cherché (rien pour arrêter) : a
Saisie incorrecte, recommencez
Elément cherché (rien pour arrêter) : 15
Trouvé en position 3
Elément cherché (rien pour arrêter) : 1
Pas dans le tableau
Elément cherché (rien pour arrêter) :

4.6. Клас Hashtable

Клас Hashtable дозволяє реалізувати словник. Словник можна уявити як таблицю з двома стовпцями:

Ключі є унікальними, c.a.d, тобто не може бути двох однакових ключів. Основні методи та властивості класу Hashtable такі:

Public Sub New()
створює порожній словник
Public Overridable Sub Add(ByVal key As
Object,ByVal value As Object) 
Implements IDictionary.Add
додає рядок (key, value) до словника, де key та value є посиланнями на об’єкти.
Public Overridable Sub Remove
(ByVal key As Object) Implements IDictionary.Remove
видаляє зі словника рядок з ключем key
Public Overridable Sub Clear() 
Implements IDictionary.Clear
очищає словник
Public Overridable Function ContainsKey
(ByVal key As Object) As Boolean
повертає значення «true», якщо ключ key є у словнику.
Public Overridable Function 
ContainsValue(ByVal value As Object) As Boolean
повертає значення «true», якщо значення value належить до словника.
Public Overridable ReadOnly Property 
Count As Integer  Implements ICollection.Count
властивість: кількість елементів словника (ключ, значення)
Public Overridable ReadOnly Property 
Keys As ICollection Implements IDictionary.Keys
властивість: набір ключів словника
Public Overridable ReadOnly Property 
Values As ICollection Implements IDictionary.Values
властивість: набір значень словника
Public Overridable Default Property 
Item(ByVal key As Object) As Object  Implements IDictionary.Item
індексована властивість: дозволяє дізнатися або встановити значення, пов’язане з ключем key

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


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

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

Module test
    Sub Main()
        Dim liste() As [String] = {"jean:20", "paul:18", "mélanie:10", "violette:15"}
        Dim i As Integer
        Dim champs As [String]() = Nothing
        Dim séparateurs() As Char = {":"c}
        ' заповнення словника
        Dim dico As New Hashtable
        For i = 0 To liste.Length - 1
            champs = liste(i).Split(séparateurs)
            dico.Add(champs(0), champs(1))
        Next i
        ' кількість елементів у словнику
        Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
        ' список ключів
        Console.Out.WriteLine("[Liste des clés]")
        Dim clés As IEnumerator = dico.Keys.GetEnumerator()
        While clés.MoveNext()
            Console.Out.WriteLine(clés.Current)
        End While
        ' список значень
        Console.Out.WriteLine("[Liste des valeurs]")
        Dim valeurs As IEnumerator = dico.Values.GetEnumerator()
        While valeurs.MoveNext()
            Console.Out.WriteLine(valeurs.Current)
        End While
        ' список ключів та значень
        Console.Out.WriteLine("[Liste des clés & valeurs]")
        clés.Reset()
        While clés.MoveNext()
            Console.Out.WriteLine(("clé=" & clés.Current.ToString & " valeur=" & dico(clés.Current).ToString))
        End While
        ' видаляємо ключ «paul»
        Console.Out.WriteLine("[Suppression d'une clé]")
        dico.Remove("paul")
        ' список ключів та значень
        Console.Out.WriteLine("[Liste des clés & valeurs]")
        clés = dico.Keys.GetEnumerator()
        While clés.MoveNext()
            Console.Out.WriteLine(("clé=" & clés.Current.ToString & " valeur=" & dico(clés.Current).ToString))
        End While

        ' пошук у словнику
        Dim nomCherché As [String] = Nothing
        Console.Out.Write("Nom recherché (rien pour arrêter) : ")
        nomCherché = Console.ReadLine().Trim()
        Dim value As [Object] = Nothing
        While Not nomCherché.Equals("")
            If dico.ContainsKey(nomCherché) Then
                value = dico(nomCherché)
                Console.Out.WriteLine((nomCherché + "," + CType(value, [String])))
            Else
                Console.Out.WriteLine(("Nom " + nomCherché + " inconnu"))
            End If
            ' наступний пошук
            Console.Out.Write("Nom recherché (rien pour arrêter) : ")
            nomCherché = Console.ReadLine().Trim()
        End While
    End Sub
End Module

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

Le dictionnaire a 4 éléments
[Liste des clés]
mélanie
paul
violette
jean
[Liste des valeurs]
10
18
15
20
[Liste des clés & valeurs]
clé=mélanie valeur=10
clé=paul valeur=18
clé=violette valeur=15
clé=jean valeur=20
[Suppression d'une clé]
[Liste des clés & valeurs]
clé=mélanie valeur=10
clé=violette valeur=15
clé=jean valeur=20
Nom recherché (rien pour arrêter) : paul
Nom paul inconnu
Nom recherché (rien pour arrêter) : mélanie
mélanie,10
Nom recherché (rien pour arrêter) :

Програма також використовує об’єкт IEnumerator для перегляду колекцій ключів та значень словника типу ICollection (див. вище властивості Keys та Values). Колекція — це сукупність об’єктів, яку можна переглядати. Інтерфейс ICollection визначено так:

Image

Властивість Count дозволяє дізнатися кількість елементів у колекції. Інтерфейс ICollection походить від інтерфейсу IEnumerable:

Image

Цей інтерфейс має лише один метод GetEnumerator, який дозволяє отримати об’єкт типу IEnumerator:

Image

Метод GetEnumerator() колекції ICollection дозволяє нам перебирати колекцію за допомогою таких методів:

MoveNext
переміщує курсор на наступний елемент колекції. Повертає значення true, якщо цей елемент існує, і false — якщо ні. Перший виклик MoveNext переміщує курсор на перший елемент. «Поточний» елемент колекції тоді доступний у властивості Current перелічувача
Current
властивість: поточний елемент колекції
Reset
переміщує індекс на початок колекції, c.a.d, перед першим елементом.

Отже, структура ітерації по елементах колекції (ICollection) на мові C виглядає наступним чином:

' визначити колекцію
dim C as ICollection C=...
' отримати індексер цієї колекції
dim itérateur as IEnumerator=C.GetEnumerator();
' пробіг по колекції за допомогою цього індексатора
while(itérateur.MoveNext())
    ' маємо поточний елемент
     ' використати itérateur.Current
end while

4.7. Клас StreamReader

Клас StreamReader дозволяє читати вміст файлу. Ось деякі з його властивостей та методів:

Public Sub New(ByVal path As String)
відкриває потік з файлу path. Якщо файл не існує, генерується виняток
Overrides Public Sub Close()
закриває потік
Overrides Public Function ReadLine() As String
зчитує рядок із відкритого потоку
Overrides Public Function ReadToEnd() As String
зчитує решту потоку, починаючи з поточної позиції

Ось приклад:


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

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

Module test
    Sub Main()
        Dim ligne As String = Nothing
        Dim fluxInfos As StreamReader = Nothing
        ' читання вмісту файлу
        Try
            fluxInfos = New StreamReader("infos.txt")
            ligne = fluxInfos.ReadLine()
            While Not (ligne Is Nothing)
                System.Console.Out.WriteLine(ligne)
                ligne = fluxInfos.ReadLine()
            End While
        Catch e As Exception
            System.Console.Error.WriteLine("L'erreur suivante s'est produite : " & e.ToString)
        Finally
            Try
                fluxInfos.Close()
            Catch
            End Try
        End Try
    End Sub
End Module

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

dos>more infos.txt
12620: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,5:23147,5
172040:0,55:30710
195000:0,6:39312
0:0,65:49062

dos>file1
12620: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,5:23147,5
172040:0,55:30710
195000:0,6:39312
0:0,65:49062

4.8. Клас StreamWriter

Клас StreamWriter дозволяє записувати дані у файл. Ось деякі з його властивостей та методів:

Public Sub New(ByVal path As String)
відкриває потік запису з файлу path. Якщо файл не вдається створити, генерується виняток
Public Overridable Property AutoFlush 
As Boolean
якщо значення дорівнює true, запис у потік відбувається без використання буфера; в іншому випадку запис у потік не відбувається негайно: спочатку дані записуються в буфер, а потім — у потік, коли буфер заповнюється. За замовчуванням використовується режим з буфером. Він добре підходить для файлових потоків, але, як правило, не підходить для мережевих потоків.
Public Overridable Property NewLine 
As String
щоб встановити або дізнатися маркер кінця рядка, який має використовуватися методом WriteLine
Overrides Public Sub Close()
закриває потік
Overloads Public Overridable Sub 
WriteLine(ByVal value As String)
записує рядок у потік запису
Overrides Public Sub Flush()
записує вміст буфера в потік

Розглянемо такий приклад:


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

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

Module test
    Sub Main()
        Dim ligne As String = Nothing        ' une ligne de texte
        Dim fluxInfos As StreamWriter = Nothing        ' le fichier texte
        Try
            ' створення текстового файлу
            fluxInfos = New StreamWriter("infos.txt")
            ' читання рядка, введеного з клавіатури
            Console.Out.Write("ligne (rien pour arrêter) : ")
            ligne = Console.In.ReadLine().Trim()
            ' цикл, поки введений рядок не є порожнім
            While ligne <> ""
                ' запис рядка у текстовий файл
                fluxInfos.WriteLine(ligne)
                ' читання нового рядка з клавіатури
                Console.Out.Write("ligne (rien pour arrêter) : ")
                ligne = Console.In.ReadLine().Trim()
            End While
        Catch e As Exception
            System.Console.Error.WriteLine("L'erreur suivante s'est produite : " & e.ToString)
        Finally
            ' закриття файлу
            Try
                fluxInfos.Close()
            Catch
            End Try
        End Try
    End Sub
End Module

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

dos>file2
ligne (rien pour arrêter) : ligne1
ligne (rien pour arrêter) : ligne2
ligne (rien pour arrêter) : ligne3
ligne (rien pour arrêter) :

dos>more infos.txt
ligne1
ligne2
ligne3

4.9. Клас Regex

Клас Regex дозволяє використовувати регулярні вирази. Вони дають змогу перевіряти формат символьного рядка. Таким чином можна перевірити, чи рядок, що позначає дату, має формат дд/мм/рр. Для цього використовується шаблон, з яким порівнюється рядок. Отже, у цьому прикладі символи j, m та a мають бути цифрами. Шаблон дійсного формату дати має вигляд «\d\d/\d\d/\d\d», де символ \d позначає цифру. У шаблоні можна використовувати такі символи (документація Microsoft):

 
Опис
\ 
Позначає наступний символ як спеціальний або літеральний. Наприклад, «n» відповідає символу «n». «\n» відповідає символу нового рядка. Послідовність «\\» відповідає «\», а «\(" відповідає «(».
^ 
Відповідає початку введення.
$ 
Відповідає кінцю введення.
* 
Відповідає попередньому символу нуль або більше разів. Таким чином, «zo*» відповідає «z» або «zoo».
+ 
Відповідає попередньому символу один або кілька разів. Таким чином, «zo+» відповідає «zoo», але не «z».
? 
Відповідає попередньому символу нуль або один раз. Наприклад, «a?ve?» відповідає «ve» у слові «lever».
.
Відповідає будь-якому окремому символу, крім символу нового рядка.

(modèle) 
Здійснює пошук за modèle і запам'ятовує збіг. Відповідний підрядок можна витягти з отриманої колекції Matches за допомогою елемента [0]...[n]. Щоб знайти збіги з символами в дужках ( ), використовуйте "\(" або "\)".

x|y
Відповідає або x, або y. Наприклад, «z|foot» відповідає «z» або «foot». «(z|f)oo» відповідає «zoo» або «foo».

{n}
n — це невід’ємне ціле число. Відповідає точно n, помноженому на символ. Наприклад, «o{2}» не відповідає «o» у слові «Bob», а відповідає двом першим «o» у слові «fooooot».

{n,} 
n — це невід’ємне ціле число. Відповідає щонайменше n-кратному кількості символів. Наприклад, «o{2,}» не відповідає «o» у слові «Bob», а відповідає всім «o» у слові «fooooot». «o{1,}» еквівалентно «o+», а «o{0,}» — «o*».

{n,m} 
m та n — це невід’ємні цілі числа. Відповідає щонайменше n і щонайбільше m повторень символу. Наприклад, «o{1,3}» відповідає трьом першим «o» у слові «foooooot», а «o{0,1}» дорівнює «o?».

[xyz] 
Набір символів. Відповідає одному з вказаних символів. Наприклад, «[abc]» відповідає «a» у слові «plat».

[^xyz] 
Негативний набір символів. Відповідає будь-якому символу, що не вказано. Наприклад, «[^abc]» відповідає «p» у слові «plat».

[a-z] 
Діапазон символів. Відповідає будь-якому символу у вказаному діапазоні. Наприклад, «[a-z]» відповідає будь-якій маленькій літері від «a» до «z».

[^m-z] 
Негативний діапазон символів. Відповідає будь-якому символу, якого немає у вказаній послідовності. Наприклад, «[^m-z]» відповідає будь-якому символу, якого немає між «m» і «z».
\b 
Відповідає межі, що позначає слово, іншими словами, позиції між словом і пробілом. Наприклад, «er\b» відповідає «er» у слові «lever», але не «er» у слові «verbe».
\B 
Відповідає межі, що не представляє слова. «en*t\B» відповідає «ent» у слові «bien entendu».
\d 
Відповідає символу, що позначає цифру. Еквівалентно [0-9].
\D 
Відповідає символу, що не є цифрою. Еквівалентно [^0-9].
\f 
Відповідає символу переходу на новий рядок.
\n 
Відповідає символу нового рядка.
\r 
Відповідає символу повернення каретки.
\s 
Відповідає будь-якому пробілу, включаючи пробіл, табуляцію, перехід на новий аркуш тощо. Еквівалентно «[ \f\n\r\t\v]».
\S 
Відповідає будь-якому символу, що не є пробілом. Еквівалентно «[^ \f\n\r\t\v]».
\t 
Відповідає символу табуляції.
\v 
Відповідає символу вертикального табуляції.
\w 
Відповідає будь-якому символу, що позначає слово та містить підкреслення. Еквівалентно «[A-Za-z0-9_]».
\W 
Відповідає будь-якому символу, що не позначає слово. Еквівалентно «[^A-Za-z0-9_]».

\num 
Відповідає num, де num — це додатне ціле число. Посилається на збережені відповідності. Наприклад, «(.)\1» відповідає двом послідовним однаковим символам.

\n
Відповідає n, де n — це вісімкове значення екранування. Вісімкові значення екранування повинні складатися з 1, 2 або 3 цифр. Наприклад, «\11» і «\011» обидва відповідають символу табуляції. "\0011" еквівалентно "\001" & "1". Восьмиричні екрануючі значення не повинні перевищувати 256. Якщо це сталося, у виразі враховуватимуться лише перші дві цифри. Дозволяє використовувати коди ASCII у регулярних виразах.

\xn
Відповідає n, де n — це шістнадцяткове значення екранування. Шістнадцяткові екрануючі значення обов’язково мають складатися з двох цифр. Наприклад, «\x41» відповідає «A». «\x041» дорівнює «\x04» та «1». Дозволяє використовувати коди ASCII у регулярних виразах.

Елемент у шаблоні може зустрічатися один або кілька разів. Розглянемо кілька прикладів із символом \d, який позначає 1 цифру:

модель
значення
\d
цифра
\d?
0 або 1 цифра
\d*
0 або більше цифр
\d+
1 або більше цифр
\d{2}
2 цифри
\d{3,}
щонайменше 3 цифри
\d{5,7}
від 5 до 7 цифр

Тепер уявімо модель, здатну описати очікуваний формат рядка символів:

пошуковий рядок
модель
une date au format jj/mm/aa
\d{2}/\d{2}/\d{2}
une heure au format hh:mm:ss
\d{2}:\d{2}:\d{2}
un nombre entier non signé
\d+
un suite d'espaces éventuellement vide
\s*
un nombre entier non signé qui peut être précédé ou suivi d'espaces
\s*\d+\s*
un nombre entier qui peut être signé et précédé ou suivi d'espaces
\s*[+|-]?\s*\d+\s*
un nombre réel non signé qui peut être précédé ou suivi d'espaces
\s*\d+(.\d*)?\s*
un nombre réel qui peut être signé et précédé ou suivi d'espaces
\s*[+|]?\s*\d+(.\d*)?\s*
une chaîne contenant le mot juste
\bjuste\b
  

Можна вказати, де саме в рядку шукати шаблон:

шаблон
значення
^modèle
модель починає рядок
modèle$
модель закінчує рядок
^modèle$
шаблон починає та закінчує рядок
modèle
шаблон шукається по всьому рядку, починаючи з його початку.
шуканий рядок
шаблон
une chaîne se terminant par un point d'exclamation
!$
une chaîne se terminant par un point
\.$
une chaîne commençant par la séquence //
^//
une chaîne ne comportant qu'un mot éventuellement suivi ou précédé d'espaces
^\s*\w+\s*$
une chaîne ne comportant deux mot éventuellement suivis ou précédés d'espaces
^\s*\w+\s*\w+\s*$
une chaîne contenant le mot secret
\bsecret\b

Підмножини шаблону можна «витягувати». Таким чином, можна не тільки перевірити, чи рядок відповідає певному шаблону, але й витягнути з цього рядка елементи, що відповідають підмножинам шаблону, які були взяті в дужки. Отже, якщо ми аналізуємо рядок, що містить дату дд/мм/рр, і хочемо додатково виокремити елементи дд, мм, рр з цієї дати, ми використаємо шаблон (\d\d)/(\d\d)/(\d\d).

4.9.1. Перевірка відповідності рядка заданому шаблону

Об’єкт типу Regex створюється таким чином:

Public Sub New(ByVal pattern As String)

Конструктор створює об’єкт «регулярний вираз» на основі шаблону, переданого як параметр (pattern). Після створення шаблону регулярного виразу його можна порівняти з символьними рядками за допомогою методу IsMatch:

Overloads Public Function IsMatch(ByVal input As String) As Boolean

IsMatch повертає значення «true», якщо вхідний рядок відповідає шаблону регулярного виразу. Ось приклад:


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

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

Module regex1

    Sub Main()
        ' шаблон регулярного виразу
        Dim modèle1 As String = "^\s*\d+\s*$"
        Dim regex1 As New Regex(modèle1)
        ' порівняння екземпляра з шаблоном
        Dim exemplaire1 As String = "  123  "
        If regex1.IsMatch(exemplaire1) Then
            affiche(("[" + exemplaire1 + "] correspond au modèle [" + modèle1 + "]"))
        Else
            affiche(("[" + exemplaire1 + "] ne correspond pas au modèle [" + modèle1 + "]"))
        End If
        Dim exemplaire2 As String = "  123a  "
        If regex1.IsMatch(exemplaire2) Then
            affiche(("[" + exemplaire2 + "] correspond au modèle [" + modèle1 + "]"))
        Else
            affiche(("[" + exemplaire2 + "] ne correspond pas au modèle [" + modèle1 + "]"))
        End If
    End Sub

    ' вивести 
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

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

dos>vbc /r:system.dll regex1.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4 pour Microsoft (R) .NET Framework version 1.1.4322.573

dos>regex1
[  123  ] correspond au modèle [^\s*\d+\s*$]
[  123a  ] ne correspond pas au modèle [^\s*\d+\s*$]

4.9.2. Знайти всі елементи рядка, що відповідають шаблону

Метод Matches

Overloads Public Function Matches(ByVal input As String) As MatchCollection

повертає колекцію елементів рядка input, що відповідають шаблону, як показано в наступному прикладі:


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

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

Module regex2
    Sub Main()
        ' кілька входжень шаблону в екземплярі
        Dim modèle2 As String = "\d+"
        Dim regex2 As New Regex(modèle2)        '
        Dim exemplaire3 As String = "  123  456  789 "
        Dim résultats As MatchCollection = regex2.Matches(exemplaire3)
        affiche(("Modèle=[" + modèle2 + "],exemplaire=[" + exemplaire3 + "]"))
        affiche(("Il y a " & résultats.Count & " occurrences du modèle dans l'exemplaire "))
        Dim i As Integer
        For i = 0 To résultats.Count - 1
            affiche((résultats(i).Value & " en position " & résultats(i).Index))
        Next i
    End Sub

    'відображає
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Клас MatchCollection має властивість Count, яка позначає кількість елементів у колекції. Якщо résultats є об’єктом MatchCollection, то résultats(i) є i-м елементом цієї колекції та має тип Match. У нашому прикладі résultats — це сукупність елементів ланцюжка exemplaire3, що відповідають шаблону modèle2, а résultats(i) — один із цих елементів. Клас Match має дві властивості, які нас тут цікавлять:

  • Value: значення об’єкта Match, тобто елемента, що відповідає моделі
  • Index: позиція, на якій елемент було знайдено в обробленому рядку

Результати виконання попередньої програми:

dos>vbc /r:system.dll regex2.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4p our Microsoft (R) .NET Framework version 1.1.4322.573

dos>regex2
Modèle=[\d+],exemplaire=[  123  456  789 ]
Il y a 3 occurrences du modèle dans l'exemplaire
123 en position 2
456 en position 7
789 en position 12

4.9.3. Витягнення частин шаблону

Підмножини шаблону можна «витягувати». Таким чином, можна не тільки перевірити, чи відповідає рядок певному шаблону, але й витягнути з цього рядка елементи, що відповідають підмножинам шаблону, які були взяті в дужки. Отже, якщо ми аналізуємо рядок, що містить дату дд/мм/рр, і хочемо додатково виокремити елементи дд, мм, рр з цієї дати, ми використаємо шаблон (\d\d)/(\d\d)/(\d\d). Розглянемо такий приклад:


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

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

Module regex2
    Sub Main()
        ' вибір елементів у моделі
        Dim modèle3 As String = "(\d\d):(\d\d):(\d\d)"
        Dim regex3 As New Regex(modèle3)
        Dim exemplaire4 As String = "Il est 18:05:49"
        ' перевірка моделі
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' екземпляр відповідає шаблону
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' відображення груп
            Dim i As Integer
            For i = 0 To résultat.Groups.Count - 1
                affiche(("groupes[" & i & "]=[" & résultat.Groups(i).Value & "] en position " & résultat.Groups(i).Index))
            Next i
        Else
            ' екземпляр не відповідає шаблону
            affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
        End If
    End Sub

    'відображає
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

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

dos>vbc /r:system.dll regex3.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4

dos>regex3
L'exemplaire [Il est 18:05:49] correspond au modèle [(\d\d):(\d\d):(\d\d)]
groupes[0]=[18:05:49] en position 7
groupes[1]=[18] en position 7
groupes[2]=[05] en position 10
groupes[3]=[49] en position 13

Нововведення міститься в наступному фрагменті коду:


        ' перевірка відповідності зразку
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' екземпляр відповідає шаблону
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' відображаються групи
            Dim i As Integer
            For i = 0 To résultat.Groups.Count - 1
                affiche(("groupes[" & i & "]=[" & résultat.Groups(i).Value & "] en position " & résultat.Groups(i).Index))
            Next i
        Else

Рядок exemplaire4 порівнюється з шаблоном regex3 за допомогою методу Match. Цей метод повертає об’єкт Match, який вже було представлено. Тут ми використовуємо дві нові властивості цього класу:

  • Success: вказує, чи було знайдено збіг
  • Groups: колекція, де
    • Groups[0] відповідає частині рядка, що відповідає шаблону
    • Groups[i] (i>=1) відповідає групі дужок № i

Якщо результат має тип Match, то résultats.Groups має тип GroupCollection, а résultats.Groups[i] — тип Group. Клас Group має дві властивості, які ми використовуємо тут:

  • Value: значення об’єкта Group, елемент якого відповідає вмісту дужки
  • Index: позиція, на якій елемент було знайдено в обробленому рядку

4.9.4. Програма для навчання

Знайти регулярний вираз, який дозволяє перевірити, чи рядок дійсно відповідає певному шаблону, іноді є справжнім викликом. Наступна програма дозволяє потренуватися. Вона запитує шаблон і рядок, а потім вказує, чи відповідає рядок шаблону чи ні.


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

' простори імен
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic

Module regex4
    Sub Main()
        ' шаблон регулярного виразу
        Dim modèle, chaine As String
        Dim regex As Regex = Nothing
        Dim résultats As MatchCollection
        ' запитуються у користувача шаблони та екземпляри, які потрібно порівняти з цим
        Dim terminé1 As Boolean = False
        Do While Not terminé1
            Dim erreur As Boolean = True
            Do While Not terminé1 And erreur
                ' запитується шаблон
                Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
                modèle = Console.In.ReadLine()
                ' закінчено?
                If modèle.Trim().ToLower() = "fin" Then
                    terminé1 = True
                Else
                    ' створюється регулярний вираз
                    Try
                        regex = New Regex(modèle)
                        erreur = False
                    Catch ex As Exception
                        Console.Error.WriteLine(("Erreur : " + ex.Message))
                    End Try
                End If
            Loop
            ' закінчено?
            If terminé1 Then Exit Sub
            ' запитуємо у користувача екземпляри, які потрібно порівняти з шаблоном
            Dim terminé2 As Boolean = False
            Do While Not terminé2
                Console.Out.Write(("Tapez la chaîne à comparer au modèle [" + modèle + "] ou fin pour arrêter :"))
                chaine = Console.In.ReadLine()
                ' завершено?
                If chaine.Trim().ToLower() = "fin" Then
                    terminé2 = True
                Else
                    ' виконується порівняння
                    résultats = regex.Matches(chaine)
                    ' успішно?
                    If résultats.Count = 0 Then
                        Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
                    Else
                        ' відображаються елементи, що відповідають шаблону
                        Dim i As Integer
                        For i = 0 To résultats.Count - 1
                            Console.Out.WriteLine(("J'ai trouvé la correspondance [" & résultats(i).Value & "] en position " & résultats(i).Index))
                            ' піделементи
                            If résultats(i).Groups.Count <> 1 Then
                                Dim j As Integer
                                For j = 1 To (résultats(i).Groups.Count) - 1
                                    Console.Out.WriteLine((ControlChars.Tab & "sous-élément [" & résultats(i).Groups(j).Value & "] en position " & résultats(i).Groups(j).Index))
                                Next j
                            End If
                        Next i
                    End If
                End If
            Loop
        Loop
    End Sub

    'відображає
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Ось приклад виконання:

Tapez le modèle à tester ou fin pour arrêter :\d+
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :123 456 789
J'ai trouvé la correspondance [123] en position 0
J'ai trouvé la correspondance [456] en position 4
J'ai trouvé la correspondance [789] en position 8
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :(\d\d):(\d\d)
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :14:15 abcd 17:18 xyzt
J'ai trouvé la correspondance [14:15] en position 0
        sous-élément [14] en position 0
        sous-élément [15] en position 3
J'ai trouvé la correspondance [17:18] en position 11
        sous-élément [17] en position 11
        sous-élément [18] en position 14
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :^\s*\d+\s*$
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter :  1456
J'ai trouvé la correspondance [  1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :^\s*(\d+)\s*$
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :1456
J'ai trouvé la correspondance [1456] en position 0
        sous-élément [1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :abcd 1
456
Je n'ai pas trouvé de correspondances
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :fin

4.9.5. Метод Split

Ми вже зустрічали цей метод у класі String:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()

Рядок розглядається як послідовність полів, розділених символами, що містяться в масиві [separator]. Результатом є масив цих полів.

Роздільником полів у рядку тут є один із символів масиву separator. Метод Split класу Regex дозволяє нам визначити роздільник на основі шаблону:

Overloads Public Function Split(ByVal input As String) As String()

Рядок [input] розбивається на поля, які розділяються роздільником, що відповідає шаблону поточного об’єкта Regex. Припустимо, наприклад, що в текстовому файлі ми маємо рядки у вигляді поле1, поле2, .., полеn. Поля розділяються комою, але перед нею або після неї можуть бути пробіли. У такому разі метод Split класу string не підходить. Рішенням є метод RegEx. Якщо ligne — це прочитаний рядок, то поля можна отримати за допомогою

dim champs() as string=new Regex("s*,\s*").Split(ligne)

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


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

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

Module regex5
    Sub Main()
        ' один рядок
        Dim ligne As String = "abc  , def  , ghi"
        ' шаблон
        Dim modèle As New Regex("\s*,\s*")
        ' розбиття рядка на поля
        Dim champs As String() = modèle.Split(ligne)
        ' відображення
        Dim i As Integer
        For i = 0 To champs.Length - 1
            Console.Out.WriteLine(("champs[" & i & "]=[" & champs(i) & "]"))
        Next i
    End Sub
End Module

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

dos>vbc /r:system.dll regex5.vb
Compilateur Microsoft (R) Visual Basic .NET version 7.10.3052.4

dos>regex5
champs[0]=[abc]
champs[1]=[def]
champs[2]=[ghi]

4.10. Класи BinaryReader та BinaryWriter

Класи BinaryReader та BinaryWriter призначені для читання та запису бінарних файлів. Розглянемо таку програму. Ми хочемо написати програму, яка викликатиметься наступним чином:

// синтаксис pg text bin
// читання текстового файлу (текст) та збереження його вмісту у
// бінарний файл
// текстовий файл містить рядки у форматі ім'я : вік
// які будуть збережені у структурі string, int

Текстовий файл має такий вміст:

paul : 10
helene : 15
jacques : 11
sylvain : 12

Програма має такий вигляд:


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

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

' BinaryWriter()

Module bw1
    ' синтаксис pg текст bin
    ' читаємо текстовий файл (text) і зберігаємо його вміст у
    ' бінарний файл
    ' текстовий файл містить рядки у форматі ім'я : вік
    ' які будуть збережені у структурі string, int

    Sub Main(ByVal arguments() As String)
        ' потрібні 2 аргументи
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg texte binaire")
            Environment.Exit(1)
        End If
        ' відкриття текстового файлу для читання
        Dim input As StreamReader = Nothing
        Try
            input = New StreamReader(arguments(0))
        Catch ex As Exception
            Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(0) & "(" & ex.Message & ")")
            Environment.Exit(2)
        End Try
        ' відкриття бінарного файлу для запису
        Dim output As BinaryWriter = Nothing
        Try
            output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))
        Catch ex As Exception
            Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(1) & "(" & ex.Message & ")")
            Environment.Exit(3)
        End Try
        ' читання текстового файлу — запис бінарного файлу
        ' рядок текстового файлу
        Dim ligne As String
        ' роздільник полів у рядку
        Dim séparateur As New Regex("\s*:\s*")
        ' шаблон віку
        Dim modAge As New Regex("\s*\d+\s*")
        Dim numLigne As Integer = 0
        Dim traitementFini As Boolean
        Dim champs As String()
        ligne = input.ReadLine()
        While Not (ligne Is Nothing)
            traitementFini = False
            ' порожній рядок?
            If ligne.Trim() = "" Then
                traitementFini = True
            End If
            ' ще один рядок
            If Not traitementFini Then
                numLigne += 1
                ' рядок «ім'я: вік»
                champs = séparateur.Split(ligne)
                ' нам потрібно 2 поля
                If champs.Length <> 2 Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
                    ' наступний рядок
                    traitementFini = True
                End If
            End If
            If Not traitementFini Then
                ' друге поле має бути цілим числом >=0
                If Not modAge.IsMatch(champs(1)) Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
                    ' наступний рядок
                    traitementFini = True
                End If
                ' записуємо дані у двійковий файл
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))
            End If
            'наступний рядок
            ligne = input.ReadLine()
        End While
        ' закриття файлів
        input.Close()
        output.Close()
    End Sub
End Module

Зупинимося на операціях, що стосуються класу BinaryWriter:

  • об’єкт BinaryWriter відкривається операцією

            output = New BinaryWriter(New FileStream(arguments(1), FileMode.Create, FileAccess.Write))

Аргументом конструктора має бути потік (Stream). У даному випадку це потік, побудований на основі файлу (FileStream), для якого задано:

  • (продовження)
    • ім’я
    • операцію, яку потрібно виконати, тут FileMode.Create для створення файлу
    • тип доступу, у даному випадку FileAccess.Write для доступу до файлу з правом запису
  • операцію запису

                 ' дані записуються у двійковий файл
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))

Клас BinaryWriter має різні перевантажені методи Write для запису різних типів простих даних

  • операція закриття потоку
        output.Close()

Результати попереднього виконання нам надасть наступна програма. Вона також приймає два аргументи:

     ' синтаксис pg bin текст
     ' читання бінарного файлу bin та збереження його вмісту у текстовому файлі (текст)
     ' бінарний файл має структуру string, int
     ' текстовий файл містить рядки у форматі ім'я : вік

Отже, ми виконуємо зворотну операцію. Ми зчитуємо двійковий файл, щоб створити текстовий файл. Якщо отриманий текстовий файл ідентичний вихідному, ми будемо знати, що перетворення «текст → двійковий → текст» пройшло успішно. Код такий:


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

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

Module br1
    ' синтаксис pg bin текст
    ' зчитується бінарний файл bin, а його вміст записується у текстовий файл (текст)
    ' бінарний файл має структуру string, int
    ' текстовий файл містить рядки у форматі ім'я : вік

    Sub Main(ByVal arguments() As String)
        ' потрібні 2 аргументи
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg binaire texte")
            Environment.Exit(1)
        End If
        ' відкриття бінарного файлу для читання
        Dim dataIn As BinaryReader = Nothing
        Try
            dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))
        Catch ex As Exception
            Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(0) & "(" & ex.Message & ")")
            Environment.Exit(2)
        End Try
        ' відкриття текстового файлу для запису
        Dim dataOut As StreamWriter = Nothing
        Try
            dataOut = New StreamWriter(arguments(1))
            dataOut.AutoFlush = True
        Catch ex As Exception
            Console.Error.WriteLine("Erreur d'ouverture du fichier " & arguments(1) & "(" & ex.Message & ")")
            Environment.Exit(3)
        End Try
        ' читання бінарного файлу — запис текстового файлу
        Dim nom As String        ' nom d'une personne
        Dim age As Integer        ' son âge
        ' цикл обробки бінарного файлу
        While True
            ' читання імені
            Try
                nom = dataIn.ReadString()
            Catch
                ' кінець файлу
                Exit Sub
            End Try
            ' читання віку
            Try
                age = dataIn.ReadInt32()
            Catch
                Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
                Exit Sub
            End Try
            ' запис у текстовий файл
            dataOut.WriteLine(nom & ":" & age)
            System.Console.WriteLine(nom & ":" & age)
        End While
        ' закриваємо все
        dataIn.Close()
        dataOut.Close()
    End Sub
End Module

Зупинимося на операціях, що стосуються класу BinaryReader:

  • об’єкт BinaryReader відкривається операцією

            dataIn = New BinaryReader(New FileStream(arguments(0), FileMode.Open, FileAccess.Read))

Аргументом конструктора має бути потік (Stream). У цьому випадку це потік, побудований на основі файлу (FileStream), для якого задано:

  • (продовження)
    • ім’я
    • операцію, яку потрібно виконати, тут — FileMode.Open для відкриття існуючого файлу
    • тип доступу, у даному випадку FileAccess.Read для доступу до файлу в режимі читання
  • операцію читання
                nom = dataIn.ReadString()
                age = dataIn.ReadInt32()

Клас BinaryReader має різні методи ReadXX для читання різних типів простих даних

  • операція закриття потоку
        dataIn.Close()

Якщо виконати дві програми послідовно, перетворюючи personnes.txt на personnes.bin, а потім personnes.bin на personnes.txt2, отримаємо:

dos>more personnes.txt
paul : 10
helene : 15
jacques : 11
sylvain : 12

dos>more personnes.txt2
paul:10
helene:15
jacques:11
sylvain:12

dos>dir
29/04/2002  18:19                   54 personnes.txt
29/04/2002  18:19                   44 personnes.bin
29/04/2002  18:20                   44 personnes.txt2