Skip to content

4. Häufig verwendete Klassen der Plattform .NET

Wir stellen hier einige Klassen der Plattform .NET vor, die auch für Anfänger von Interesse sind. Zunächst zeigen wir, wie man Informationen zu den Hunderten von verfügbaren Klassen erhält.

4.1. Hilfe bei SDK.NET suchen

4.1.1. wincv

Wenn nur das SDK und nicht Visual Studio.NET installiert wurde, kann das Programm wincv.exe verwendet werden, das sich normalerweise im SDK-Verzeichnis befindet, zum Beispiel unter C:\Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1. Beim Starten dieses Dienstprogramms wird folgende Benutzeroberfläche angezeigt:

Man gibt unter (1) den Namen der gewünschten Klasse ein. Daraufhin werden unter (2) verschiedene mögliche Themen angezeigt. Man wählt das passende aus und erhält das Ergebnis unter (3), in diesem Fall die Klasse HashTable. Diese Methode eignet sich, wenn man den Namen der gesuchten Klasse kennt. Möchte man die Liste der von der .NET oder die Datei HTML StartHere.htm verwenden, die sich ebenfalls direkt im Installationsordner von SSK.Net befindet, zum Beispiel C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.

Image

Über den Link „.NET Framework SDK Dokumentation“ erhalten Sie einen Überblick über die Klassen „.NET“:

Image

Dort folgen wir dem Link [Bibliothèque de classes]. Dort finden wir die Liste aller Klassen von .NET:

Image

Folgen wir zum Beispiel dem Link System.Collections. Dieser Namensraum umfasst verschiedene Klassen, die Sammlungen implementieren, darunter die Klasse HashTable:

Image

Folgen wir dem untenstehenden Link HashTable:

Image

Wir gelangen auf die folgende Seite:

Image

Beachten Sie unten die Position des Mauszeigers. Er zeigt auf einen Link, über den die gewünschte Sprache ausgewählt werden kann, in diesem Fall Visual Basic.

Dort finden wir den Prototyp der Klasse sowie Anwendungsbeispiele. Folgen wir dem untenstehenden Link [Hashtable, membres]:

Image

Man erhält die vollständige Beschreibung der Klasse:

Image

Diese Methode eignet sich am besten, um sich mit SDK und seinen Klassen vertraut zu machen. Das Tool WinCV erweist sich als nützlich, wenn man die Klasse bereits ein wenig kennt und einige ihrer Mitglieder vergessen hat. Mit WinCV lassen sich die Klasse und ihre Mitglieder dann schnell wiederfinden.

4.2. Hilfe zu Klassen mit VS.NET suchen

Hier geben wir einige Hinweise, wie Sie mit Visual Studio.NET Hilfe finden können

4.2.1. Option „Hilfe“

Wählen wir die Option [?] aus dem Menü.

Image

Es erscheint das folgende Fenster:

Image

In der Dropdown-Liste kann man einen Hilfefilter auswählen. Hier wählen wir den Filter [Visual Basic].

Image

Zwei Hilfestellungen sind nützlich:

  • die Hilfe zur Sprache VB.NET selbst (Syntax)
  • die Hilfe zu den classes.NET, die von der Sprache VB.NET verwendet werden können

Die Hilfe zur Sprache VB.NET ist über [Visual Studio.NET/Visual Basic et Visual C#/Reference/Visual Basic] zugänglich:

Image

Man gelangt zur folgenden Hilfeseite:

Image

Von dort aus bieten die verschiedenen Unterrubriken Hilfe zu verschiedenen Themen von VB.NET. Beachten Sie insbesondere die Tutorials von VB.NET:

Image

Um Zugriff auf die verschiedenen Klassen der Plattform .NET zu erhalten, wählen wir die Hilfe [Visual Studio.NET/.NET Framework].

Image

Von besonderem Interesse ist dabei der Abschnitt [Référence/Bibliothèque de classes]:

Image

Nehmen wir an, wir interessieren uns für die Klasse [ArrayList]. Sie befindet sich im Namensraum [System.Collections]. Das muss man wissen, andernfalls sollte man die im Folgenden beschriebene Suchmethode bevorzugen. Man erhält folgende Hilfe:

Image

Der Link [ArrayList, classe] bietet einen Überblick über die Klasse:

Image

Diese Art von Seite gibt es für alle Klassen. Sie bietet eine Zusammenfassung der Klasse mit Beispielen. Für eine Beschreibung der Klassenelemente folgt man dem Link [ArrayList, membres]:

Image

4.2.2. Hilfe/Index

Image

Mit der Option [Aide/index] lässt sich die Hilfe gezielter suchen als mit der vorherigen Option. Geben Sie einfach das gesuchte Stichwort ein:

Image

Der Vorteil dieser Methode gegenüber der vorherigen besteht darin, dass man nicht wissen muss, wo sich das Gesuchte im Hilfesystem befindet. Diese Methode ist wahrscheinlich die bevorzugte Wahl für eine gezielte Suche, während die andere Methode eher dazu geeignet ist, das gesamte Angebot der Hilfe zu erkunden.

4.3. Die Klasse „String“

Die Klasse „String“ verfügt über zahlreiche Eigenschaften und Methoden. Hier sind einige davon:

Public ReadOnly Property Length As Integer
Anzahl der Zeichen in der Zeichenkette
Public Default ReadOnly Property
Chars(ByVal index As Integer) As Char
Standardmäßig indizierte Eigenschaft. [String].Chars(i) ist das Zeichen Nr. i der Zeichenkette
Public Function EndsWith(ByVal value As String)
As Boolean
gibt „wahr“ zurück, wenn die Zeichenkette mit „value“ endet
Public Function StartsWith(ByVal value As String)
As Boolean
gibt „wahr“ zurück, wenn die Zeichenfolge mit dem Wert beginnt
Overloads Public Function Equals(ByVal value
As String) As Boolean
gibt „wahr“ zurück, wenn die Zeichenfolge mit „value“ übereinstimmt
Overloads Public Function IndexOf(ByVal value
As String) As Integer
gibt die erste Position der Zeichenfolge „value“ in der Zeichenfolge zurück – die Suche beginnt ab Zeichen Nr. 0
Overloads Public Function IndexOf(ByVal value
As String,ByVal startIndex As Integer) As Integer
gibt die erste Position der Zeichenfolge „value“ in der Zeichenfolge zurück – die Suche beginnt ab Zeichen Nr. startIndex
Overloads Public Shared Function
Join(ByVal separator As String,ByVal value()
As String) As String
Klassenmethode – gibt eine Zeichenkette zurück, die das Ergebnis der Verkettung der Werte des Arrays „value“ mit dem Trennzeichen „separator“ ist
Overloads Public Function Replace(ByVal oldChar
As Char,ByVal newChar As Char) As String
Gibt eine Kopie der aktuellen Zeichenkette zurück, in der das Zeichen oldChar durch das Zeichen newChar ersetzt wurde
Overloads Public Function Split(ByVal ParamArray
separator() As Char) As String()
Die Zeichenkette wird als eine Folge von Feldern betrachtet, die durch die in der Tabelle „separator“ enthaltenen Zeichen getrennt sind. Das Ergebnis ist ein Array dieser Felder
Overloads Public Function Substring(
ByVal startIndex As Integer,ByVal length As Integer)
As String
Teilzeichenfolge der aktuellen Zeichenfolge, beginnend an der Position startIndex und mit einer Länge von length Zeichen
Overloads Public Function ToLower()
As String
wandelt die aktuelle Zeichenkette in Kleinbuchstaben um
Overloads Public Function ToUpper()
As String
wandelt die aktuelle Zeichenfolge in Großbuchstaben um
Overloads Public Function Trim()
As String
entfernt die führenden und abschließenden Leerzeichen aus der aktuellen Zeichenkette

Eine Zeichenkette C kann als Zeichenarray betrachtet werden. Somit

  • ist C.Chars(i) das i-te Zeichen von C
  • C.Length ist die Anzahl der Zeichen in C

Betrachten wir das folgende Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
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

    ' Anzeige
    Sub affiche(ByVal msg As [String])
        ' zeigt Meldung an
        Console.Out.WriteLine(msg)
    End Sub
End Module

Die Ausführung liefert folgende Ergebnisse:

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]

