10.2 String
Wie in Abschnitt 3.1.9, »Datentypen«, bereits erwähnt wurde, sind Zeichenketten vom Typ String unveränderlich. Bei jeder Änderung wird ein neues Objekt erzeugt. Häufig zu ändernde Zeichenfolgen repräsentieren Sie effizienter mit der Klasse StringBuilder. Um keinen Speicherplatz zu verschwenden, werden String-Literale in einem Pool verwaltet.
10.2.1 Erzeugung
Die Initialisierung einer Zeichenkette kann durch direkte Zuweisung oder über einen Konstruktor erfolgen, von denen drei häufiger eingesetzt werden:
Dim z As String = "Literal" Dim z As String = <Char-Array> Public Sub New(c As Char, count As Integer) Public Sub New(value As Char()) Public Sub New(value As Char(), startIndex As Integer, length As Integer) |
Der erste Konstruktor wiederholt ein Zeichen, die beiden anderen bedienen sich aus einem Zeichenarray.
Dim z1 As String = New Char(){"1"c,"2"c,"3"c,"4"c} 'ergibt "1234" Dim z2 As New String("x"c, 3) 'ergibt "xxx" Dim z3 As New String(New Char(){"1"c,"2"c,"3"c,"4"c}) 'ergibt "1234" Dim z4 As New String(New Char(){"1"c,"2"c,"3"c,"4"c}, 1, 2) 'ergibt "23"
10.2.2 Eigenschaften
String weist nur zwei Eigenschaften auf: Length und Chars. Length liefert die Anzahl der Zeichen, und mit Chars greifen Sie auf ein einzelnes Zeichen aus der Zeichenfolge zu:
Public ReadOnly Default Property Chars(index As Integer) As Char |
Im folgenden Codefragment wird das Zeichen »L« in c gespeichert:
Dim str As String = "HALLO" Dim c As Char = str(2)
10.2.3 Methoden
Die Methoden dienen im Wesentlichen zur Manipulation von Zeichenketten (siehe Tabelle 10.2).
Methode | Beschreibung | |
Clone |
Referenz auf diesen String (keine Kopie) |
|
Compare |
Vergleich zweier Zeichenketten |
S |
CompareOrdinal |
Vergleich zweier Zeichenketten auf Codebasis |
S |
CompareTo |
Vergleich zweier Zeichenketten |
|
Concat |
Zeichenketten zusammenfügen |
S |
Contains |
Gibt an, ob die gegebene Zeichenkette in dieser Zeichenkette vorkommt. |
|
Copy |
Kopie der Zeichenkette |
S |
CopyTo |
Kopie eines Teilstrings in ein Zeichenarray |
|
EndsWith |
Gibt an, ob die gegebene Zeichenkette das Ende dieser Zeichenkette darstellt. |
|
Equals |
Gibt an, ob zwei Zeichenketten gleiche Buchstabenfolgen haben. |
(S) |
Format |
Formatierung ähnlich Write |
S |
GetEnumerator |
»Zähler« zum Durchlaufen in einer Schleife |
|
GetTypeCode |
Gleichnamige Enumeration hat Primitive, Object, DBNull und Empty. |
|
IndexOf |
Erstes Auftreten der gegebenen Zeichenkette in dieser Zeichenkette |
|
IndexOfAny |
Erstes Auftreten der gegebenen Buchstaben in dieser Zeichenkette |
|
Insert |
Einfügen eines Teilstrings |
|
Intern |
Interne Referenz auf diese Zeichenkette (gegebenenfalls in Pool überführt) |
S |
IsInterned |
Referenz auf Pool-String oder Nothing |
S |
IsNormalized |
Gibt an, ob die Zeichenkette in Unicode »Normalform« vorliegt. |
|
IsNullOrEmpty |
Gibt an, ob ein Leerstring oder Nothing vorliegt. |
S |
Join |
Verbinden eines String-Arrays mit gegebenem Separator |
S |
LastIndexOf |
Letztes Auftreten der gegebenen Zeichenkette in dieser Zeichenkette |
|
LastIndexOfAny |
Letztes Auftreten der gegebenen Zeichen in dieser Zeichenkette |
|
Normalize |
Unicode in »Normalform« konvertieren |
|
PadLeft |
Auffüllen von links mit gegebenen Zeichen, bis Länge erreicht ist |
|
PadRight |
Auffüllen von rechts mit gegebenen Zeichen, bis Länge erreicht ist |
|
Remove |
Eine gegebene Anzahl Zeichen löschen |
|
Replace |
Ersetzen von Teilstrings durch gegebene Zeichenfolgen |
|
Split |
String beim Auftreten der gegebenen Zeichen trennen |
|
StartsWith |
Gibt an, ob die gegebene Zeichenkette den Anfang dieser Zeichenkette darstellt. |
|
Substring |
Extraktion eines Teilstrings |
|
ToCharArray |
Kopie von Buchstaben in ein Char-Array |
|
ToLower |
Umwandlung in Kleinbuchstaben |
|
ToLowerInvariant |
Umwandlung in Kleinbuchstaben mit neutraler Kultur |
|
ToUpper |
Umwandlung in Großbuchstaben |
|
ToUpperInvariant |
Umwandlung in Großbuchstaben mit neutraler Kultur |
|
Trim |
Entfernen gegebener Zeichen am Rand |
|
TrimEnd |
Entfernen gegebener Zeichen am rechten Rand |
|
TrimStart |
Entfernen gegebener Zeichen am linken Rand |
Zeichenfolgen-Vergleiche
Die vier Methoden Equals, Compare, CompareTo und CompareOrdinal sind sehr ähnlich. Wie bereits in Abschnitt 6.2.2, »List«, gezeigt wurde, liefert CompareTo einen negativen Wert, wenn die Zeichenketten lexikalisch sortiert sind, und einen positiven Wert, wenn nicht. Bei Gleichheit wird Null zurückgegeben.
Hinweis |
Standardmäßig wird bei String-Variablen zwischen Groß- und Kleinschreibung unterschieden. |
Entscheidend dafür, wann ein Zeichen als größer oder kleiner im Vergleich zu einem zweiten gilt, ist die spezifische Ländereinstellung. Im mitteleuropäischen Sprachraum ist festgelegt, dass den Großbuchstaben ein größerer Wert zugeordnet ist als ihrem kleingeschriebenen Pendant. Compare vergleicht erst Buchstaben und dann die Schreibung:
a < A < b < B < c < C ... < y < Y < z < Z |
CompareOrdinal vergleicht zwei Zeichenfolgen auf Basis der Zeichencodes. Sind alle identisch, gibt die Funktion Null zurück. Sonst gibt sie die Differenz der Codes des ersten unterschiedlichen Buchstabens zurück.
A < B < C ... X < Y < Z ... a < b < c ... x < y < z |
Das folgende Codefragment testet die beiden Vergleiche:
'...\Basisklassen\KlasseString\Vergleich.vb |
Option Strict On Namespace Basisklassen Module Vergleich Sub Vergleichen(ByVal fun As Func(Of String, String, Integer)) For Each s As String In New String() {"A", "a", "E", "e"} Console.Write("{0}-{1}:{2} ", "C", s, fun("C", s)) Next Console.WriteLine() End Sub Sub Test() Console.Write("Compare: ") Vergleichen(AddressOf String.Compare) Console.Write("CompareOrdinal: ") Vergleichen(AddressOf String.CompareOrdinal) Console.ReadLine() End Sub End Module End Namespace
Die Ausgabe zeigt die verschiedene Einsortierung der Kleinbuchstaben:
Compare: C-A:1 C-a:1 C-E:-1 C-e:-1 CompareOrdinal: C-A:2 C-a:-30 C-E:-2 C-e:-34
Suchen in einer Zeichenkette
Es gibt zwei Gruppen von Suchfunktionen. Die Methoden StartsWith, Contains und EndsWith testen, ob ein Teilstring mit einer gegebenen Zeichenfolge übereinstimmt, während IndexOf und LastIndexOf eine konkrete Position liefern, die in den Methoden Substring und Insert verwendet werden kann. Die Länge der beteiligten Zeichenketten ist beliebig, die Suchfunktionen berücksichtigen Groß- und Kleinschreibung. Das folgende Beispiel zeigt einige der Methoden im Einsatz. Die Abbruchbedingung der Schleife nutzt die Rückgabe von -1 der Methode IndexOf, wenn der Teilstring nicht gefunden wird.
'...\Basisklassen\KlasseString\Suchen.vb |
Option Strict On Namespace Basisklassen Module Suchen Sub Test() Dim str As String = "Da wird der Hund in der Pfanne verrückt." Console.WriteLine("Start mit Da: {0}", str.StartsWith("Da")) Dim pos As Integer = –1 Do pos += 1 pos = str.IndexOf("der", pos) If pos > 0 Then Console.Write(str.Substring(pos, 7) & " -") Loop While pos >= 0 Console.WriteLine() Console.WriteLine("Rest: {0}", str.Substring(str.LastIndexOf("der"))) Console.ReadLine() End Sub End Module End Namespace
Der Satzanfang wird korrekt gefunden, und es werden jeweils 7 Buchstaben lange Teilstrings ausgegeben, die mit »der« beginnen (IndexOf liefert den Beginn der gesuchten Zeichenfolge). Die einparametrige Variante von Substring extrahiert einen Teilstring von der gegebenen Position bis zum Ende der gesamten Zeichenkette.
Start mit Da: True der Hun -der Pfa - Rest: der Pfanne verrückt.
Textränder bearbeiten
Leerzeichen sind naturgemäß nicht sichtbar. Bei einer Texteingabe können sie insbesondere am Anfang und Ende der Eingabe leicht übersehen werden. Werden die Eingaben ungefiltert gespeichert und wird später ohne Leerzeichen danach gesucht, sind die Daten »unauffindbar«. Die unerwünschten Zusatzzeichen können Sie mit Trim, TrimStart oder TrimEnd entfernen.
Public Function Trim() As String Public Function Trim(ParamArray trimChars As Char()) As String Public Function TrimEnd(ParamArray trimChars As Char()) As String Public Function TrimStart(ParamArray trimChars As Char()) As String |
Die Überladungen der Methode entfernen auch andere Zeichen an den Textenden. Im folgenden Codefragment wird das Trennzeichen für Verzeichnisse in einer Pfadangabe entfernt, ganz ohne If-Anweisungen:
Dim str As String = "C:\Temp\ "
Console.WriteLine("""{0}"" -> ""{1}""", str, str.TrimEnd("\ ".ToCharArray()))
Die Ausgabe zeigt die Kürzung:
"C:\Temp\ " -> "C:\Temp"
Der gegenteilige Fall sind fehlende Zeichen an den Textenden. Die Methoden PadLeft und PadRight füllen eine Zeichenkette bis zur angegebenen Länge auf.
Public Function PadLeft(totalWidth As Integer) As String Public Function PadLeft(totalWidth As Integer, padding As Char) As String Public Function PadRight(totalWidth As Integer) As String Public Function PadRight(totalWidth As Integer, padding As Char) As String |
Dies ist zum Beispiel für tabellarische Darstellungen praktisch.
For Each z As Double In New Double() {-1.27, 8.24, 12.98, –100.01}
Console.WriteLine(z.ToString().PadLeft(7))
Next
Die Zahlen werden rechtsbündig ausgegeben:
–1,27 8,24 12,98 –100,01
Zeichenfolgen ändern
Neben den drei grundlegenden Änderungsoperationen Einfügen einer Zeichenkette, Löschen von Bereichen und Ersetzen eines Teilstrings durch einen anderen gibt es Methoden, um alle Buchstaben einer Zeichenkette klein- oder großzuschreiben, wobei Kulturabhängigkeiten berücksichtigt werden können.
Public Function Insert(startIndex As Integer, value As String) As String Public Function Remove(startIndex As Integer) As String Public Function Remove(startIndex As Integer, count As Integer) As String Public Function Replace(oldChar As Char, newChar As Char) As String Public Function Replace(oldValue As String, newValue As String) As String Public Function ToLower() As String Public Function ToLower(culture As CultureInfo) As String Public Function ToLowerInvariant() As String Public Function ToUpper() As String Public Function ToUpper(culture As CultureInfo) As String Public Function ToUpperInvariant() As String |
Im folgenden Codefragment nutzen wir IndexOf, um die richtige Einfügeposition in Insert für den zweiten Vornamen zu erhalten. Diesen schreiben wir danach durch Ersetzen mit Replace aus bzw. geben den Namen mit ToUpper in Großschreibung aus:
Dim str As String = "James Kirk" str = str.Insert(str.IndexOf("Kirk"), "T. ") Console.WriteLine("Kurzform: {0}", str) Console.WriteLine("Voller Name: {0}", str.Replace("T.", "Tiberius")) Console.WriteLine("Großgeschrieben: {0}", str.ToUpper())
Die verschiedenen Namensformen werden korrekt ausgegeben:
Kurzform: James T. Kirk Voller Name: James Tiberius Kirk Großgeschrieben: JAMES T. KIRK
Daten in Zeichenketten
Programme können nicht alle denkbaren Datenformate speichern, sondern nur die bei der Entwicklung berücksichtigten. So weiß zum Beispiel eine Datenbank in der Regel nichts von einer von Ihnen entwickelten Datenstruktur. Wollen Sie die Daten dennoch in zusammenhängender Form speichern, bietet sich eine Konvertierung in eine Zeichenkette an. Die einzelnen Datenfelder werden durch Zeichen getrennt, die in den Daten selbst nicht vorkommen. Ein einfaches Beispiel ist eine Textverarbeitung, die die Zeilen des Textes zusammenhängend speichert. Das Trennzeichen ist in diesem Fall ein Zeilenvorschub. Am einfachsten setzen Sie die Zeichenkette mit Join zusammen, und Sie zerlegen sie mit Split. In der folgenden Syntax sind optionale Parameter kursiv gesetzt.
Public Shared Function Join(separator As String, value As String(), _ startIndex As Integer, count As Integer) As String Public Function Split(ParamArray separator As Char()) As String() Public Function Split(separator As Char(), count As Integer, _ options As StringSplitOptions) As String() Public Function Split(separator As String(), count As Integer, _ options As StringSplitOptions) As String() |
Im folgenden Beispiel wird Split im Konstruktor der Klasse Person benutzt, um die Werte der einzelnen Felder zu ermitteln. Das Zusammensetzen für die Ausgabe in ToString übernimmt Join. Ich benutze die Methoden GetFields, GetValue und SetValue aus der Klasse Type, um das Listing kurz zu halten und Ihnen Anregungen für eigene Klassen zu geben.
'...\Basisklassen\KlasseString\Teilen.vb |
Option Strict On Namespace Basisklassen Module Teilen Class Person Public Name, Straße, Ort As String Public Sub New(ByVal p As String) Dim felder() As String = p.Split(";"c) For nr As Integer = 0 To Me.GetType().GetFields().Length – 1 Me.GetType().GetFields()(nr).SetValue(Me, felder(nr)) Next End Sub Public Overrides Function ToString() As String Return String.Join(";", Me.GetType().GetFields(). _ Select(Function(f) CType(f.GetValue(Me), String)).ToArray()) End Function End Class Sub Test() Dim p As New Person("E. van Haar;Engelsstr. 10;42283 Wuppertal") Console.WriteLine("Person : {0}", p) Console.WriteLine("Kontrolle: {0};{1};{2}", p.Name, p.Straße, p.Ort) Console.ReadLine() End Sub End Module End Namespace
Die ausgegebenen Informationen sind identisch zur Eingabe:
Person : E. van Haar;Engelsstr. 10;42283 Wuppertal Kontrolle: E. van Haar;Engelsstr. 10;42283 Wuppertal
Wollen Sie die Separatorzeichen lieber selbst einsetzen, können Sie als Alternative zum Verkettungsoperator & die Methode Concat verwenden:
Public Shared Function Concat(ParamArray args As Object()) As String Public Shared Function Concat(ParamArray values As String()) As String |
Zeichenfolgen und Char-Arrays
Viele Methoden im .NET Framework haben Zeichenketten als Parameter, andere erwarten ein Char-Array. Daher sind Umwandlungen öfter nötig. Der Weg zur Zeichenkette führt über den Konstruktor (siehe Abschnitt 10.2.1, »Erzeugung«). Für die umgekehrte Richtung gibt es eine Methode:
Public Function ToCharArray() As Char() Public Function ToCharArray(start As Integer, length As Integer) As Char() |
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.