Skip to content

4. Classi .NET di uso comune

Qui presentiamo alcune classi della piattaforma .NET che sono di interesse anche per un principiante. Innanzitutto, mostriamo come ottenere informazioni sulle centinaia di classi disponibili.

4.1. Cercare assistenza con SDK.NET

4.1.1. wincv

Se avete installato solo l'SDK e non Visual Studio.NET, potete utilizzare il programma wincv.exe, che di solito si trova nella directory dell'SDK, ad esempio C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1. Quando avviate questa utility, viene visualizzata la seguente interfaccia:

Digitare il nome della classe desiderata in (1). Verranno visualizzate varie opzioni possibili in (2). Selezionare quella appropriata e il risultato apparirà in (3)—in questo caso, la classe HashTable. Questo metodo è adatto se si conosce il nome della classe che si sta cercando. Se si desidera esplorare l'elenco delle opzioni offerte dalla piattaforma .NET, è possibile utilizzare il file HTML StartHere.htm, che si trova anch'esso direttamente nella cartella di installazione di SSK.Net, ad esempio C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

Image

Il link alla documentazione dell'SDK di .NET Framework è quello da seguire per ottenere una panoramica delle classi .NET:

Image

Da lì, clicca sul link [Class Library]. Contiene un elenco di tutte le classi .NET:

Image

Ad esempio, seguiamo il link System.Collections. Questo spazio dei nomi contiene varie classi che implementano le collezioni, inclusa la classe HashTable:

Image

Seguiamo il link HashTable qui sotto:

Image

Arriviamo alla pagina seguente:

Image

Notate la posizione del cursore qui sotto. Sta indicando un link che consente di specificare il linguaggio desiderato, in questo caso Visual Basic.

Qui troverete il prototipo della classe e alcuni esempi di utilizzo. Cliccate sul link [Hashtable, Members] qui sotto:

Image

Otteniamo la descrizione completa della classe:

Image

Questo metodo è il modo migliore per esplorare l'SDK e le sue classi. Lo strumento WinCV è utile quando si conosce già un po' la classe ma si sono dimenticati alcuni dei suoi membri. WinCV consente quindi di trovare rapidamente la classe e i suoi membri.

4.2. Ricerca di aiuto sulle classi con VS.NET

Ecco alcuni suggerimenti per trovare aiuto con Visual Studio.NET

4.2.1. Opzione Aiuto

Selezionare l'opzione [?] dal menu.

Image

Viene visualizzata la seguente finestra:

Image

Nell'elenco a discesa è possibile selezionare un filtro della guida. In questo caso, sceglieremo il filtro [Visual Basic].

Image

Sono utili due tipi di guida:

  • aiuto sul linguaggio VB.NET stesso (sintassi)
  • aiuto sulle classi .NET che possono essere utilizzate dal linguaggio VB.NET