Betrachten wir ein neues Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System

Module string2
    Sub Main()
        ' die zu analysierende Zeile
        Dim ligne As String = "un:deux::trois:"
        ' Feldtrennzeichen
        Dim séparateurs() As Char = {":"c}
        ' Aufteilung
        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

und die Ausführungsergebnisse:

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

Mit der Methode „Split“ der Klasse String lassen sich die Felder einer Zeichenkette in ein Array zerlegen. Die Definition der hier verwendeten Methode lautet wie folgt:

Overloads Public Function Split(ByVal ParamArray separator() As Char) As String()
separator
Zeichenarray. Diese Zeichen stellen die Trennzeichen dar, die zur Trennung der Felder der Zeichenkette verwendet werden. Wenn die Zeichenkette also [champ1, champ2, champ3] lautet, kann man separator=new char() {","c} verwenden. Ist das Trennzeichen eine Folge von Leerzeichen, verwendet man separator=nothing.
résultat
Array von Zeichenketten, wobei jedes Element ein Feld der Zeichenkette ist.

Die Methode Join ist eine statische Methode der Klasse *String*:

Overloads Public Shared Function Join(ByVal separator As String,ByVal value() As String) As String
value
Zeichenfolgen-Array
separator
eine Zeichenkette, die als Feldtrennzeichen dient
résultat
eine Zeichenkette, die aus der Verkettung der Elemente des Arrays value besteht, getrennt durch die Zeichenkette separator.

4.4. Die Klasse „Array“

Die Klasse „Array“ implementiert ein Array. In unserem Beispiel verwenden wir die folgenden Eigenschaften und Methoden:

Public ReadOnly Property Length As Integer
Eigenschaft – Anzahl der Elemente des Arrays
Overloads Public Shared Function BinarySearch
(ByVal array As Array,ByVal index As Integer,
ByVal length As Integer,ByVal value As Object) As Integer
Klassenmethode – gibt die Position von value im sortierten Array array zurück – sucht ab der Position index und mit length Elementen
Overloads Public Shared Sub Copy(ByVal sourceArray
As Array,ByVal destinationArray As Array,
ByVal length As Integer)
Klassenmethode – kopiert Elemente von length aus sourceArray in destinationArray – dabei wird destinationArray angelegt
Overloads Public Shared Sub Sort(ByVal array As Array)
Klassenmethode – sortiert das Array array – dieses muss einen Datentyp enthalten, der über eine Standard-Sortierfunktion verfügt (Zeichenketten, Zahlen).

Das folgende Programm veranschaulicht die Verwendung der Klasse Array:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System

Module test
    Sub Main()
        ' Einlesen von per Tastatur eingegebenen Array-Elementen
        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é
            ' Frage
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' Antwort einlesen
            réponse = Console.ReadLine().Trim()
            ' Ende der Eingabe bei leerer Zeichenkette
            If réponse.Equals("") Then
                Exit While
            End If
            ' Überprüfung der Eingabe
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' wenn kein Fehler vorliegt
            If Not erreur Then
                ' neues Array zur Aufnahme des neuen Elements
                éléments2 = New Double(i) {}
                ' Altes Array in neues Array kopieren
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' Das neue Array wird zum alten Array
                éléments1 = éléments2
                ' Das neue Array wird nicht mehr benötigt
                éléments2 = Nothing
                ' Einfügen eines neuen Elements
                éléments1(i) = élément
                ' ein weiteres Element im Array
                i += 1
            End If
        End While
        ' Anzeige des unsortierten Arrays
        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
        ' Sortierung der Tabelle
        System.Array.Sort(éléments1)
        ' Anzeige der sortierten Tabelle
        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
        ' Suche
        While Not terminé
            ' Frage
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' Antwort vorlesen und überprüfen
            réponse = Console.ReadLine().Trim()
            ' Fertig?
            If réponse.Equals("") Then
                Exit While
            End If
            ' Überprüfung
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' Wenn kein Fehler
            If Not erreur Then
                ' Das Element wird im sortierten Array gesucht
                i = System.Array.BinarySearch(éléments1, 0, éléments1.Length, élément)
                ' Anzeige der Antwort
                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

Die Bildschirmausgabe sieht wie folgt aus:

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

