- Symbolkette
-
Eine Zeichenkette oder ein String (englisch) ist eine Folge von Zeichen (z. B. Buchstaben, Ziffern, Sonderzeichen und Steuerzeichen) aus einem definierten Zeichensatz. Zeichen können sich in einer Zeichenkette wiederholen, die Reihenfolge der Zeichen ist definiert. Zeichenketten sind somit Sequenzen aus Symbolen mit endlicher Länge.
Im Kontext formaler Sprachen werden Zeichenketten meist als Wörter bezeichnet. Die Theorie der formalen Sprachen befasst sich mit den Eigenschaften von Mengen von Wörtern.
In der Programmierung ist eine Zeichenkette ein Datentyp, der eine Kette von Zeichen mit fester oder variabler Länge enthält. Damit werden hauptsächlich Wörter, Sätze und ganze Texte gespeichert. Fast jede Programmiersprache besitzt einen derartigen Datentyp und manche Programmiersprachen arbeiten ausschließlich mit diesem Datentyp. Beispiele dafür sind sed, awk und bash.
Inhaltsverzeichnis
Repräsentation
Zeichenketten können auf verschiedenen Ebenen repräsentiert werden. Eine davon ist der Quelltext eines Programms, der vom Übersetzer gelesen und interpretiert wird. Eine andere ist, wie eine Zeichenkette zur Laufzeit eines Programms im Speicher abgelegt wird.
Syntax für Literale
Im Allgemeinen wird eine literale Zeichenkette in den Programmiersprachen durch das einfache Aneinanderfügen von Zeichen repräsentiert. Sie wird durch einfache oder doppelte Anführungsstriche eingeschlossen:
"Wikipedia"
'Dieser Satz ist eine Zeichenkette.'
"123"
""
(eine leere Zeichenkette, Leerstring)"Erste Lösung, um das Anführungszeichen " als Teil der Zeichenkette aufzunehmen."
(z. B. in C; C-Strings werden stets durch Gänsefüßchen begrenzt, ein Gänsefüßchen als Element der Zeichenkette kann trotzdem in Form einer Escape-Sequenz eingebaut werden)'Zweite Lösung, um ein '' aufzunehmen'
(Verdoppelung des Begrenzers, z. B. in Pascal oder Rexx; Pascal-Strings werden stets durch Hochkommata begrenzt)"Dritte Lösung, um ein ' aufzunehmen"
:
(Verwendung eines bzw. des anderen Begrenzers, z. B. in Rexx oder Python)
Solche Strings müssen normalerweise in einer einzigen Zeile notiert werden. In manchen Programmiersprachen wie etwa Python können jedoch Strings, die durch verdreifachte Anführungszeichen begrenzt werden, auch mehrere Zeilen umfassen.
Intern
Es gibt mehrere Verfahren, um Zeichenketten effizient abzuspeichern. Zum Beispiel kann ein Zeichen aus dem verwendeten Zeichensatz als Abschlusszeichen definiert werden. Eine Zeichenkette hört dann vor dem ersten Vorkommen dieses Zeichens auf. Eine andere Möglichkeit ist, die Länge der Zeichenkette separat zu speichern.
Repräsentation mit Abschlusszeichen
In Programmiersprachen wie C werden die Zeichenketten fortlaufend im Speicher abgelegt und mit dem Nullzeichen (NUL in ASCII) abgeschlossen. Das Nullzeichen ist das Zeichen, dessen binäre Repräsentation nur aus Nullen besteht. Das folgende Beispiel zeigt, wie eine Zeichenkette mit 5 Zeichen in einem Buffer von 10 Byte Länge abgelegt wird.
F R A N K NUL k e f w 46 52 41 4E 4B 00 6B 65 66 77 Die Länge der obigen Zeichenkette ist 5; sie benötigt aber 6 Bytes im Buffer. Buchstaben nach dem NUL-Zeichen zählen nicht mehr zur Zeichenkette; sie können zu einer neuen Zeichenkette gehören oder einfach ungenutzt sein. Eine Zeichenkette in C ist ein Array vom Typ char, wobei die Zeichenkette als Endekennung eine Null (ASCII-Zeichen NUL) enthält. Deswegen heißen solche Zeichenketten auch nullterminiert. Da das Nullzeichen selbst auch noch einen Speicherplatz benötigt, den die Zeichenkette belegt, ist der Speicherbedarf einer Zeichenkette immer mindestens 1 Zeichen größer als die nutzbare Länge der Zeichenkette. Als „Länge der Zeichenkette“ wird die Anzahl der Zeichen vor der Endekennung bezeichnet. Sie wird von der C-Funktion
strlen()
ermittelt.Der Vorteil dieser Methode ist, dass die Länge eines Strings praktisch nur durch den verfügbaren Speicher begrenzt ist; ein Nachteil ist, dass er keine Null-Zeichen enthalten kann, und dass der Umgang vergleichsweise schwierig und ineffizient ist; beispielsweise kann die Länge eines solchen Strings nur durch das Abzählen der Zeichen ermittelt werden.
Repräsentation mit separater Längenangabe
Eine andere Art, Zeichenketten abzulegen, wird in den Programmiersprachen Pascal, BASIC, PL/1 u. a. verwendet:
length F R A N K k e f w 05 46 52 41 4E 4B 6B 65 66 77 Zeichenketten, die so gespeichert werden, können eine bestimmte Länge nicht überschreiten. In Turbo Pascal wird die Länge zum Beispiel im „nullten“ Zeichen gespeichert. Da ein Zeichen 8 Bit groß ist, ist die Länge damit auf 255 Zeichen begrenzt. Die Nachfolgesprache Borland Delphi hat das Längenfeld auf 31 Bit erweitert und unterstützt Zeichenketten von bis zu 2 Gigabyte Länge. Auch in Rexx wird die Länge in vier Bytes gespeichert, wodurch die maximale Länge für die meisten praktischen Zwecke quasi unbegrenzt ist.
Noch offen: Hinweis auf MBCS/UTF-8
Basisoperationen mit Zeichenketten
Die Basisoperationen mit Zeichenketten, die in fast allen Programmiersprachen vorkommen, sind Kopieren, Ermitteln der Länge, Verketten, Bilden von Teilketten, Mustererkennung, Suchen von Teilketten oder einzelnen Zeichen.
Zum Kopieren von Zeichenketten wird in vielen höheren Programmiersprachen der Zuweisungsoperator (meist „=“ oder „:=“) benutzt. In C wird das Kopieren mit der Standardfunktion strcpy durchgeführt. Wie zeitaufwendig das Kopieren ist, hängt stark von der Repräsentation der Zeichenketten ab. Bei einem Verfahren mit Referenzzählern besteht das Kopieren nur aus dem Erhöhen des Referenzzählers. In anderen Verfahren muss eventuell die komplette Zeichenkette kopiert werden.
Zum Verketten gibt es in vielen Programmiersprachen Operatoren wie „+“ (BASIC, Pascal, Python, Java), „&“ (Ada, BASIC), „.“ (Perl, PHP) oder „||“ (REXX). In C gibt es dafür die Funktion strcat.
Um an eine bereits bestehende Zeichenkette eine andere anzufügen, stellen einige Sprachen einen eigenen Operator zur Verfügung („+=“ in Java und Python, „.=“ in Perl und PHP). Dabei wird üblicherweise der Operand nicht einfach hinten angefügt, sondern der Ausdruck alt+neu ausgewertet und der Variablen alt zugewiesen, da Strings in der Regel als unveränderlich betrachtet werden; es handelt sich also nur um eine abkürzende Schreibweise.
Direkt (mit oder ohne Whitespace) hintereinander notierte Strings werden in manchen Sprachen implizit verkettet (Python, REXX).
Um eine Teilkette zu erhalten, gibt es verschiedene Möglichkeiten. Durch die Angabe von (Zeichenkette, Startindex, Endindex) bzw. (Zeichenkette, Startindex, Länge) kann eine Teilkette eindeutig definiert werden. Diese Operation heißt häufig substr. Einige Programmiersprachen, zum Beispiel Python, bieten syntaktischen Zucker für diese Operation an (siehe Beispiele).
BASIC
text$ = "FRANK" text2$ = text$
Das nachgestellte Dollarzeichen gibt an, dass es sich um eine Zeichenkettenvariable handelt. Da ein String durch Gänsefüßchen begrenzt wird, können sie selbst nur über die
Chr(34)
- bzw.CHR$(34)
-Funktion in den String eingebaut werden, die 34 ist der ASCII-Code des Gänsefüßchens.Mehrere Zeichenketten können (je nach BASIC-Dialekt) mit dem Pluszeichen oder mit dem Kaufmanns-Und „&“ zu einer verbunden (konkateniert) werden:
text2$ = "***" + text$ + "***"
text2$ = "***" & text$ & "***"
C
Dieses C-Programm definiert zwei Zeichenketten-Variablen, die jeweils 5 Zeichen „Nutzlast“ aufnehmen können. Da Zeichenketten mit einem Nullzeichen abgeschlossen werden, muss das Array 6 Zeichen haben. Anschließend wird in beide Variablen der Text „FRANK“ kopiert.
#include <string.h> int main(void) { char text1[6]; char text2[6]; strcpy(text1, "FRANK"); strcpy(text2, text1); return 0; }
Eine einfache Methode zwei Strings aneinanderzuhängen, bietet die Standardfunktion strcat:
#include <string.h> int main(void) { char puffer[128]; strcpy(puffer, "FRANK"); strcat(puffer, "ENSTEIN"); return 0; }
Java
String text1 = "FRANK"; String text2 = text1;
Zeichenketten in Java sind Objekte der Klasse String. Sie sind nach dem Erzeugen nicht mehr änderbar. Im obigen Beispiel repräsentieren text und text2 dasselbe Objekt.
Die Konkatenation von Zeichenketten wird durch den (für diesen Fall überladenen) Plus-Operator durchgeführt:
String text1 = "FRANK"; String text2 = "ENSTEIN"; String ganzerName = text1 + text2;
Pascal
(Streng genommen funktioniert das folgende erst seit Turbo Pascal, da die ursprüngliche von Niklaus Wirth geschaffene Pascal-Sprache nur packed arrays of char kannte, die etwas umständlicher zu handhaben waren)
var s1, s2: string; (...) s1 := 'FRANK'; s2 := '***' + s1 + '***';
PHP
Bei PHP verhält es sich ähnlich wie bei Perl
$text = "FRANK"; $text2 = $text; // $text2 ergibt "FRANK"
Texte werden mit einem Punkt konkateniert.
$text = "FRANK"; $text = "FRANK" . "ENSTEIN"; // $text ergibt "FRANKENSTEIN"
$text = "FRANK"; $text .= "ENSTEIN"; // $text ergibt "FRANKENSTEIN"
Rexx
In Rexx wird alles, incl. Zahlen, als String repräsentiert. So wird einer Variablen ein String-Wert zugewiesen:
a = "Ottos Mops"
Die folgenden Ausdrücke ergeben jeweils den Wert
"Ottos Mops"
:"Ottos" "Mops"
(implizit verkettet; genau ein Leerzeichen wird automatisch eingefügt)"Ottos" || ' Mops'
(explizit verkettet, kein Einfügen eines Leerzeichens)"Ottos"' Mops'
(implizit verkettet durch unmittelbares Anfügen eines weiteren Strings, der durch das andere Begrenzungszeichen begrenzt wird)
Weitere Operationen
Substrings ermitteln
Angenommen, die Variable
s
enthalte die ZeichenketteOttos Mops hopst fort
. Dann lassen sich das erste Zeichen (O
), die ersten fünf Zeichen (Ottos
), das siebte bis zehnte (Mops
) sowie die letzten vier (fort
) wie folgt ermitteln:Python
s[0]
=> Os[:4]
oders[0:4]
=> Ottos[6:10]
=> Mopss[-4:]
=> fort
Dieses Verfahren wird Slicing (von engl. „to slice“ mit der Bedeutung „in Scheiben schneiden“ bzw. „aufteilen“) genannt. Das erste Zeichen hat den Index 0.
Rexx
SubStr(s, 1, 1)
oderLeft(s, 1)
=> OLeft(s, 4)
oderWord(s, 1)
=> OttosSubStr(s, 7, 4)
oderWord(s, 2)
=> MopsRight(s, 4)
oderWord(s, 4)
=> fort
Rexx kann Strings auch wortweise verarbeiten, wobei Wörter durch (beliebig viele) Leerzeichen getrennt werden. Das erste Zeichen hat, wie bei Pascal-Strings, den Index 1.
PARSE VAR s A 2 1 O M F
=> Variablen A,O,M,F beinhalten 'O','Ottos', 'Mops','fort'
PHP
SubStr(s, 0, 5)
=> OttosSubStr(s, 6, 4)
=> MopsSubStr(s, 0, -4)
=> fort
BlitzBasic
Left(s, 5)
=> OttosMid(s, 7, 4)
=> MopsRight(s, 4)
=> fort
Algorithmen
Verschiedene Algorithmen arbeiten vorwiegend mit Zeichenketten:
- String-Matching-Algorithmen überprüfen ob eine Zeichenkette Teil einer größeren Zeichenkette ist.
- Bestimmen von Teilzeichenketten, die mit einem regulären Ausdruck beschrieben sind.
- Sortieralgorithmen
- Parser
- Codeumwandlungen (Unicode, usw.)
Heute schreibt ein Programmierer diese Art Algorithmen meist nicht mehr selbst, sondern benutzt Konstrukte einer Sprache oder Bibliotheksfunktionen.
Zeichenketten und Computersicherheit
Zu den häufigsten Fehlerquellen und damit zu der häufigsten Angriffsquelle auf Servern zählen Pufferüberläufe. Dabei wird versucht, einer Zeichenkettenvariablen einen Inhalt zuzuweisen, dessen Länge die Länge der Variablen übersteigt. Dadurch werden andere, benachbarte Variablen im Speicher überschrieben. Bei geschickter Ausnutzung dieses Effekts kann ein auf einem Server laufendes Programm manipuliert und für Angriffe auf den Server missbraucht werden.
Zur sicheren Programmierung sollten Zeichenketten-Operationen nur mit Funktionen durchgeführt werden, bei denen die maximale Länge der Zeichenkette überprüft wird. In C wären das Funktionen wie z. B.
strncpy()
,snprintf()
, … (anstelle vonstrcpy()
,sprintf()
, …).Weblinks
Wikimedia Foundation.