È possibile accedere alla guida del linguaggio VB.NET tramite [Visual Studio.NET/Visual Basic e Visual C#/Riferimenti/Visual Basic]:

Image

Viene visualizzata la seguente pagina della guida:

Image

Da lì, le varie sottosezioni forniscono assistenza su diversi argomenti relativi a VB.NET. Presta particolare attenzione ai tutorial su VB.NET:

Image

Per accedere alle varie classi della piattaforma .NET, seleziona la guida [Visual Studio.NET/.NET Framework].

Image

Ci concentreremo in particolare sulla sezione [Riferimenti/Libreria di classi]:

Image

Supponiamo di essere interessati alla classe [ArrayList]. Si trova nello spazio dei nomi [System.Collections]. È importante saperlo; altrimenti, preferiremmo il metodo di ricerca descritto di seguito. Otteniamo la seguente guida:

Image

Il link [ArrayList, Classe] offre una panoramica della classe:

Image

Questo tipo di pagina è disponibile per tutte le classi. Fornisce una sintesi della classe con esempi. Per una descrizione dei membri della classe, segui il link [ArrayList, membri]:

Image

4.2.2. Aiuto/Indice

Image

L'opzione [Aiuto/Indice] consente di cercare un aiuto più mirato rispetto al metodo precedente. È sufficiente digitare la parola chiave che si sta cercando:

Image

Il vantaggio di questo metodo rispetto al precedente è che non è necessario sapere dove trovare ciò che si sta cercando nel sistema di aiuto. Questo è probabilmente il metodo preferito per le ricerche mirate, mentre l'altro metodo è più adatto per esplorare tutto ciò che il sistema di aiuto ha da offrire.

4.3. La classe String

La classe String ha molte proprietà e metodi. Eccone alcuni:

Proprietà pubblica di sola lettura Length come Integer
numero di caratteri nella stringa
Proprietà pubblica di sola lettura predefinita
Chars(ByVal index As Integer) As Char
proprietà indicizzata predefinita. [String].Chars(i) è l'i-esimo carattere della stringa
Funzione pubblica EndsWith(ByVal value As String)
As Boolean
Restituisce true se la stringa termina con value
Funzione pubblica StartsWith(ByVal valore As String)
As Boolean
Restituisce true se la stringa inizia con valore
Sovraccarichi Funzione pubblica Equals(ByVal valore
As String) As Boolean
restituisce true se la stringa è uguale a value
Sovraccarichi Funzione pubblica IndexOf(ByVal valore
As String) As Integer
restituisce la prima posizione nella stringa in cui si trova il valore della stringa: la ricerca inizia dal carattere 0
Sovraccarichi Funzione Pubblica IndexOf(ByVal valore
As String, ByVal startIndex As Integer) As Integer
Restituisce la posizione della prima occorrenza del valore stringa nella stringa: la ricerca inizia all'indice del carattere startIndex
Sovraccarichi Funzione Pubblica Condivisa
Join(ByVal separator As String, ByVal value()
As String) As String
metodo di classe - restituisce una stringa risultante dalla concatenazione dei valori nell'array value con il separatore separator
Sovraccarichi Funzione pubblica Replace(ByVal vecchioCarattere
As Char, ByVal newChar As Char) As String
restituisce una copia della stringa corrente in cui il carattere oldChar è stato sostituito dal carattere newChar
Sovraccarichi Funzione Pubblica Split(ByVal ParamArray
separator() As Char) As String()
La stringa viene trattata come una sequenza di campi separati dai caratteri presenti nell'array separator. Il risultato è un array di questi campi
Sovraccarichi la funzione pubblica Substring(
ByVal startIndex As Integer, ByVal length As Integer)
As String
Una sottostringa della stringa corrente che inizia nella posizione startIndex e contiene length caratteri
Sovraccarichi Funzione Pubblica ToLower()
As String
converte la stringa corrente in minuscolo
Sovraccarichi Funzione pubblica ToUpper()
Come String
converte la stringa corrente in maiuscolo
Sovraccarichi la funzione pubblica Trim()
Come String
rimuove gli spazi iniziali e finali dalla stringa corrente

Una stringa C può essere considerata un array di caratteri. Pertanto

  • C.Chars(i) è l'i-esimo carattere di C
  • C.Length è il numero di caratteri in C

Si consideri il seguente esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
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
 
    ' poster
    Sub affiche(ByVal msg As [String])
        ' poster msg
        Console.Out.WriteLine(msg)
    End Sub
End Module

L'esecuzione produce i seguenti risultati:

dos>vbc string1.vb

dos>string1
uneChaine=l'bird flies above the clouds
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 ABOVE DES NUAGES
uneChaine.ToLower()=l'bird flies above the clouds
uneChaine.Replace('a','A')=l'oiseAu flies Over the nuAges
champs[0]=[l'bird]
champs[1]=[vole]
champs[2]=[au-dessus]
champs[3]=[des]
champs[4]=[nuages]
Join(":",champs)=l'bird:flies:above:clouds
("  abc  ").Trim()=[abc]

Consideriamo un nuovo esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
 
Module string2
    Sub Main()
        ' the line to be analyzed
        Dim ligne As String = "un:deux::trois:"
        ' field separators
        Dim séparateurs() As Char = {":"c}
        ' split
        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
        ' join
        Console.Out.WriteLine(("join=[" + System.String.Join(":", champs) + "]"))
    End Sub
End Module

e i risultati dell'esecuzione:

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

Il metodo Split della classe String consente di inserire i campi di una stringa in un array. La definizione del metodo qui utilizzato è la seguente:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()
separator
array di caratteri. Questi caratteri rappresentano i caratteri utilizzati per separare i campi nella stringa. Pertanto, se la stringa è [campo1, campo2, campo3], possiamo utilizzare separator=new char() {","c}. Se il separatore è una sequenza di spazi, utilizziamo separator=nothing.
risultato
array di stringhe in cui ogni elemento è un campo della stringa.

Il metodo Join è un metodo statico della classe String:

Overloads Public Shared Function Join(ByVal separator As String, ByVal value() As String) As String
valore
array di stringhe
separatore
una stringa che fungerà da separatore di campi
risultato
una stringa formata dalla concatenazione degli elementi dell'array dei valori, separati dalla stringa separatrice.

4.4. La classe Array

La classe Array implementa un array. Nel nostro esempio, useremo le seguenti proprietà e metodi:

Proprietà pubblica di sola lettura Length tipo Integer
proprietà - numero di elementi nell'array
Sovraccarichi Funzione pubblica condivisa BinarySearch
(ByVal array As Array, ByVal index As Integer,
ByVal lunghezza As Integer, ByVal valore As Object) As Integer
Metodo di classe - restituisce la posizione di value nell'array ordinato - esegue la ricerca a partire dalla posizione index e su length elementi
Sovraccarichi Public Shared Sub Copy(ByVal sourceArray
As Array, ByVal destinationArray As Array,
ByVal lunghezza As Integer)
Metodo di classe - copia i primi length elementi di sourceArray in destinationArray - destinationArray viene creato appositamente per questo scopo
Sovraccarichi Public Shared Sub Sort(ByVal array As Array)
Metodo di classe - ordina l'array - l'array deve contenere un tipo di dati con una funzione di ordinamento predefinita (stringhe, numeri).

Il programma seguente illustra l'uso della classe Array:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
 
Module test
    Sub Main()
        ' read table elements typed on keyboard
        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é
            ' question
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' reading the answer
            réponse = Console.ReadLine().Trim()
            ' end of input if string empty
            If réponse.Equals("") Then
                Exit While
            End If
            ' input verification
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' if no error
            If Not erreur Then
                ' new table to accommodate the new element
                éléments2 = New Double(i) {}
                ' copy old panel to new panel
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' new table becomes old table
                éléments1 = éléments2
                ' no need for the new panel
                éléments2 = Nothing
                ' insert new element
                éléments1(i) = élément
                ' one more element in the picture
                i += 1
            End If
        End While
        ' unsorted table display
        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
        ' table sorting
        System.Array.Sort(éléments1)
        ' sorted table display
        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
        ' Search
        While Not terminé
            ' question
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' reading-checking response
            réponse = Console.ReadLine().Trim()
            ' finished?
            If réponse.Equals("") Then
                Exit While
            End If
            ' check
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' if no error
            If Not erreur Then
                ' search for the element in the sorted array
                i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
                ' Display response
                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

Il risultato sullo schermo è il seguente:

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) :

La prima parte del programma costruisce un array a partire dai dati numerici inseriti tramite la tastiera. L'array non può essere predefinito poiché non sappiamo quanti elementi inserirà l'utente. Lavoriamo quindi con due array, elements1 ed elements2.


                ' nouveau tableau pour accueillir le nouvel élément
                éléments2 = New Double(i) {}
                ' copie ancien tableau vers nouveau tableau
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' nouveau tableau devient ancien tableau
                éléments1 = éléments2
                ' plus besoin du nouveau tableau
                éléments2 = Nothing
                ' insertion nouvel élément
                éléments1(i) = élément
                ' un élémt de plus dans le tableau
                i += 1

L'array elements1 contiene i valori attualmente inseriti. Quando l'utente aggiunge un nuovo valore, creiamo un array elements2 con un elemento in più rispetto a elements1, copiamo il contenuto di elements1 in elements2 (Array.Copy), impostiamo elements1 in modo che punti a elements2 e infine aggiungiamo il nuovo elemento a elements1. Si tratta di un processo complesso che può essere semplificato utilizzando un array a dimensione variabile (ArrayList) invece di un array a dimensione fissa (Array).

L'array viene ordinato utilizzando il metodo Array.Sort. Questo metodo può essere chiamato con vari parametri che specificano le regole di ordinamento. Se non vengono specificati parametri, per impostazione predefinita viene eseguito l'ordinamento in ordine crescente. Infine, il metodo Array.BinarySearch consente di cercare un elemento in un array ordinato.

4.5. La classe ArrayList

La classe ArrayList consente di implementare array di dimensione variabile durante l'esecuzione del programma, cosa che la precedente classe Array non permette. Ecco alcune delle proprietà e dei metodi più comuni:

Public Sub New()
crea una lista vuota
Proprietà pubblica sovrascrivibile di sola lettura Count
As Integer  Implements ICollection.Count
numero di elementi nella raccolta
Funzione pubblica sovrascrivibile Add(ByVal valore
As Object) As Integer Implements IList.Add
Aggiunge l'oggetto valore alla fine della raccolta
Sub pubblica sovrascrivibile Clear()
Implementa IList.Clear
cancella l'elenco
Sovraccarichi Funzione pubblica sovrascrivibile
IndexOf(ByVal valore As Object) As Integer
Implementa IList.IndexOf
indice dell'oggetto valore nell'elenco oppure -1 se non esiste
Sovraccarichi Funzione pubblica sovrascrivibile
IndexOf(ByVal value As Object, ByVal startIndex
As Integer) As Integer
Come sopra, ma a partire dall'elemento startIndex
Sovraccarichi Funzione pubblica sovrascrivibile
LastIndexOf(ByVal value As Object) As Integer
Come sopra, ma restituisce l'indice dell'ultima occorrenza di value nell'elenco
Sovraccarichi Funzione pubblica sovrascrivibile
LastIndexOf(ByVal valore As Object, ByVal indiceIniziale As Integer) As Integer
Come sopra, ma a partire dall'elemento all'indice startIndex
Public Overridable Sub Remove(ByVal obj As Object)
Implementa IList.Remove
Rimuove l'oggetto obj se presente nell'elenco
Sub pubblica sovrascrivibile RemoveAt(ByVal index As Integer)
Implementa IList.RemoveAt
rimuove l'elemento all'indice dall'elenco
Sovraccarichi Funzione pubblica sovrascrivibile
BinarySearch(ByVal valore As Object) As Integer
Restituisce la posizione dell'oggetto valore nell'elenco oppure -1 se non viene trovato. L'elenco deve essere ordinato
Sovraccarichi Public Overridable Sub Sort()
Ordina l'elenco. L'elenco deve contenere oggetti con una relazione di ordinamento predefinita (stringhe, numeri)
Sovraccarichi Public Overridable Sub
Sort(ByVal comparer As IComparer)
ordina l'elenco in base all'ordinamento stabilito dalla funzione comparatore

Riprendiamo l'esempio che utilizza gli oggetti Array e applichiamolo agli oggetti ArrayList:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
 
Module test
    Sub Main()
        ' read table elements typed on keyboard
        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é
            ' question
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' reading the answer
            réponse = Console.ReadLine().Trim()
            ' end of input if string empty
            If réponse.Equals("") Then
                Exit While
            End If
            ' input verification
            Try
                élément = Double.Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' if no error
            If Not erreur Then
                ' one more element in the picture
                éléments.Add(élément)
            End If
        End While
        ' unsorted table display
        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        ' table sorting
        éléments.Sort()
        ' sorted table display
        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
        ' Search
        While Not terminé
            ' question
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' reading-checking response
            réponse = Console.ReadLine().Trim()
            ' finished?
            If réponse.Equals("") Then
                Exit While
            End If
            ' check
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' if no error
            If Not erreur Then
                ' search for the element in the sorted array
                i = éléments.BinarySearch(élément)
                ' Display response
                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

I risultati dell'esecuzione sono i seguenti:

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. La classe Hashtable

La classe Hashtable consente di implementare un dizionario. Un dizionario può essere visto come un array a due colonne:

Le chiavi sono univoche; ciò significa che non possono esserci due chiavi identiche. I principali metodi e proprietà della classe Hashtable sono i seguenti:

Public Sub New()
crea un dizionario vuoto
Public Overridable Sub Add(ByVal key As
Object, ByVal value As Object)
Implementa IDictionary.Add
aggiunge una voce (chiave, valore) al dizionario, dove chiave e valore sono riferimenti a oggetti.
Public Overridable Sub Remove
(ByVal chiave As Object) Implements IDictionary.Remove
rimuove la voce con chiave=chiave dal dizionario
Sub pubblica sovrascrivibile Clear()
Implementa IDictionary.Clear
cancella il dizionario
Funzione pubblica sovrascrivibile ContainsKey
(ByVal chiave As Object) As Boolean
Restituisce true se la chiave key è presente nel dizionario.
Funzione pubblica sovrascrivibile
ContainsValue(ByVal value As Object) As Boolean
Restituisce true se il valore value è presente nel dizionario.
Proprietà pubblica sovrascrivibile di sola lettura
Count As Integer  Implementa ICollection.Count
proprietà: numero di elementi nel dizionario (chiave, valore)
Proprietà pubblica sovrascrivibile di sola lettura
Keys come ICollection implementa IDictionary.Keys
proprietà: raccolta delle chiavi del dizionario
Proprietà pubblica sovrascrivibile di sola lettura
Valori come ICollection implementa IDictionary.Values
proprietà: raccolta di valori del dizionario
Proprietà pubblica sovrascrivibile predefinita
Item(ByVal key As Object) As Object  Implementa IDictionary.Item
proprietà indicizzata: consente di recuperare o impostare il valore associato a una chiave

Si consideri il seguente programma di esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
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}
        ' filling the dictionary
        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
        ' number of elements in the dictionary
        Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
        ' kEY LIST
        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
        ' list of values
        Console.Out.WriteLine("[Liste des valeurs]")
        Dim valeurs As IEnumerator = dico.Values.GetEnumerator()
        While valeurs.MoveNext()
            Console.Out.WriteLine(valeurs.Current)
        End While
        ' list of keys & values
        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
        ' delete the "paul" key
        Console.Out.WriteLine("[Suppression d'une clé]")
        dico.Remove("paul")
        ' list of keys & values
        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
 
        ' dictionary search
        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
            ' next search
            Console.Out.Write("Nom recherché (rien pour arrêter) : ")
            nomCherché = Console.ReadLine().Trim()
        End While
    End Sub