Der erste Teil des Programms erstellt ein Array aus numerischen Daten, die über die Tastatur eingegeben werden. Die Größe des Arrays kann nicht im Voraus festgelegt werden, da die Anzahl der Elemente, die der Benutzer eingeben wird, nicht bekannt ist. Daher wird mit zwei Arrays gearbeitet: éléments1 und éléments2.


                ' neues Array zur Aufnahme des neuen Elements
                éléments2 = New Double(i) {}
                ' Altes Array in neues Array kopieren
                If i <> 0 Then
                    Array.Copy(éléments1, éléments2, i)
                End If
                ' Das neue Array wird zum alten Array
                éléments1 = éléments2
                ' Das neue Array wird nicht mehr benötigt
                éléments2 = Nothing
                ' Einfügen eines neuen Elements
                éléments1(i) = élément
                ' ein weiteres Element in der Tabelle
                i += 1

Die Tabelle éléments1 enthält die aktuell eingegebenen Werte. Wenn der Benutzer einen neuen Wert hinzufügt, wird eine Tabelle éléments2 angelegt, die ein Element mehr enthält als éléments1, der Inhalt von éléments1 wird in éléments2 (Array.Copy) kopiert, man lässt éléments1 auf éléments2 „verweisen“ und fügt schließlich das neue Element zu éléments1 hinzu. Dies ist ein komplexer Vorgang, der vereinfacht werden kann, wenn anstelle eines Arrays fester Größe (Array) ein Array variabler Größe (ArrayList) verwendet wird.

Das Array wird mit der Methode Array.Sort sortiert. Diese Methode kann mit verschiedenen Parametern aufgerufen werden, die die Sortierregeln festlegen. Ohne Parameter erfolgt standardmäßig eine Sortierung in aufsteigender Reihenfolge. Schließlich ermöglicht die Methode Array.BinarySearch die Suche nach einem Element in einem sortierten Array.

4.5. Die Klasse ArrayList

Die Klasse ArrayList ermöglicht die Implementierung von Arrays mit variabler Größe während der Programmausführung, was mit der vorherigen Klasse Array nicht möglich ist. Hier sind einige der gängigen Eigenschaften und Methoden:

Public Sub New()
Erstellt eine leere Liste
Public Overridable ReadOnly Property Count
As Integer  Implements ICollection.Count
Anzahl der Elemente in der Sammlung
Public Overridable Function Add(ByVal value
As Object) As Integer Implements IList.Add
fügt das Objekt „value“ am Ende der Sammlung hinzu
Public Overridable Sub Clear()
Implements IList.Clear
löscht die Liste
Overloads Public Overridable Function
IndexOf(ByVal value As Object) As Integer
Implements IList.IndexOf
Index des Objekts „value“ in der Liste oder -1, falls es nicht vorhanden ist
Overloads Public Overridable Function
IndexOf(ByVal value As Object, ByVal startIndex
As Integer) As Integer
ebenso, jedoch beginnend mit dem Element Nr. startIndex
Overloads Public Overridable Function
LastIndexOf(ByVal value As Object) As Integer
ebenso, gibt jedoch den Index des letzten Vorkommens von „value“ in der Liste zurück
Overloads Public Overridable Function
LastIndexOf(ByVal value As Object, ByVal startIndex As Integer) As Integer
ebenso, sucht jedoch ab dem Element Nr. startIndex
Public Overridable Sub Remove( ByVal obj As Object)
Implements IList.Remove
Entferne das Objekt „obj“, falls es in der Liste vorhanden ist
Public Overridable Sub RemoveAt(ByVal index As Integer)
Implements IList.RemoveAt
Entfernt das Element mit dem Index aus der Liste
Overloads Public Overridable Function
BinarySearch(ByVal value As Object) As Integer
Gibt die Position des Objekts „value“ in der Liste zurück oder -1, wenn es nicht vorhanden ist. Die Liste muss sortiert sein
Overloads Public Overridable Sub Sort()
sortiert die Liste. Diese muss Objekte enthalten, die eine vordefinierte Reihenfolge aufweisen (Zeichenketten, Zahlen)
Overloads Public Overridable Sub
Sort(ByVal comparer As IComparer)
sortiert die Liste gemäß der durch die Funktion „vergleichen“ festgelegten Reihenfolge

Nehmen wir das Beispiel mit Objekten vom Typ Array noch einmal auf und wenden wir es auf Objekte vom Typ ArrayList an:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections

Module test
    Sub Main()
        ' Auslesen der per Tastatur eingegebenen Array-Elemente
        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é
            ' Frage
            Console.Out.Write(("Elément (réel) " & i & " du tableau (rien pour terminer) : "))
            ' Antwort auslesen
            réponse = Console.ReadLine().Trim()
            ' Eingabe beenden, wenn Zeichenfolge leer ist
            If réponse.Equals("") Then
                Exit While
            End If
            ' Eingabeprüfung
            Try
                élément = Double.Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' wenn kein Fehler vorliegt
            If Not erreur Then
                ' ein weiteres Element in das Array
                éléments.Add(élément)
            End If
        End While
        ' Anzeige des unsortierten Arrays
        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()
        ' Anzeige des sortierten Arrays
        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
        ' Suche
        While Not terminé
            ' Frage
            Console.Out.Write("Elément cherché (rien pour arrêter) : ")
            ' Antwort lesen und überprüfen
            réponse = Console.ReadLine().Trim()
            ' Fertig?
            If réponse.Equals("") Then
                Exit While
            End If
            ' Überprüfung
            Try
                élément = [Double].Parse(réponse)
                erreur = False
            Catch
                Console.Error.WriteLine("Saisie incorrecte, recommencez")
                erreur = True
            End Try
            ' Wenn kein Fehler
            If Not erreur Then
                ' Das Element wird im sortierten Array gesucht
                i = éléments.BinarySearch(élément)
                ' Anzeige der Antwort
                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

Die Ausführungsergebnisse lauten wie folgt:

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. Die Klasse „Hashtable“

Mit der Klasse Hashtable lässt sich ein Wörterbuch implementieren. Ein Wörterbuch kann man sich als zweispaltiges Array vorstellen:

Die Schlüssel sind eindeutig, c.a.d, d. h., es kann keine zwei identischen Schlüssel geben. Die wichtigsten Methoden und Eigenschaften der Klasse „Hashtable“ sind die folgenden:

Public Sub New()
Erstellt ein leeres Wörterbuch
Public Overridable Sub Add(ByVal key As
Object,ByVal value As Object)
Implements IDictionary.Add
Fügt eine Zeile (Schlüssel, Wert) in das Wörterbuch ein, wobei Schlüssel und Wert Objektreferenzen sind.
Public Overridable Sub Remove
(ByVal key As Object) Implements IDictionary.Remove
entfernt den Eintrag mit dem Schlüssel „key“ aus dem Wörterbuch
Public Overridable Sub Clear()
Implements IDictionary.Clear
leert das Wörterbuch
Public Overridable Function ContainsKey
(ByVal key As Object) As Boolean
Gibt „true“ zurück, wenn der Schlüssel „key“ im Wörterbuch enthalten ist.

Public Overridable Function
ContainsValue(ByVal value As Object) As Boolean
gibt „true“ zurück, wenn der Wert „value“ im Wörterbuch enthalten ist.
Public Overridable ReadOnly Property
Count As Integer  Implements ICollection.Count
Eigenschaft: Anzahl der Elemente im Wörterbuch (Schlüssel, Wert)
Public Overridable ReadOnly Property
Keys As ICollection Implements IDictionary.Keys
Eigenschaft: Sammlung der Schlüssel des Wörterbuchs
Public Overridable ReadOnly Property
Values As ICollection Implements IDictionary.Values
Eigenschaft: Sammlung der Werte des Wörterbuchs
Public Overridable Default Property
Item(ByVal key As Object) As Object  Implements IDictionary.Item
indizierte Eigenschaft: ermöglicht es, den einem Schlüssel „key“ zugeordneten Wert abzurufen oder festzulegen

Betrachten wir das folgende Beispielprogramm:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
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}
        ' Befüllen des Wörterbuchs
        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
        ' Anzahl der Elemente im Wörterbuch
        Console.Out.WriteLine(("Le dictionnaire a " & dico.Count & " éléments"))
        ' Liste der Schlüssel
        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
        ' Liste der Werte
        Console.Out.WriteLine("[Liste des valeurs]")
        Dim valeurs As IEnumerator = dico.Values.GetEnumerator()
        While valeurs.MoveNext()
            Console.Out.WriteLine(valeurs.Current)
        End While
        ' Liste der Schlüssel und Werte
        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
        ' Der Schlüssel „paul“ wird gelöscht
        Console.Out.WriteLine("[Suppression d'une clé]")
        dico.Remove("paul")
        ' Liste der Schlüssel und Werte
        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

        ' Suche im Wörterbuch
        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
            ' nächste Suche
            Console.Out.Write("Nom recherché (rien pour arrêter) : ")
            nomCherché = Console.ReadLine().Trim()
        End While
    End Sub
End Module

Die Ausführungsergebnisse lauten wie folgt:

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

Das Programm verwendet außerdem ein Objekt vom Typ IEnumerator, um die Schlüssel- und Wertesammlungen des Wörterbuchs vom Typ ICollection zu durchlaufen (siehe oben die Eigenschaften „Keys“ und „Values“). Eine Sammlung ist eine Gruppe von Objekten, die durchlaufen werden kann. Die Schnittstelle ICollection ist wie folgt definiert:

Image

Die Eigenschaft Count ermöglicht es uns, die Anzahl der Elemente der Sammlung zu ermitteln. Die Schnittstelle ICollection leitet sich von der Schnittstelle IEnumerable ab:

Image

Diese Schnittstelle verfügt nur über eine Methode, GetEnumerator, mit der wir ein Objekt vom Typ IEnumerator abrufen können:

Image

Die Methode GetEnumerator() einer Sammlung vom Typ ICollection ermöglicht es uns, die Sammlung mit den folgenden Methoden zu durchlaufen:

MoveNext
Springt zum nächsten Element der Sammlung. Gibt „true“ zurück, wenn dieses Element vorhanden ist, andernfalls „false“. Der erste Aufruf von MoveNext springt zum ersten Element. Das „aktuelle“ Element der Sammlung ist dann in der Eigenschaft Current des Enumerators verfügbar
Current
Eigenschaft: aktuelles Element der Sammlung
Reset
setzt den Iterator an den Anfang der Sammlung zurück, c.a.d, vor das erste Element.

Die Struktur für die Iteration über die Elemente einer Sammlung (ICollection) in C sieht daher wie folgt aus:

' Sammlung definieren
dim C as ICollection C=...
' Enumerator für diese Sammlung abrufen
dim itérateur as IEnumerator=C.GetEnumerator();
' die Sammlung mit diesem Enumerator durchlaufen
while(itérateur.MoveNext())
    ' Es gibt ein aktuelles Element
    ' itérateur.Current auswerten
end while

4.7. Die Klasse StreamReader

Die Klasse StreamReader ermöglicht das Lesen des Inhalts einer Datei. Hier sind einige ihrer Eigenschaften und Methoden:

Public Sub New(ByVal path As String)
Öffnet einen Datenstrom aus der Datei „path“. Wenn diese nicht existiert, wird eine Ausnahme ausgelöst
Overrides Public Sub Close()
schließt den Datenstrom
Overrides Public Function ReadLine() As String
liest eine Zeile aus dem geöffneten Stream
Overrides Public Function ReadToEnd() As String
liest den Rest des Streams ab der aktuellen Position

Hier ein Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections
Imports System.IO

Module test
    Sub Main()
        Dim ligne As String = Nothing
        Dim fluxInfos As StreamReader = Nothing
        ' Inhalt der Datei lesen
        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

und die Ausführungsergebnisse:

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. Die Klasse StreamWriter

Die Klasse StreamWriter ermöglicht das Schreiben in eine Datei. Hier sind einige ihrer Eigenschaften und Methoden:

Public Sub New(ByVal path As String)
Öffnet einen Schreibstrom aus der Datei „path“. Es wird eine Ausnahme ausgelöst, wenn dieser nicht erstellt werden kann
Public Overridable Property AutoFlush
As Boolean
Ist der Wert „wahr“, erfolgt das Schreiben in den Stream ohne Zwischenspeicherung; andernfalls erfolgt das Schreiben nicht sofort: Zunächst wird in einen Puffer geschrieben, und erst wenn dieser voll ist, in den Stream. Standardmäßig wird der gepufferte Modus verwendet. Dieser eignet sich gut für Dateistreams, in der Regel jedoch nicht für Netzwerkstreams.
Public Overridable Property NewLine
As String
um das von der Methode WriteLine zu verwendende Zeilenendezeichen festzulegen oder zu ermitteln
Overrides Public Sub Close()
schließt den Stream
Overloads Public Overridable Sub
WriteLine(ByVal value As String)
schreibt eine Zeile in den Schreib-Stream
Overrides Public Sub Flush()
schreibt den Puffer in den Stream

