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 |
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.
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."'Zweite Lösung, um ein '' aufzunehmen'"Dritte Lösung, um ein ' aufzunehmen":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.
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.
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.
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
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).
text$ = "FRANK"
text2$ = text$
Das nachgestellte Dollarzeichen gibt an, dass es sich um eine Zeichenkettenvariable handelt. 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$ & "***"
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;
}
String text = "FRANK";
String text2 = text;
Zeichenketten in Java sind Objekte der Klasse String. Ihre Länge ist nach dem Erzeugen nicht mehr änderbar. Im obigen Beispiel repräsentieren text und text2 dasselbe Objekt. Die Anführungszeichen-Schreibweise ist lediglich eine Kurzform. So steht „foobar“ intern für new String(char[] stringinhalt)
Die Konkatenation von Zeichenketten wird durch den (für diesen Fall überladenen) Plus-Operator durchgeführt:
String text = "FRANK";
String text2 = "ENSTEIN";
String ganzerName = text+text2;
(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 + '***';
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"
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""Ottos" || ' Mops'"Ottos"' Mops'Angenommen, die Variable s enthalte die Zeichenkette Ottos 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:
s[0] => Os[:4] oder s[0:4] => Ottos[6:10] => Mopss[-4:] => fortDieses Verfahren wird Slicing (von engl. „to slice“ mit der Bedeutung „in Scheiben schneiden“ bzw. „aufteilen“) genannt. Das erste Zeichen hat den Index 0.
SubStr(s, 1, 1) oder Left(s, 1) => OLeft(s, 4) oder Word(s, 1) => OttosSubStr(s, 7, 4) oder Word(s, 2) => MopsRight(s, 4) oder Word(s, 4) => fortRexx 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'SubStr(s, 0, 5) => OttosSubStr(s, 6, 4) => MopsSubStr(s, 0, -4) => fortLeft(s, 5) => OttosMid(s, 7, 4) => MopsRight(s, 4) => fortVerschiedene Algorithmen arbeiten vorwiegend mit Zeichenketten:
Heute schreibt ein Programmierer diese Art Algorithmen meist nicht mehr selbst, sondern benutzt Konstrukte einer Sprache oder Bibliotheksfunktionen.
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 von strcpy(), sprintf(), …).