End Module

I risultati dell'esecuzione sono i seguenti:

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) :

Il programma utilizza inoltre un oggetto IEnumerator per iterare attraverso le collezioni di chiavi e valori nel dizionario di tipo ICollection (vedere le proprietà Keys e Values sopra). Una collezione è un insieme di oggetti su cui è possibile iterare. L'interfaccia ICollection è definita come segue:

Image

La proprietà Count ci permette di determinare il numero di elementi presenti nella collezione. L'interfaccia ICollection deriva dall'interfaccia IEnumerable:

Image

Questa interfaccia ha un solo metodo, GetEnumerator, che ci permette di ottenere un oggetto di tipo IEnumerator:

Image

Il metodo GetEnumerator() di un ICollection ci permette di iterare attraverso la collezione utilizzando i seguenti metodi:

Avanti
passa all'elemento successivo nella raccolta. Restituisce true se l'elemento esiste, altrimenti false. Il primo MoveNext passa al primo elemento. L'elemento "corrente" della raccolta è quindi disponibile nella proprietà Current dell'enumeratore
Current
: elemento corrente della raccolta
Reset
riporta l'iteratore all'inizio della collezione, ovvero prima del primo elemento.

La struttura per iterare sugli elementi di una collezione C (ICollection) è quindi la seguente:

' define collection
dim C as ICollection C=...
' get an enumerator of this collection
dim itérateur as IEnumerator=C.GetEnumerator();
' browse the collection with this enumerator
while(itérateur.MoveNext())
    ' we have a current element
    ' operate itérateur.Current
end while

4.7. La classe StreamReader

La classe StreamReader consente di leggere il contenuto di un file. Ecco alcune delle sue proprietà e dei suoi metodi:

Public Sub New(ByVal path As String)
apre un flusso dal percorso del file. Se il file non esiste, viene generata un'eccezione
Sovrascrive Public Sub Close()
chiude lo stream
Sovrascrive la funzione pubblica ReadLine() As String
Legge una riga dallo stream aperto
Sovrascrive la funzione pubblica ReadToEnd() As String
Legge il resto del flusso a partire dalla posizione corrente

Ecco un esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.IO
 
Module test
    Sub Main()
        Dim ligne As String = Nothing
        Dim fluxInfos As StreamReader = Nothing
        ' read file content
        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

e i risultati della sua esecuzione:

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. La classe StreamWriter

La classe StreamWriter consente di scrivere su un file. Ecco alcune delle sue proprietà e dei suoi metodi:

Public Sub New(ByVal path As String)
apre un flusso di scrittura dal percorso del file. Se non è possibile creare il flusso, viene generata un'eccezione
Proprietà pubblica sovrascrivibile AutoFlush
As Boolean
Se impostato su true, la scrittura nel flusso bypassa il buffer; altrimenti, la scrittura nel flusso non è immediata: i dati vengono prima scritti in un buffer e poi nel flusso quando il buffer è pieno. Per impostazione predefinita, viene utilizzata la modalità con buffer. È adatta per i flussi di file ma generalmente non per i flussi di rete.
Proprietà pubblica sovrascrivibile NewLine
Come stringa
Per impostare o recuperare il carattere di fine riga utilizzato dal metodo WriteLine
Sovrascrive Public Sub Close()
Chiude il flusso
Sovraccarica Public Overridable Sub
WriteLine(ByVal valore As String)
scrive una riga nel flusso di scrittura
Sovrascrive Public Sub Flush()
svuota il buffer nello stream