Betrachten wir das folgende Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
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
            ' Erstellung der Textdatei
            fluxInfos = New StreamWriter("infos.txt")
            ' Einlesen der über die Tastatur eingegebenen Zeile
            Console.Out.Write("ligne (rien pour arrêter) : ")
            ligne = Console.In.ReadLine().Trim()
            ' Schleife, solange die eingegebene Zeile nicht leer ist
            While ligne <> ""
                ' Zeile in Textdatei schreiben
                fluxInfos.WriteLine(ligne)
                ' Lesen einer neuen Zeile von der Tastatur
                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
            ' Datei schließen
            Try
                fluxInfos.Close()
            Catch
            End Try
        End Try
    End Sub
End Module

und die Ausführungsergebnisse:

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. Die Klasse „Regex“

Die Klasse Regex ermöglicht die Verwendung regulärer Ausdrücke. Mit diesen lässt sich das Format einer Zeichenkette überprüfen. So kann beispielsweise überprüft werden, ob eine Zeichenkette, die ein Datum darstellt, tatsächlich im Format TT/MM/JJ vorliegt. Dazu wird ein Muster verwendet und die Zeichenkette mit diesem Muster verglichen. In diesem Beispiel müssen j, m und a also Ziffern sein. Das Muster für ein gültiges Datumsformat lautet dann „\d\d/\d\d/\d\d“, wobei das Symbol \d für eine Ziffer steht. Die folgenden Symbole können in einem Muster verwendet werden (Microsoft-Dokumentation):

 
Beschreibung
\
Markiert das folgende Zeichen als Sonderzeichen oder Literal. Beispielsweise entspricht „n“ dem Zeichen „n“. „\n“ entspricht einem Zeilenumbruch. Die Sequenz „\\“ entspricht „\“, während „\("“ dem Zeichen „(“ entspricht.
^
Entspricht dem Beginn der Eingabe.
$
Entspricht dem Ende der Eingabe.
*
Entspricht dem vorhergehenden Zeichen nullmal oder mehrmals. So entspricht „zo*“ sowohl „z“ als auch „zoo“.
+
Entspricht dem vorhergehenden Zeichen ein- oder mehrmals. So entspricht „zo+“ beispielsweise „zoo“, aber nicht „z“.
?
Entspricht dem vorhergehenden Zeichen null- oder einmal. Beispielsweise entspricht „a?ve?“ dem Zeichen „ve“ in „lever“.
.
Entspricht einem beliebigen einzelnen Zeichen, mit Ausnahme des Zeilenumbruchzeichens.

(modèle)
Sucht nach modèle und speichert die Übereinstimmung. Die entsprechende Teilzeichenfolge kann mithilfe von Item [0]...[n] aus der erhaltenen Matches-Sammlung extrahiert werden. Um Übereinstimmungen mit Zeichen in Klammern ( ) zu finden, verwenden Sie „\(“ oder „\)“.

x|y
Entspricht entweder x oder y. Beispielsweise entspricht „z|foot“ entweder „z“ oder „foot“. „(z|f)oo“ entspricht entweder „zoo“ oder „foo“.

{n}
n ist eine nicht-negative ganze Zahl. Entspricht genau dem n-fachen des Zeichens. Beispielsweise entspricht „o{2}“ nicht dem „o“ in „Bob“, sondern den ersten beiden „o“ in „fooooot“.

{n,}
n ist eine nicht-negative ganze Zahl. Entspricht mindestens n-mal dem Zeichen. Beispielsweise entspricht „o{2,}“ nicht dem „o“ in „Bob“, sondern allen „o“ in „fooooot“. „o{1,}“ entspricht „o+“ und „o{0,}“ entspricht „o*“.

{n,m}
m und n sind nicht-negative ganze Zahlen. Entspricht mindestens n und höchstens m Mal dem Zeichen. Beispielsweise entspricht „o{1,3}“ den ersten drei „o“ in „foooooot“ und „o{0,1}“ entspricht „o?“.

[xyz]
Zeichensatz. Entspricht einem der angegebenen Zeichen. Beispielsweise entspricht „[abc]“ dem Zeichen „a“ in „plat“.

[^xyz]
Negativer Zeichensatz. Entspricht jedem nicht angegebenen Zeichen. Beispielsweise entspricht „[^abc]“ dem Zeichen „p“ in „plat“.

[a-z]
Zeichenbereich. Entspricht jedem Zeichen in der angegebenen Zeichenfolge. Beispielsweise entspricht „[a-z]“ jedem Kleinbuchstaben zwischen „a“ und „z“.

[^m-z]
Negativer Zeichenbereich. Entspricht jedem Zeichen, das nicht in der angegebenen Zeichenfolge enthalten ist. Beispielsweise entspricht „[^m-z]“ jedem Zeichen, das nicht zwischen „m“ und „z“ liegt.
\b
Entspricht einer Grenze, die ein Wort darstellt, d. h. der Position zwischen einem Wort und einem Leerzeichen. Beispielsweise entspricht „er\b“ dem Wort „er“ in „lever“, nicht jedoch dem Wort „er“ in „verbe“.
\B
Entspricht einer Grenze, die kein Wort darstellt. „en*t\B“ entspricht „ent“ in „bien entendu“.
\d
Entspricht einem Zeichen, das eine Ziffer darstellt. Entspricht [0-9].
\D
Entspricht einem Zeichen, das keine Ziffer darstellt. Entspricht [^0-9].
\f
Entspricht einem Seitenumbruchzeichen.
\n
Entspricht einem Zeilenumbruchzeichen.
\r
Entspricht einem Wagenrücklaufzeichen.
\s
Entspricht allen Leerzeichen, einschließlich Leerzeichen, Tabulatoren, Seitenumbrüchen usw. Entspricht „[ \f\n\r\t\v]“.
\S
Entspricht jedem nicht-leeren Leerzeichen. Entspricht „[^ \f\n\r\t\v]“.
\t
Entspricht einem Tabulatorzeichen.
\v
Entspricht einem vertikalen Tabulatorzeichen.
\w
Entspricht jedem Zeichen, das ein Wort darstellt und einen Unterstrich enthält. Entspricht „[A-Za-z0-9_]“.
\W
Entspricht jedem Zeichen, das kein Wort darstellt. Entspricht „[^A-Za-z0-9_]“.

\num
Entspricht num, wobei num eine positive ganze Zahl ist. Bezieht sich auf gespeicherte Zuordnungen. Beispielsweise entspricht „(.)\1“ zwei aufeinanderfolgenden identischen Zeichen.

\n
Entspricht n, wobei n ein oktaler Escape-Wert ist. Oktale Escape-Werte müssen aus 1, 2 oder 3 Ziffern bestehen. Beispielsweise entsprechen sowohl „\11“ als auch „\011“ einem Tabulatorzeichen. „\0011“ entspricht „\001“ & „1“. Oktale Escape-Werte dürfen den Wert 256 nicht überschreiten. Sollte dies der Fall sein, werden nur die ersten beiden Ziffern im Ausdruck berücksichtigt. Ermöglicht die Verwendung der Codes ASCII in regulären Ausdrücken.

\xn
Entspricht n, wobei n ein hexadezimaler Escape-Wert ist. Hexadezimale Escape-Werte müssen zwingend aus zwei Ziffern bestehen. Beispielsweise entspricht „\x41“ dem Zeichen „A“. „\x041“ entspricht „\x04“ und „1“. Ermöglicht die Verwendung der Codes ASCII in regulären Ausdrücken.

Ein Element in einer Vorlage kann ein- oder mehrfach vorkommen. Betrachten wir einige Beispiele rund um das Symbol \d, das für eine Ziffer steht:

Vorlage
Bedeutung
\d
eine Ziffer
\d?
0 oder 1 Ziffer
\d*
0 oder mehr Ziffern
\d+
1 oder mehr Ziffern
\d{2}
2 Ziffern
\d{3,}
mindestens 3 Ziffern
\d{5,7}
zwischen 5 und 7 Ziffern

Stellen wir uns nun das Modell vor, das das erwartete Format für eine Zeichenkette beschreiben kann:

gesuchte Zeichenfolge
Modell
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
  

Man kann angeben, an welcher Stelle in der Zeichenfolge nach dem Muster gesucht werden soll:

Muster
Bedeutung
^modèle
Die Vorlage steht am Anfang der Zeichenfolge
modèle$
Die Vorlage beendet die Zeichenfolge
^modèle$
Die Vorlage beginnt und beendet die Zeichenfolge
modèle
Das Muster wird im gesamten String gesucht, beginnend am Anfang des Strings.
Gesuchte Zeichenfolge
Muster
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

Teilmengen eines Musters können „extrahiert“ werden. So lässt sich nicht nur überprüfen, ob eine Zeichenfolge einem bestimmten Muster entspricht, sondern es können auch die Elemente aus dieser Zeichenfolge extrahiert werden, die den in Klammern gesetzten Teilmengen des Musters entsprechen. Wenn man also eine Zeichenfolge analysiert, die ein Datum im Format TT/MM/JJ enthält, und zusätzlich die Elemente TT, MM und JJ dieses Datums extrahieren möchte, verwendet man das Muster (\d\d)/(\d\d)/(\d\d).

4.9.1. Überprüfen, ob eine Zeichenkette einem bestimmten Muster entspricht

Ein Objekt vom Typ „Regex“ wird wie folgt erstellt:

Public Sub New(ByVal pattern As String)

Der Konstruktor erstellt ein „Regulärer Ausdruck“-Objekt anhand eines als Parameter übergebenen Musters (pattern). Sobald der reguläre Ausdruck erstellt ist, kann er mit der Methode IsMatch mit Zeichenfolgen verglichen werden:

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

IsMatch gibt „wahr“ zurück, wenn die Eingabezeichenfolge mit dem Muster des regulären Ausdrucks übereinstimmt. Hier ein Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions

Module regex1

    Sub Main()
        ' ein regulärer Ausdruck als Vorlage
        Dim modèle1 As String = "^\s*\d+\s*$"
        Dim regex1 As New Regex(modèle1)
        ' Ein Exemplar mit dem Muster vergleichen
        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

    ' Anzeigen 
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

und die Ausführungsergebnisse:

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. Alle Elemente einer Zeichenkette finden, die einem Muster entsprechen

Die Methode „Matches“

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

gibt eine Sammlung von Elementen der Zeichenfolge input zurück, die dem Muster entsprechen, wie das folgende Beispiel zeigt:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions

Module regex2
    Sub Main()
        ' mehrere Vorkommen des Musters im Exemplar
        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

    'anzeigen
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Die Klasse MatchCollection verfügt über die Eigenschaft „Count“, die die Anzahl der Elemente in der Sammlung angibt. Wenn résultats ein Objekt vom Typ MatchCollection ist, dann ist résultats(i) das i-te Element dieser Sammlung und vom Typ „Match“. In unserem Beispiel ist résultats die Menge der Elemente der Zeichenkette exemplaire3, die dem Muster modèle2 entsprechen, und résultats(i) ist eines dieser Elemente. Die Klasse Match verfügt über zwei Eigenschaften, die uns hier interessieren:

  • Value: der Wert des Match-Objekts, also das Element, das dem Modell entspricht
  • Index: die Position, an der das Element in der durchsuchten Zeichenkette gefunden wurde

Die Ergebnisse der Ausführung des vorherigen Programms:

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. Teile eines Musters extrahieren

Teilmengen eines Musters können „extrahiert“ werden. So lässt sich nicht nur überprüfen, ob eine Zeichenfolge einem bestimmten Muster entspricht, sondern es können auch die Elemente aus dieser Zeichenfolge extrahiert werden, die den in Klammern gesetzten Teilmengen des Musters entsprechen. Wenn man also eine Zeichenfolge analysiert, die ein Datum im Format TT/MM/JJ enthält, und zusätzlich die Elemente TT, MM und JJ dieses Datums extrahieren möchte, verwendet man das Muster (\d\d)/(\d\d)/(\d\d). Betrachten wir das folgende Beispiel:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions

Module regex2
    Sub Main()
        ' Erfassung von Elementen in der Vorlage
        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"
        ' Vorlagenprüfung
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' Die Instanz entspricht der Vorlage
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' Gruppen werden angezeigt
            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
            ' Das Exemplar entspricht nicht der Vorlage
            affiche(("L'exemplaire[" + exemplaire4 + " ne correspond pas au modèle [" + modèle3 + "]"))
        End If
    End Sub

    'zeigt an
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Die Ausführung dieses Programms liefert folgende Ergebnisse:

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

Die Neuerung befindet sich im folgenden Codeabschnitt:


        ' Vorlagenprüfung
        Dim résultat As Match = regex3.Match(exemplaire4)
        If résultat.Success Then
            ' Das Exemplar entspricht der Vorlage
            affiche(("L'exemplaire [" + exemplaire4 + "] correspond au modèle [" + modèle3 + "]"))
            ' Gruppen werden angezeigt
            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

Die Zeichenfolge exemplaire4 wird mithilfe der Methode Match mit dem Muster regex3 verglichen. Diese Methode gibt ein bereits vorgestelltes Objekt Match zurück. Wir verwenden hier zwei neue Eigenschaften dieser Klasse:

  • Success: gibt an, ob eine Übereinstimmung vorliegt
  • Groups: Sammlung, in der
    • Groups[0] dem Teil der Zeichenkette entspricht, der dem Muster
    • Groups[i] (i >= 1) der Klammergruppe Nr. i entspricht

Wenn das Ergebnis den Typ Match hat, dann ist résultats.Groups vom Typ GroupCollection und résultats.Groups[i] vom Typ Group. Die Klasse Group verfügt über zwei Eigenschaften, die wir hier verwenden:

  • Value: Der Wert des Group-Objekts, dessen Element dem Inhalt einer Klammer entspricht
  • Index: Die Position, an der das Element in der durchsuchten Zeichenkette gefunden wurde

4.9.4. Ein Übungsprogramm

Es ist manchmal eine echte Herausforderung, den regulären Ausdruck zu finden, mit dem wir überprüfen können, ob eine Zeichenkette tatsächlich einem bestimmten Muster entspricht. Mit dem folgenden Programm können Sie üben. Es fragt nach einem Muster und einer Zeichenkette und gibt dann an, ob die Zeichenkette dem Muster entspricht oder nicht.


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Collections
Imports System.Text.RegularExpressions
Imports Microsoft.visualbasic

Module regex4
    Sub Main()
        ' ein regulärer Ausdruck als Vorlage
        Dim modèle, chaine As String
        Dim regex As Regex = Nothing
        Dim résultats As MatchCollection
        ' Der Benutzer wird aufgefordert, die Vorlagen und Instanzen anzugeben, die mit dieser verglichen werden sollen
        Dim terminé1 As Boolean = False
        Do While Not terminé1
            Dim erreur As Boolean = True
            Do While Not terminé1 And erreur
                ' Das Muster wird abgefragt
                Console.Out.Write("Tapez le modèle à tester ou fin pour arrêter :")
                modèle = Console.In.ReadLine()
                ' Fertig?
                If modèle.Trim().ToLower() = "fin" Then
                    terminé1 = True
                Else
                    ' Der reguläre Ausdruck wird erstellt
                    Try
                        regex = New Regex(modèle)
                        erreur = False
                    Catch ex As Exception
                        Console.Error.WriteLine(("Erreur : " + ex.Message))
                    End Try
                End If
            Loop
            ' Fertig?
            If terminé1 Then Exit Sub
            ' Der Benutzer wird aufgefordert, die mit dem Muster zu vergleichenden Instanzen anzugeben
            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()
                ' fertig?
                If chaine.Trim().ToLower() = "fin" Then
                    terminé2 = True
                Else
                    ' Der Vergleich wird durchgeführt
                    résultats = regex.Matches(chaine)
                    ' Erfolgreich?
                    If résultats.Count = 0 Then
                        Console.Out.WriteLine("Je n'ai pas trouvé de correspondances")
                    Else
                        ' Die mit der Vorlage übereinstimmenden Elemente werden angezeigt
                        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))
                            ' Unterelemente
                            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

    'zeigt an
    Sub affiche(ByVal msg As String)
        Console.Out.WriteLine(msg)
    End Sub
