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
تُرجع القيمة «صحيح» إذا كانت السلسلة تنتهي بالقيمة
Public Function StartsWith(ByVal value As String)
As Boolean
تُرجع القيمة "صحيح" إذا كانت السلسلة تبدأ بالقيمة
Overloads Public Function Equals(ByVal value
As String) As Boolean
تُرجع القيمة "صحيح" إذا كانت السلسلة تساوي 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. هذه عملية معقدة يمكن تبسيطها إذا استخدمنا مصفوفة متغيرة الحجم (ArrayList) بدلاً من مصفوفة ذات حجم ثابت (Array).

يتم فرز المصفوفة باستخدام الطريقة 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
نفس الشيء ولكن مع إرجاع مؤشر آخر ظهور لـ value في القائمة
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
يُزيل العنصر index من القائمة
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
إذا كانت القيمة «صحيح»، فإن الكتابة في الدفق لا تمر عبر ذاكرة مؤقتة؛ وإلا فإن الكتابة في الدفق لا تتم فورًا: حيث تتم الكتابة أولاً في ذاكرة مؤقتة ثم في الدفق عندما تمتلئ الذاكرة المؤقتة. بشكل افتراضي، يتم استخدام الوضع المؤقت. وهو مناسب تمامًا لدفقات الملفات ولكنه غير مناسب عمومًا لدفقات الشبكة.
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 إلى رقم. الرموز التي يمكن استخدامها في النموذج هي التالية (وثائق مايكروسوفت):

 
الوصف
\
يُشير إلى الحرف التالي على أنه حرف خاص أو حرف حرفي. على سبيل المثال، «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 الذي يمثل رقمًا واحدًا:

القالب
المعنى
\d
رقم واحد
\d?
رقم واحد أو صفر
\d*
صفر أو أكثر من رقم
\d+
رقم واحد أو أكثر
\d{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

يمكن "استخراج" المجموعات الفرعية لنموذج ما. وبالتالي، لا يمكننا فقط التحقق من أن سلسلة ما تتطابق مع نموذج معين، بل يمكننا أيضًا استخراج العناصر الموجودة في هذه السلسلة والتي تتطابق مع المجموعات الفرعية للنموذج التي تم وضعها بين أقواس. فإذا قمنا بتحليل سلسلة تحتوي على تاريخ jj/mm/aa وأردنا أيضًا استخراج العناصر jj و mm و aa من هذا التاريخ، فسنستخدم النموذج (\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 القيمة «صحيح» إذا كانت السلسلة المدخلة تتطابق مع نموذج التعبير العادي. وفيما يلي مثال على ذلك:


' خيارات
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. استخراج أجزاء من نموذج

يمكن "استخراج" مجموعات فرعية من نموذج ما. وبذلك، لا يمكننا فقط التحقق من أن سلسلة ما تتطابق مع نموذج معين، بل يمكننا أيضًا استخراج العناصر الموجودة في هذه السلسلة والتي تتطابق مع المجموعات الفرعية للنموذج التي تم وضعها بين أقواس. فإذا قمنا بتحليل سلسلة تحتوي على تاريخ jj/mm/aa وأردنا أيضًا استخراج العناصر jj و mm و aa من هذا التاريخ، فسنستخدم النموذج (\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 فهي التي توفر الحل. إذا كان «line» هو السطر الذي تمت قراءته، فيمكن الحصول على الحقول من خلال

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 نص ثنائي
// قراءة ملف نصي (نص) وتخزين محتواه في
// ملف ثنائي
// يحتوي الملف النصي على أسطر بالصيغة التالية: الاسم : العمر
// والتي سيتم تخزينها في بنية من نوع 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 نص ثنائي
    ' يتم قراءة ملف نصي (نص) وتخزين محتواه في
    ' ملف ثنائي
    ' يحتوي الملف النصي على أسطر بالصيغة الاسم: العمر
    ' التي سيتم تخزينها في بنية string، int

    Sub Main(ByVal arguments() As String)
        ' يلزم وجود معلمتين
        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)
                ' نحتاج إلى حقلين
                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 text
    ' قراءة ملف ثنائي بن وتخزين محتواه في ملف نصي (نص)
    ' الملف الثنائي له بنية string، int
    ' يحتوي الملف النصي على أسطر بالصيغة اسم : عمر

لذلك نقوم بالعملية العكسية. نقوم بقراءة ملف ثنائي لإنشاء ملف نصي. إذا كان الملف النصي الناتج مطابقًا للملف الأصلي، فسنعرف أن عملية التحويل من نص إلى ثنائي ثم إلى نص قد تمت بنجاح. والرمز هو كما يلي:


' خيارات
Option Strict On
Option Explicit On 

' مساحات الأسماء
Imports System
Imports System.Text.RegularExpressions
Imports System.IO

Module br1
    ' صيغة pg bin text
    ' يتم قراءة ملف ثنائي بن وتخزين محتواه في ملف نصي (نص)
    ' الملف الثنائي له بنية string، int
    ' يحتوي الملف النصي على أسطر بالصيغة اسم : عمر

    Sub Main(ByVal arguments() As String)
        ' يلزم وجود معلمتين
        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