Si consideri il seguente esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.IO
 
Module test
    Sub Main()
        Dim ligne As String = Nothing        ' one line of text
        Dim fluxInfos As StreamWriter = Nothing        ' the text file
        Try
            ' text file creation
            fluxInfos = New StreamWriter("infos.txt")
            ' read line typed on keyboard
            Console.Out.Write("ligne (rien pour arrêter) : ")
            ligne = Console.In.ReadLine().Trim()
            ' loop as long as the line entered is not empty
            While ligne <> ""
                ' write line to text file
                fluxInfos.WriteLine(ligne)
                ' read new line on keyboard
                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
            ' close file
            Try
                fluxInfos.Close()
            Catch
            End Try
        End Try
    End Sub
End Module

e i risultati dell'esecuzione:

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. La classe Regex

La classe Regex consente l'uso di espressioni regolari. Queste vengono utilizzate per convalidare il formato di una stringa. Ad esempio, è possibile verificare che una stringa che rappresenta una data sia nel formato gg/mm/aa. Per farlo, si utilizza un modello e si confronta la stringa con tale modello. In questo esempio, g, m e a devono essere cifre. Il modello per un formato di data valido è quindi "\d\d/\d\d/\d\d", dove il simbolo \d rappresenta una cifra. I simboli che possono essere utilizzati in un modello sono i seguenti (documentazione Microsoft):

 
Descrizione
\
Indica il carattere seguente come carattere speciale o letterale. Ad esempio, "n" corrisponde al carattere "n". "\n" corrisponde a un carattere di nuova riga. La sequenza "\\" corrisponde a "\", mentre "\(" corrisponde a "(".
^
Corrisponde all'inizio dell'input.
$
Corrisponde alla fine dell'input.
*
Corrisponde al carattere precedente zero o più volte. Pertanto, "zo*" corrisponde a "z" o "zoo".
+
Corrisponde al carattere precedente una o più volte. Pertanto, "zo+" corrisponde a "zoo", ma non a "z".
?
Corrisponde al carattere precedente zero o una volta. Ad esempio, "a?ve?" corrisponde a "ve" in "lever".
.
Corrisponde a qualsiasi singolo carattere, eccetto il carattere di nuova riga.

(pattern)
Cerca il pattern e memorizza la corrispondenza. La sottostringa corrispondente può essere recuperata dalla collezione Matches risultante utilizzando Item [0]...[n]. Per trovare i caratteri racchiusi tra parentesi ( ), usa "\(" o "\)".
x|y
Corrisponde a x o y. Ad esempio, "z|foot" corrisponde a "z" o "foot". "(z|f)oo" corrisponde a "zoo" o "foo".

{n}
n è un numero intero non negativo. Trova esattamente n occorrenze del carattere. Ad esempio, "o{2}" non trova "o" in "Bob", ma trova le prime due "o" in "fooooot".

{n,}
n è un numero intero non negativo. Trova almeno n occorrenze del carattere. Ad esempio, "o{2,}" non trova "o" in "Bob", ma trova tutte le "o" in "fooooot". "o{1,}" equivale a "o+" e "o{0,}" equivale a "o*".

{n,m}
m e n sono numeri interi non negativi. Trova da un minimo di n a un massimo di m occorrenze del carattere. Ad esempio, "o{1,3}" trova le prime tre "o" in "foooooot" e "o{0,1}" equivale a "o?".

[xyz]
Insieme di caratteri. Trova uno qualsiasi dei caratteri specificati. Ad esempio, "[abc]" trova la "a" in "plat".

[^xyz]
Set di caratteri negativo. Corrisponde a qualsiasi carattere non elencato. Ad esempio, "[^abc]" corrisponde alla "p" in "plat".

[a-z]
Intervallo di caratteri. Trova qualsiasi carattere nell'intervallo specificato. Ad esempio, "[a-z]" trova qualsiasi carattere alfabetico minuscolo compreso tra "a" e "z".

[^m-z]
Intervallo di caratteri negativo. Trova qualsiasi carattere non compreso nell'intervallo specificato. Ad esempio, "[^m-z]" trova qualsiasi carattere non compreso tra "m" e "z".
\b
Corrisponde a un confine di parola, ovvero alla posizione tra una parola e uno spazio. Ad esempio, "er\b" corrisponde a "er" in "lever", ma non a "er" in "verb".
\B
Corrisponde a un confine che non rappresenta una parola. "en*t\B" corrisponde a "ent" in "bien entendu".
\d
Corrisponde a un carattere che rappresenta una cifra. Equivalente a [0-9].
\D
Corrisponde a un carattere che non è una cifra. Equivalente a [^0-9].
\f
Corrisponde a un carattere di interruzione di riga.
\n
Corrisponde a un carattere di nuova riga.
\r
Equivalente al carattere di ritorno a capo.
\s
Corrisponde a qualsiasi carattere di spaziatura, inclusi spazio, tabulazione, interruzione di pagina, ecc. Equivalente a "[ \f\n\r\t\v]".
\S
Corrisponde a qualsiasi carattere non spazio. Equivalente a "[^ \f\n\r\t\v]".
\t
Corrisponde a un carattere di tabulazione.
\v
Corrisponde a un carattere di tabulazione verticale.
\w
Corrisponde a qualsiasi carattere che rappresenta una parola, compreso il trattino basso. Equivalente a "[A-Za-z0-9_]".
\W
Corrisponde a qualsiasi carattere che non rappresenti una parola. Equivalente a "[^A-Za-z0-9_]".

\num
Corrisponde a num, dove num è un numero intero positivo. Fa riferimento alle corrispondenze memorizzate. Ad esempio, "(.)\1" corrisponde a due caratteri identici consecutivi.

\n
Corrisponde a n, dove n è un valore di escape ottale. I valori di escape ottali devono essere composti da 1, 2 o 3 cifre. Ad esempio, "\11" e "\011" corrispondono entrambi a un carattere di tabulazione. "\0011" è equivalente a "\001" e "1". I valori di escape ottali non devono superare 256. In caso contrario, nell'espressione vengono prese in considerazione solo le prime due cifre. Consente l'uso dei codici ASCII nelle espressioni regolari.

\xn
Corrisponde a n, dove n è un valore di escape esadecimale. I valori di escape esadecimali devono essere composti da due cifre. Ad esempio, "\x41" corrisponde a "A". "\x041" è equivalente a "\x04" e "1". Consente l'uso dei codici ASCII nelle espressioni regolari.

Un elemento in un pattern può apparire una o più volte. Vediamo alcuni esempi che coinvolgono il simbolo \d, che rappresenta una singola cifra:

modello
significato
\d
una cifra
\d?
0 o 1 cifra
\d*
0 o più cifre
\d+
1 o più cifre
\d{2}
2 cifre
\d{3,}
almeno 3 cifre
\d{5,7}
da 5 a 7 cifre

Ora immaginiamo un modello in grado di descrivere il formato previsto per una stringa:

stringa di destinazione
modello
una data nel formato gg/mm/aa
\d{2}/\d{2}/\d{2}
un'ora nel formato hh:mm:ss
\d{2}:\d{2}:\d{2}
un numero intero senza segno
\d+
una sequenza di spazi, che può essere vuota
\s*
un numero intero senza segno che può essere preceduto o seguito da spazi
\s*\d+\s*
un numero intero che può essere con segno e preceduto o seguito da spazi
\s*[+|-]?\s*\d+\s*
un numero reale senza segno che può essere preceduto o seguito da spazi
\s*\d+(.\d*)?\s*
un numero reale che può essere con segno e preceduto o seguito da spazi
\s*[+|]?\s*\d+(.\d*)?\s*
una stringa contenente la parola "just"
\bjuste\b
  

È possibile specificare dove cercare il pattern nella stringa:

sequenza
significato
^motivo
il pattern inizia la stringa
pattern$
il pattern termina la stringa
^pattern$
il pattern inizia e termina la stringa
pattern
il pattern viene cercato in qualsiasi punto della stringa, a partire dall'inizio.
stringa di ricerca
sequenza
una stringa che termina con un punto esclamativo
!$
una stringa che termina con un punto
\.$
una stringa che inizia con la sequenza //
^//
una stringa composta da una singola parola, facoltativamente seguita o preceduta da spazi
^\s*\w+\s*$
una stringa composta da due parole, facoltativamente preceduta o seguita da spazi
^\s*\w+\s*\w+\s*$
una stringa contenente la parola secret
\bsecret\b

I sottopattern di un pattern possono essere "estratti". Pertanto, non solo possiamo verificare che una stringa corrisponda a un particolare pattern, ma possiamo anche estrarre da quella stringa gli elementi corrispondenti ai sottopattern del pattern che sono stati racchiusi tra parentesi. Ad esempio, se stiamo analizzando una stringa contenente una data nel formato dd/mm/yy e vogliamo anche estrarre gli elementi dd, mm e yy da quella data, useremmo il modello (\d\d)/(\d\d)/(\d\d).

4.9.1. Verifica della corrispondenza di una stringa con un dato modello

Un oggetto Regex viene costruito come segue:

Public Sub New(ByVal pattern As String)

Il costruttore crea un oggetto "espressione regolare" a partire da un modello passato come parametro (pattern). Una volta creato il modello di espressione regolare, è possibile confrontarlo con stringhe di caratteri utilizzando il metodo IsMatch:

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

IsMatch restituisce true se la stringa di input corrisponde al modello di espressione regolare. Ecco un esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
 
Module regex1
 
    Sub Main()
        ' a regular expression template
        Dim modèle1 As String = "^\s*\d+\s*$"
        Dim regex1 As New Regex(modèle1)
        ' compare a copy with the model
        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
 
    ' poster 
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

e i risultati dell'esecuzione:

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. Trova tutti gli elementi in una stringa che corrispondono a un modello

Il metodo Matches

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

restituisce una raccolta di elementi della stringa di input che corrispondono al modello, come mostrato nell'esempio seguente:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
 
Module regex2
    Sub Main()
        ' several occurrences of the model in the copy
        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
 
    'poster
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

La classe MatchCollection dispone di una proprietà Count, che rappresenta il numero di elementi presenti nella raccolta. Se results è un oggetto MatchCollection, results(i) è l'i-esimo elemento di questa raccolta ed è di tipo Match. Nel nostro esempio, results è l'insieme degli elementi nella stringa example3 che corrispondono al modello pattern2, e results(i) è uno di questi elementi. La classe Match dispone di due proprietà rilevanti in questo contesto:

  • Value: il valore dell'oggetto Match, ovvero l'elemento che corrisponde al pattern
  • Index: la posizione in cui l'elemento è stato trovato nella stringa cercata

I risultati dell'esecuzione del programma precedente:

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. Estrazione di parti di un modello

È possibile "estrarre" sottoinsiemi di un pattern. Pertanto, non solo possiamo verificare che una stringa corrisponda a un particolare pattern, ma possiamo anche estrarre da quella stringa gli elementi corrispondenti ai sottoinsiemi del pattern che sono stati racchiusi tra parentesi. Quindi, se stiamo analizzando una stringa contenente una data nel formato dd/mm/yy e vogliamo anche estrarre gli elementi dd, mm e yy da quella data, useremo il pattern (\d\d)/(\d\d)/(\d\d). Esaminiamo il seguente esempio:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
 
Module regex2
    Sub Main()
        ' capture elements in the model
        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"
        ' model checking
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' the copy corresponds to the model
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' display groups
            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
            ' the copy does not correspond to the model
            affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
        End If
    End Sub
 
    'poster
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

L'esecuzione di questo programma produce i seguenti risultati:

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

La nuova funzionalità è presente nel seguente frammento di codice:


        ' model checking
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' the copy corresponds to the model
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' display groups
            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

La stringa example4 viene confrontata con il pattern regex3 utilizzando il metodo Match. Questo restituisce un oggetto Match, come descritto in precedenza. Qui utilizziamo due nuove proprietà di questa classe:

  • Success: indica se c'è stata una corrispondenza
  • Groups: una collezione in cui
    • Groups[0] corrisponde alla parte della stringa che corrisponde al pattern
    • Groups[i] (i>=1) corrisponde all'i-esimo gruppo di parentesi

Se il risultato è di tipo Match, results.Groups è di tipo GroupCollection e results.Groups[i] è di tipo Group. La classe Group ha due proprietà che utilizziamo qui:

  • Value: il valore dell'oggetto Group contenente l'elemento corrispondente al contenuto di una parentesi
  • Index: la posizione in cui l'elemento è stato trovato nella stringa analizzata

4.9.4. Un programma di esercitazione

Trovare l'espressione regolare che ci permette di verificare che una stringa corrisponda a un determinato pattern può a volte essere una vera sfida. Il seguente programma ti permette di esercitarti. Richiede un pattern e una stringa e poi indica se la stringa corrisponde o meno al pattern.


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic
 
Module regex4
    Sub Main()
        ' a regular expression template
        Dim modèle, chaine As String
        Dim regex As Regex = Nothing
        Dim résultats As MatchCollection
        ' the user is asked for models and samples to compare with this one
        Dim terminé1 As Boolean = False
        Do While Not terminé1
            Dim erreur As Boolean = True
            Do While Not terminé1 And erreur
                ' the model is requested
                Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
                modèle = Console.In.ReadLine()
                ' finished?
                If modèle.Trim().ToLower() = "fin" Then
                    terminé1 = True
                Else
                    ' we create the regular expression
                    Try
                        regex = New Regex(modèle)
                        erreur = False
                    Catch ex As Exception
                        Console.Error.WriteLine(("Erreur : " + ex.Message))
                    End Try
                End If
            Loop
            ' finished?
            If terminé1 Then Exit Sub
            ' the user is asked for the specimens to be compared with the model
            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()
                ' finished?
                If chaine.Trim().ToLower() = "fin" Then
                    terminé2 = True
                Else
                    ' we make the comparison
                    résultats = regex.Matches(chaine)
                    ' success?
                    If résultats.Count = 0 Then
                        Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
                    Else
                        ' the elements corresponding to the model are displayed
                        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))
                            ' sub-elements
                            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
 
    'poster
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Ecco un esempio di esecuzione:

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. Il metodo Split

