String-Typen
Unterschiedliche String-Typen
In Delphi gibt es verschiedene Möglichkeiten, Strings zu deklarieren:
- String
- ShortString
- AnsiString
- WideString
- Array[0..x] of Char
- PChar
In diesem Abschnitt soll es darum gehen, welchen Typ man wann benutzt und wie sie sich überhaupt voneinander unterscheiden.
Pascal-Strings
Zunächst muss nach Delphi-Version unterschieden werden. Den Datentyp String gibt es in Pascal schon immer, jedoch hat sich mit der Umstellung auf 32 Bit (Delphi 2) und bei .NET sein Aufbau verändert.
In den 16-Bit-Versionen (bis Delphi 1) bestand ein String aus maximal 255 Zeichen, für den statisch Arbeitsspeicher reserviert wurde. Im ersten Byte des Strings befand sich die Längenangabe. Mit Delphi 2 hat sich das geändert, der alte String-Typ kann trotzdem noch verwendet werden, sein Typ ist ShortString:
Ebenso wird ein String als ShortString angesehen, wenn man ihm bei der Deklaration eine feste Länge verordnet:
Die "altmodische", aus DOS-Tagen stammende Begrenzung auf 255 Zeichen wurde mit Delphi 2 aufgehoben. Wird seitdem in Win32 eine Variable vom Typ String deklariert, handelt es sich um einen AnsiString. Die Besonderheit hiervon ist, dass es sich bei der Variable nur noch um einen Zeiger auf eine Stelle im Arbeitsspeicher handelt, die dynamisch vergeben wird. Der String kann somit (rein theoretisch) bis zu 2 GB groß werden, wobei sich der Speicherverbrauch automatisch der String-Länge anpasst. Enthält der String keine Zeichen, verbraucht er auch keinen Speicherplatz, abgesehen von 4 Byte für den Zeiger auf nil, also ins Leere. AnsiStrings enden mit einem Nullzeichen (#0), sind also voll kompatibel zu nullterminierten Strings, wie sie manchmal von API-Funktionen gefordert werden.
WideStrings werden in der .NET-Umgebung als Standard-String verwendet, existieren aber auch schon in früheren Delphi-Versionen. Sie bieten jedoch pro Zeichen zwei statt einem Byte Speicher, sind also Unicode-tauglich. AnsiStrings mit einem Byte pro Zeichen können nur Ansi-Zeichen aufnehmen. Mit Unicode sollen jedoch alle Schriftzeichen der Welt dargestellt werden können, weshalb auf zwei Byte pro Zeichen umgestellt wurde. WideStrings werden wie AnsiStrings dynamisch verwaltet. Unter Win32 unterliegen WideStrings nicht der Referenzzählung. Unter Linux und .NET jedoch schon.
Grundsätzlich ist es angebracht, in eigenen Programmen immer den generischen Typ String zur Deklaration von Strings zu verwenden. Kurze Strings (ShortString) sollten wegen ihrer statischen Größe nur in bestimmten Fällen (z.B. Datenaustausch mit DLLs) verwendet werden oder der Speichbedarf bekannt ist und deshalb auf den Verwaltungsaufwand für die Speicherverwaltung von AnsiStrings verzichtet werden kann.
Nullterminierte Strings
Die folgenden String-Typen sind innerhalb eines normalen Delphi-Programms nicht erforderlich, gelegentlich werden sie jedoch zur Kommunikation mit der "Außenwelt", der in C++ geschriebenen Win32-API benötigt.
Bei nullterminierten Strings handelt es sich um Zeichenketten, die ihr Ende durch eine ASCII-Null (#0) kennzeichnen. Man deklariert sie so:
Da es sich hierbei um keine normalen Pascal-Strings handelt, müssen solche nullterminierten Strings mit speziellen Funktionen bearbeitet werden, z.B. StrPCopy, um einen Pascal-String in einen nullterminierten String zu kopieren.
Bei PChar handelt es sich um einen Zeiger auf ein C-kompatibles Zeichenarray. Dieser Typ wird von einigen API-Funktionen gefordert. Man erhält ihn ganz einfach, indem man einen AnsiString mittels PChar(langerText) umwandelt.
Arbeiten mit Pascal-Strings
Die Arbeit mit den anfangs erwähnten Pascal-Stings (ShortString, AnsiString, WideString) ist recht einfach:
Zeichenketten zusammenhängen
begin
text1 := 'toll';
text2 := 'Ich finde Delphi '+text1+'!!';
// text2 enthält nun den Text 'Ich finde Delphi toll!!'
Zugreifen auf ein bestimmtes Zeichen eines Strings
Der Zugriff auf ein einzelnes String-Zeichen erfolgt über dessen Index:
var text: String;
zeichen: Char;
begin
text := 'Ich finde Delphi toll!';
zeichen := text[1];
// zeichen enthält nun den Buchstaben 'I'
Vergleich zweier Strings
Das Vergleichen von zwei Strings erfolgt mit dem Gleichheitszeichen. Dabei wird Groß- und Kleinschreibung beachtet.
var text1, text2: string;
...
if text1 = text2 then ...
Die Delphi-Laufzeitumgebung bietet noch einige weitere Funktionen, z.B. AnsiCompareText zum Vergleich zweier AnsiStrings ohne Berücksichtigung der Groß- und Kleinschreibung. pos hilft beim Auffinden eines Teilstrings; copy zum Kopieren eines Teilstrings und delete zum Löschen eines Teilstrings sind ebenfalls wichtige Bearbeitungsmöglichkeiten.
Arbeiten mit .NET-Strings
Zur effektiven Arbeit mit Strings unter .NET bietet das .NET-Framework die Klasse StringBuilder (Namensraum System.Text). Das Zusammenfügen mehrerer Strings sollte unter .NET nicht mit dem Plus-Operator erfolgen, sondern so:
uses System.Text;
var s1, s2: string;
sb: StringBuilder;
begin
s1 := 'Hallo';
s2 := 'Delphi';
sb := StringBuilder.Create(s1);
s1 := sb.Append(s2).ToString;
Hintergrund: Strings sind unter .NET unveränderbar. Wenn zwei Strings zu einem verbunden werden soll bedeutet das, dass Speicher für den neuen String reserviert werden muss, dann werden die beiden alten Strings in den neuen kopiert und der Speicher der alten Strings freigegeben. Das ist Aufwand, der sich bei Verwendung der StringBuilder-Klasse reduziert.