End Module

Hier ein Ausführungsbeispiel:

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. Die Methode „Split“

Diese Methode haben wir bereits in der Klasse String kennengelernt:

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

Die Zeichenkette wird als eine Folge von Feldern betrachtet, die durch die im Array [separator] enthaltenen Zeichen getrennt sind. Das Ergebnis ist das Array dieser Felder.

Das Feldtrennzeichen der Zeichenkette ist hier eines der Zeichen aus dem Array separator. Mit der Methode Split der Klasse Regex können wir das Trennzeichen anhand eines Musters ausdrücken:

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

Die Zeichenfolge [input] wird in Felder zerlegt, wobei diese durch ein Trennzeichen getrennt werden, das dem Muster des aktuellen Objekts Regex entspricht. Nehmen wir beispielsweise an, wir hätten in einer Textdatei Zeilen der Form Feld1, Feld2, …, Feldn. Die Felder sind durch ein Komma getrennt, dem jedoch vor oder nach dem Komma Leerzeichen folgen können. Die Methode Split der Klasse string ist in diesem Fall nicht geeignet. Die Methode RegEx bietet die Lösung. Wenn „Zeile“ die gelesene Zeile ist, können die Felder wie folgt abgerufen werden:

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

abgerufen werden, wie das folgende Beispiel zeigt:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Text.RegularExpressions