Abbiamo già incontrato questo metodo nella classe String:

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

La stringa viene trattata come una sequenza di campi separati dai caratteri presenti nell'array [separator]. Il risultato è un array di questi campi.

Il separatore di campo nella stringa è uno dei caratteri presenti nell'array separator. Il metodo Split della classe Regex ci permette di specificare il separatore in base a un pattern:

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

La stringa [input] viene suddivisa in campi, separati da un separatore che corrisponde al modello dell'oggetto Regex corrente. Supponiamo, ad esempio, di avere righe in un file di testo della forma campo1, campo2, ..., campoN. I campi sono separati da una virgola, ma questa può essere preceduta o seguita da spazi. Il metodo Split della classe String non è quindi adatto. Il metodo RegEx fornisce la soluzione. Se line è la riga letta, i campi possono essere ottenuti tramite

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

come mostrato nell'esempio seguente:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Text.RegularExpressions
 
Module regex5
    Sub Main()
        ' a line
        Dim ligne As String = "abc  , def  , ghi"
        ' a model
        Dim modèle As New Regex("\s*,\s*")
        ' decomposition of line into fields
        Dim champs As String() = modèle.Split(ligne)
        ' display
        Dim i As Integer
        For i = 0 To champs.Length - 1
            Console.Out.WriteLine(("champs[" & i & "]=[" & champs(i) & "]"))
        Next i
    End Sub
