std.string — Zeichenketten
Die meistgenutzte Unit der Standardbibliothek: Suchen, Vergleichen, Ersetzen, Teilen, Verbinden, Auffüllen, Umwandeln — alles auf pchar, also auf rohen, mit einem Nullbyte abgeschlossenen Bytes.
Autor: Andreas Röne
Copyright: 2024–2025 Andreas Röne
Quelle: std/string.lyx
<WRAP info> Die Such-, Vergleichs-, Ersetz- und Aufteilfunktionen sind vollständig geprüft und arbeiten korrekt. Die beiden früher hier verzeichneten Parser-Mängel sind seit 1.0.20F behoben (#1517, #1518):
StrToF64("0.5") = 0.500000 ok=1
StrToF64("3.75") = 3.750000 ok=1
StrToInt64("-") = 0 ok=0
</WRAP>
StringBuilder ist eine Klasse und muss mit new erzeugt werden:
var sb: StringBuilder := new StringBuilder();
var sb: StringBuilder; wird seit #1570 abgewiesen — die Prüfung aus #1519 greift jetzt auch bei importierten Klassen: sema error: Variable hat Klassentyp ohne Startwert — `new` oder `null` angeben 'StringBuilder'. Vorher übersetzte die Zeile fehlerfrei und stürzte beim ersten Aufruf ab.
Import
import std.string;
StrLen, StrCharAt, StrSetChar, StrConcat, StrSub, StrNew, StrFree, StrStartsWith und StrEndsWith sind Builtins — sie stehen ohne Import zur Verfügung und sind nicht Teil dieser Unit.
Die drei Speicher-Konventionen
Das ist der wichtigste Abschnitt dieser Seite. Die Unit ist über Jahre gewachsen und verwendet drei verschiedene Konventionen dafür, wohin das Ergebnis geschrieben wird. Wer sie verwechselt, bekommt entweder keinen Effekt oder einen Absturz.
| Konvention | Erkennbar an | Funktionen |
|---|---|---|
| Ziel vom Aufrufer | erster Parameter heißt dest | StrToLower, StrToUpper, StrTrimWhitespace, StrSubstring, StrReplace, Int64ToStr |
| Ergebnis alloziert | nur der Eingabestring als Parameter, Rückgabe pchar | StrTrim, StrFirstCharToUpper, StrFirstCharToLower, StrLastCharToUpper, StrLastCharToLower, StrJoin, StrRepeat, StrFormat, StrPadLeft/StrPadRight (siehe unten) |
| an Ort und Stelle | verändert das Argument selbst | StrReverse |
Bei der ersten Konvention rechnet der Aufrufer die nötige Größe aus und legt den Puffer an — es findet keine Prüfung statt. Bei der zweiten gehört der zurückgegebene Speicher dem Aufrufer.
Funktionen
Suchen
| Signatur | Beschreibung |
|---|---|
StrFind(haystack: pchar, needle: pchar): int64 | Position des ersten Vorkommens, sonst -1 |
StrIndexOf(s: pchar, needle: pchar, startIndex: int64): int64 | wie StrFind, aber ab einer Startposition |
StrContains(s: pchar, needle: pchar): bool | ob der Teilstring vorkommt |
StrIndexOfChar(s: pchar, c: int64, startIndex: int64): int64 | erstes Vorkommen eines Zeichens ab startIndex |
StrLastIndexOfChar(s: pchar, c: int64): int64 | letztes Vorkommen eines Zeichens |
StrAllIndicesOfCharCount(s: pchar, c: int64): int64 | wie oft ein Zeichen vorkommt |
StrCount(s: pchar, needle: pchar): int64 | wie oft ein Teilstring vorkommt — überlappungsfrei |
StrSafeCharAt(s: pchar, index: int64): int64 | Zeichen an einer Stelle, -1 außerhalb der Länge |
Eine leere Nadel liefert bei StrFind die Position 0 (sie gilt als am Anfang gefunden), bei StrCount dagegen 0. StrCount(„aaaa“, „aa“) ergibt 2, nicht 3 — nach einem Treffer wird hinter dem Fund weitergesucht.
Vergleichen
| Signatur | Beschreibung |
|---|---|
StrCmp(a: pchar, b: pchar): int64 | -1, 0 oder 1 — lexikografisch nach Bytewert |
StrCmp("abc", "abc") // 0
StrCmp("abc", "abd") // -1
StrCmp("b", "a") // 1
Groß- und Kleinschreibung
| Signatur | Beschreibung |
|---|---|
CharToLower(c: int64): int64 | einzelnes Zeichen |
CharToUpper(c: int64): int64 | einzelnes Zeichen |
StrToLower(dest: pchar, src: pchar): pchar | ganzer String nach dest |
StrToUpper(dest: pchar, src: pchar): pchar | ganzer String nach dest |
StrFirstCharToUpper(s: pchar): pchar | erstes Zeichen groß, Ergebnis alloziert |
StrFirstCharToLower(s: pchar): pchar | erstes Zeichen klein, Ergebnis alloziert |
StrLastCharToUpper(s: pchar): pchar | letztes Zeichen groß, Ergebnis alloziert |
StrLastCharToLower(s: pchar): pchar | letztes Zeichen klein, Ergebnis alloziert |
Alle wandeln nur ASCII. StrToUpper auf „straße“ ergibt „STRAßE“ — das ß bleibt, weil es in UTF-8 zwei Bytes belegt, die keine ASCII-Buchstaben sind. Für Umlaute und Sonderzeichen ist std.text zuständig.
Zuschneiden und Teilstrings
| Signatur | Beschreibung |
|---|---|
StrTrim(s: pchar): pchar | Leerraum an beiden Enden weg, Ergebnis alloziert |
StrTrimWhitespace(dest: pchar, src: pchar): pchar | dasselbe, aber nach dest |
StrSubstring(dest: pchar, src: pchar, start: int64, len: int64): pchar | Teilstring nach dest; start und len werden auf die Länge begrenzt |
IsWhitespace(c: int64): bool | Leerzeichen, Tabulator, Zeilenumbruch … |
Die beiden Trim-Funktionen unterscheiden sich nur in der Speicherkonvention — die Namen verraten das nicht. StrTrim alloziert, StrTrimWhitespace schreibt in einen mitgegebenen Puffer.
Verändern
| Signatur | Beschreibung |
|---|---|
StrReverse(s: pchar): pchar | dreht das Argument selbst um und gibt es zurück |
StrReplace(dest: pchar, src: pchar, old: pchar, replacement: pchar): pchar | ersetzt alle Vorkommen, Ergebnis nach dest |
StrPadLeft(s: pchar, width: int64, padChar: int64): pchar | links auffüllen bis width |
StrPadRight(s: pchar, width: int64, padChar: int64): pchar | rechts auffüllen bis width |
StrRepeat(s: pchar, n: int64): pchar | n-fache Wiederholung, Ergebnis alloziert |
Teilen und Verbinden
| Signatur | Beschreibung |
|---|---|
StrSplit(s: pchar, delim: pchar, out: int64, maxParts: int64): int64 | schreibt Zeiger auf die Teile in out, liefert deren Anzahl |
StrJoin(parts: int64, count: int64, delim: pchar): pchar | fügt count Strings mit Trenner zusammen, Ergebnis alloziert |
out ist die Adresse eines Feldes aus int64-Plätzen zu je 8 Byte. Jeder Teil wird einzeln alloziert; der Aufrufer gibt sie einzeln frei. Sind mehr Teile vorhanden als maxParts zulässt, landet der gesamte Rest ungeteilt im letzten Platz:
StrSplit("a,b,c,d", ",", out, 2) // 2 Teile: "a" und "b,c,d"
Zahlen
| Signatur | Beschreibung |
|---|---|
StrToInt(s: pchar): int64 | überliest führenden Leerraum, bricht beim ersten Nicht-Ziffernzeichen ab, meldet keinen Fehler |
StrToInt64(s: pchar, ok: int64): int64 | strenger Parser; ok zeigt auf ein int64, das auf 1 oder 0 gesetzt wird |
Int64ToStr(n: int64, buf: int64): pchar | Zahl nach buf — mindestens 22 Byte bereitstellen |
StrToF64(s: pchar, ok: int64): f64 | Dezimalzahl mit Nachkommateil; ok zeigt Erfolg an |
Die beiden Ganzzahlparser verhalten sich verschieden, was leicht zu verwechseln ist:
| Eingabe | StrToInt | StrToInt64 |
|---|---|---|
„42“ | 42 | 42, ok=1 |
„ 42“ | 42 | 0, ok=0 |
„12x“ | 12 | 0, ok=0 |
„abc“ | 0 | 0, ok=0 |
StrToInt kann eine fehlgeschlagene Umwandlung nicht anzeigen: das Ergebnis 0 ist von einer echten „0“ nicht zu unterscheiden. Wo die Eingabe von außen kommt, gehört StrToInt64 mit ausgewertetem ok hin. Einen Überlaufschutz hat keiner von beiden.
Formatieren
| Signatur | Beschreibung |
|---|---|
StrFormat(fmt: pchar, a0, a1, a2, a3, a4: int64): pchar | printf-artig, genau 5 Argumente, Ergebnis alloziert |
| Platzhalter | Bedeutung |
|---|---|
%s | Zeichenkette (pchar als int64 übergeben) |
%d | Dezimalzahl |
%x | Hexadezimal, Kleinbuchstaben |
%08x | Hexadezimal, auf 8 Stellen mit Nullen aufgefüllt |
* std.buffer — binärsichere Operationen auf rohen Bytes