Module regex5
    Sub Main()
        ' eine Zeile
        Dim ligne As String = "abc  , def  , ghi"
        ' eine Vorlage
        Dim modèle As New Regex("\s*,\s*")
        ' Aufschlüsselung einer Zeile in Felder
        Dim champs As String() = modèle.Split(ligne)
        ' Anzeige
        Dim i As Integer
        For i = 0 To champs.Length - 1
            Console.Out.WriteLine(("champs[" & i & "]=[" & champs(i) & "]"))
        Next i
    End Sub
End Module

Die Ausführungsergebnisse:

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. Die Klassen BinaryReader und BinaryWriter

Die Klassen BinaryReader und BinaryWriter dienen zum Lesen und Schreiben von Binärdateien. Betrachten wir die folgende Anwendung. Wir möchten ein Programm schreiben, das wie folgt aufgerufen wird:

// Syntax pg Text bin
// Eine Textdatei (Text) wird gelesen und ihr Inhalt in einem
// binäre Datei
// Die Textdatei enthält Zeilen der Form „Name: Alter“
//, die in einer Struktur vom Typ „string, int“ gespeichert werden sollen

Die Textdatei hat folgenden Inhalt:

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

Das Programm lautet wie folgt:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Text.RegularExpressions
Imports System.IO

' BinaryWriter()