End Module

Risultati dell'esecuzione:

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. Le classi BinaryReader e BinaryWriter

Le classi BinaryReader e BinaryWriter vengono utilizzate per leggere e scrivere file binari. Consideriamo la seguente applicazione. Vogliamo scrivere un programma che venga chiamato come segue:

// syntaxe pg texte bin
// on lit un fichier texte (texte) et on range son contenu dans un
// fichier binaire
// le fichier texte a des lignes de la forme nom : age
// qu'on rangera dans une structure string, int

Il file di testo ha il seguente contenuto:

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

Il programma è il seguente:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
 
' BinaryWriter()
 
Module bw1
    ' syntax pg text bin
    ' read a text file (text) and store its contents in a
    ' binary file
    ' the text file has lines of the form name: age
    ' which will be stored in a string structure, int
 
    Sub Main(ByVal arguments() As String)
        ' you need 2 arguments
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg texte binaire")
            Environment.Exit(1)
        End If
        ' open text file in read mode
        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
        ' open binary file for writing
        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
        ' read text file - write binary file
        ' text file line
        Dim ligne As String
        ' line field separator
        Dim séparateur As New Regex("\s*:\s*")
        ' the age model
        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
            ' empty line?
            If ligne.Trim() = "" Then
                traitementFini = True
            End If
            ' one more line
            If Not traitementFini Then
                numLigne += 1
                ' one line name: age
                champs = séparateur.Split(ligne)
                ' we need 2 fields
                If champs.Length <> 2 Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
                    ' next line
                    traitementFini = True
                End If
            End If
            If Not traitementFini Then
                ' the second field must be an integer >=0
                If Not modAge.IsMatch(champs(1)) Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
                    ' next line
                    traitementFini = True
                End If
                ' write data to the binary file
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))
            End If
            'next line
            ligne = input.ReadLine()
        End While
        ' closing files
        input.Close()
        output.Close()
    End Sub
