Nun, da uns Arrays bekannt sind und wir mit den Basis-Typen
und dem Schlüsselwortimmutable
beschäftigt haben, wird es
Zeit zwei neue Konstrukte in einer Zeile einzuführen:
alias string = immutable(char)[];
Der Begriff string
wird durch das Schlüsselwort alias
definiert,
und zwar als Slice bestehend aus immutable(char)
s.
Das bedeutet, sobald ein string
konstruiert wurde, wird sich sein
Inhalt nie mehr ändern. Und damit sind wir bei dem zweiten Konstrukt:
Willkommen UTF-8 string
!
Aufgrund ihrer Unveränderlichkeit (engl.: immutablility) können
string
s über verschiedene Threads hinweg geteilt werden. Da string
ein Slice ist, können Teile ohne Speicher-Allokationen entnommnen werden.
Die Standard-Funktion std.algorithm.splitter
](https://dlang.org/phobos/stdalgorithmiteration.html#.splitter)
z.B. teilt einen String anhand von Zeilensprüngen (newline-Zeichen)
ohne jede Speicher-Allokation.
Neben dem UTF-8 string
gibt es zwei weitere Typen:
alias wstring = immutable(wchar)[]; // UTF-16
alias dstring = immutable(dchar)[]; // UTF-32
Diese Varianten können durch Nutzung der to
-Methode aus std.conv
einfach ineinander konvertiert werden:
dstring myDstring = to!dstring(myString);
string myString = to!string(myDstring);
Ein einfacher string
ist als ein Array aus 8-bit Unicode code
units definiert. Alle Array-Operationen
können auf Strings angewandt werden, aber dies wird nur auf der Code-Unit-Ebene
funktionieren, nicht aber auf Zeichen-Ebene! Gleichzeitig interpretieren die
Algorithmen der Standard-Bibliothek Strings als Sequenzen aus
Code Points. Darüber hinaus gibt es
die Option der Behandlung der Sequenz als
Grapheme durch explizite Nutznung von
std.uni.byGrapheme
.
Diese kleine Beispiel verdeutlicht die unterschiedlichen Interpretationen:
string s = "\u0041\u0308"; // Ä
writeln(s.length); // 3
import std.range : walkLength;
writeln(s.walkLength); // 2
import std.uni : byGrapheme;
writeln(s.byGrapheme.walkLength); // 1
Hier ist die tatsächliche Länge des Arrays s
3, weil es 3 Code Units
enthält: 0x41
, 0x03
and 0x08
. Von diesen definieren zwei einen einzelnen
Code Point (kombinierende diakritische Zeichen) und
walkLength
(Funktion der Standard-Bibliothek zur Berechnung der Länge beliebiger Ranges)
zählt zwei Code Points. Schließlich ermittelt byGrapheme
in einer aufwändigeren
Berechnung, dass sich diese beiden Code Points zu einem einzigen angezeigten
Zeichen zusammensetzen.
Korrekte Unicode-Verarbeitung kann sehr kompliziert sein. Trotzdem dürfen
D-Entwickler String-Variablen als magische Byte-Arrays betrachten und sich darauf
verlassen, dass die Standard-Bibliothek "das Richtige tut".
Die meiste Unicode-Funktionalität wird in dem Modul
std.uni
bereitgestellt, Grundlegenderes
in std.utf
.
Für die Erzeugung mehrzeiliger Strings bietet sich die
string str = q{ ... }
-Syntax an:
string multiline = q{ This
may be a
long document
};
Auch ist es möglich Raw Strings zu benutzen, um die aufwändige Verarbeitung
von reservierten Symbolen zu minimieren. Raw Strings können mittels Backticks
(invertierte Hochkommanta) ( ` ... `
) oder den r(aw)-Präfix (r" ... "
)
deklariert werden.
string raw = `raw "string"`; // raw "string"
string raw2 = r"raw "string"; // raw "string"