Module bw1
    ' Syntax pg Text bin
    ' Eine Textdatei (Text) wird gelesen und ihr Inhalt in einem
    ' binäre Datei
    ' Die Textdatei enthält Zeilen der Form „Name: Alter“
    ' die in eine Struktur vom Typ „string, int“ gespeichert werden

    Sub Main(ByVal arguments() As String)
        ' Es sind 2 Argumente erforderlich
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg texte binaire")
            Environment.Exit(1)
        End If
        ' Öffnen der Textdatei zum Lesen
        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
        ' Öffnen der Binärdatei zum Schreiben
        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
        ' Textdatei lesen – Binärdatei schreiben
        ' Zeile der Textdatei
        Dim ligne As String
        ' Feldtrennzeichen der Zeile
        Dim séparateur As New Regex("\s*:\s*")
        ' Altersmuster
        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
            ' Leere Zeile?
            If ligne.Trim() = "" Then
                traitementFini = True
            End If
            ' eine weitere Zeile
            If Not traitementFini Then
                numLigne += 1
                ' eine Zeile mit dem Namen: Alter
                champs = séparateur.Split(ligne)
                ' Wir benötigen 2 Felder
                If champs.Length <> 2 Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un nombre de champs incorrect"))
                    ' nächste Zeile
                    traitementFini = True
                End If
            End If
            If Not traitementFini Then
                ' Das zweite Feld muss eine ganze Zahl >= 0 sein
                If Not modAge.IsMatch(champs(1)) Then
                    Console.Error.WriteLine(("La ligne n° " & numLigne & " du fichier " & arguments(0) & " a un âge incorrect"))
                    ' nächste Zeile
                    traitementFini = True
                End If
                ' Die Daten werden in die Binärdatei geschrieben
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))
            End If
            'nächste Zeile
            ligne = input.ReadLine()
        End While
        ' Schließen der Dateien
        input.Close()
        output.Close()
    End Sub
End Module

Werfen wir einen Blick auf die Vorgänge bezüglich der Klasse BinaryWriter:

  • Das Objekt BinaryWriter wird durch den Vorgang

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

Das Argument des Konstruktors muss ein Stream sein. Hier handelt es sich um einen Stream, der aus einer Datei (FileStream) erstellt wird, für die folgende Angaben gemacht werden:

  • (Fortsetzung)
    • den Namen
    • die auszuführende Operation, hier FileMode.Create zum Erstellen der Datei
    • die Zugriffsart, hier FileAccess.Write für einen Schreibzugriff auf die Datei
  • den Schreibvorgang

                ' Die Daten werden in die Binärdatei geschrieben
                output.Write(champs(0))
                output.Write(Integer.Parse(champs(1)))

Die Klasse BinaryWriter verfügt über verschiedene überladene Methoden Write zum Schreiben der verschiedenen einfachen Datentypen

  • den Vorgang zum Schließen des Datenstroms
        output.Close()

Die Ergebnisse der vorherigen Ausführung werden uns vom folgenden Programm ausgegeben. Dieses akzeptiert ebenfalls zwei Argumente:

    ' Syntax: pg bin text
    ' eine Binärdatei „bin“ wird gelesen und ihr Inhalt in eine Textdatei („text“) gespeichert
    ' Die Binärdatei hat eine Struktur aus Zeichenketten und Ganzzahlen
    ' Die Textdatei enthält Zeilen der Form „Name: Alter“

Wir führen also den umgekehrten Vorgang durch. Wir lesen eine Binärdatei ein, um eine Textdatei zu erstellen. Wenn die erzeugte Textdatei mit der Originaldatei identisch ist, wissen wir, dass die Konvertierung von Text → Binär → Text erfolgreich verlaufen ist. Der Code lautet wie folgt:


' Optionen
Option Strict On
Option Explicit On 

' Namensräume
Imports System
Imports System.Text.RegularExpressions
Imports System.IO

Module br1
    ' Syntax pg bin text
    ' Eine Binärdatei „bin“ wird gelesen und ihr Inhalt in eine Textdatei („text“) geschrieben
    ' Die Binärdatei hat die Struktur „string, int“
    ' Die Textdatei enthält Zeilen der Form „Name: Alter“

    Sub Main(ByVal arguments() As String)
        ' Es sind 2 Argumente erforderlich
        Dim nbArgs As Integer = arguments.Length
        If nbArgs <> 2 Then
            Console.Error.WriteLine("syntaxe : pg binaire texte")
            Environment.Exit(1)
        End If
        ' Öffnen der Binärdatei zum Lesen
        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
        ' Öffnen der Textdatei zum Schreiben
        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
        ' Binärdatei lesen – Textdatei schreiben
        Dim nom As String        ' nom d'une personne
        Dim age As Integer        ' son âge
        ' Verarbeitungsschleife für die Binärdatei
        While True
            ' Name lesen
            Try
                nom = dataIn.ReadString()
            Catch
                ' Ende der Datei
                Exit Sub
            End Try
            ' Alter lesen
            Try
                age = dataIn.ReadInt32()
            Catch
                Console.Error.WriteLine("Le fichier " & arguments(0) + " ne semble pas avoir un format correct")
                Exit Sub
            End Try
            ' Schreiben in Textdatei
            dataOut.WriteLine(nom & ":" & age)
            System.Console.WriteLine(nom & ":" & age)
        End While
        ' alles schließen
        dataIn.Close()
        dataOut.Close()
    End Sub
End Module

Werfen wir einen Blick auf die Vorgänge rund um die Klasse BinaryReader:

  • Das Objekt BinaryReader wird durch den Vorgang

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

Das Argument des Konstruktors muss ein Stream sein. Hier handelt es sich um einen Stream, der aus einer Datei (FileStream) erstellt wurde, für die wir Folgendes angeben:

  • (Fortsetzung)
    • den Namen
    • die auszuführende Operation, hier FileMode.Open zum Öffnen einer vorhandenen Datei
    • die Zugriffsart, hier FileAccess.Read für den Lesezugriff auf die Datei
  • den Lesevorgang
                nom = dataIn.ReadString()
                age = dataIn.ReadInt32()

Die Klasse BinaryReader verfügt über verschiedene Methoden ReadXX zum Lesen der verschiedenen einfachen Datentypen

  • der Vorgang zum Schließen des Datenstroms
        dataIn.Close()

Wenn man die beiden Programme nacheinander ausführt und dabei personnes.txt in personnes.bin und anschließend personnes.bin in personnes.txt2 umwandelt, erhält man:

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