End Module

Diamo un'occhiata più da vicino alle operazioni relative alla classe BinaryWriter:

  • L'oggetto BinaryWriter viene aperto dall'operazione

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

L'argomento del costruttore deve essere uno stream (Stream). In questo caso, si tratta di uno stream creato da un file (FileStream) per il quale specifichiamo:

  • (continua)
    • il nome
    • l'operazione da eseguire, in questo caso `FileMode.Create` per creare il file
    • il tipo di accesso, in questo caso FileAccess.Write per l'accesso in scrittura al file
  • l'operazione di scrittura

                ' on écrit les données dans le fichier binaire
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))

La classe BinaryWriter dispone di vari metodi Write sovraccaricati per la scrittura di diversi tipi di dati semplici

  • l'operazione di chiusura dello stream
        output.Close()

I risultati dell'esecuzione precedente saranno forniti dal seguente programma. Anche questo programma accetta due argomenti:

    ' syntaxe pg bin texte
    ' on lit un fichier binaire bin et on range son contenu dans un fichier texte (texte)
    ' le fichier binaire a une structure string, int
    ' le fichier texte a des lignes de la forme nom : age

Stiamo quindi eseguendo l'operazione inversa. Leggiamo un file binario per creare un file di testo. Se il file di testo risultante è identico al file originale, sapremo che la conversione testo --> binario --> testo ha avuto esito positivo. Il codice è il seguente:


' options
Option Strict On
Option Explicit On 
 
' namespaces
Imports System
Imports System.Text.RegularExpressions
Imports System.IO
 
Module br1
    ' syntax pg bin text
    ' read a binary bin file and store its contents in a text file (text)
    ' the binary file has a structure string, int
    ' the text file has lines of the form name: age
 
    Sub Main(ByVal arguments() As String)
        ' you need 2 arguments
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg binaire texte")
            Environment.Exit(1)
        End If
        ' open binary file for reading
        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
        ' open text file for writing
        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
        ' read binary file - write text file
        Dim nom As String        ' name of a person
        Dim age As Integer        ' his age
        ' binary file evaluation loop
        While True
            ' read name
            Try
                nom = dataIn.ReadString()
            Catch
                ' end of file
                Exit Sub
            End Try
            ' age reading
            Try
                age = dataIn.ReadInt32()
            Catch
                Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
                Exit Sub
            End Try
            ' writing to text file
            dataOut.WriteLine(nom & ":" & age)
            System.Console.WriteLine(nom & ":" & age)
        End While
        ' we close everything
        dataIn.Close()
        dataOut.Close()
    End Sub
End Module

Diamo un'occhiata più da vicino alle operazioni relative alla classe BinaryReader:

  • L'oggetto BinaryReader viene aperto dall'operazione

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

L'argomento del costruttore deve essere uno stream (Stream). In questo caso, si tratta di uno stream creato da un file (FileStream) per il quale specifichiamo:

  • (continua)
    • il nome
    • l'operazione da eseguire, in questo caso `FileMode.Open` per aprire un file esistente
    • il tipo di accesso, in questo caso FileAccess.Read per l'accesso in lettura al file
  • l'operazione di lettura
                nom = dataIn.ReadString()
                age = dataIn.ReadInt32()

La classe BinaryReader fornisce vari metodi ReadXX per la lettura di diversi tipi di dati semplici

  • l'operazione per chiudere lo stream
        dataIn.Close()

Se eseguiamo i due programmi in sequenza, convertendo personnes.txt in personnes.bin e poi personnes.bin in personnes.txt2, otteniamo:

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