Grundlagen: String-Typen (Artikel im Pascalmagazin)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

Hallo!
Vor wenigen Monaten wurde das Pascalmagazin.de online gestellt, ein Schwesterprojekt vom Lazarusforum.
Im Pascalmagazin sollen Tipps+Tricks und andere Artikel zum Thema Programmieren mit Pascal veröffentlicht werden, natürlich mit Schwerpunkt FreePascal und Lazarus.

Vorgestern ist mein erster Artikel online gegangen, der die verschiedenen String-Typen beschreibt - als Grundlage für Anfänger und um Unterschiede nachlesen zu können.
https://pascalmagazin.de/grundlagen/str ... in-pascal/

Dieser Forums-Thread soll zur Diskussion über den String-Typen-Artikel dienen, wenn jemand Kritik äußern will, Ergänzungen oder Verbesserungsvorschläge hat.
Oder wenn z.B. jemand Rückfragen zum Thema Strings hat, weil die Beschreibung im Artikel unklar oder nicht ausführlich genug ist.

Diesen Thread werde ich nacher auch unter dem Artikel verlinken.
Grüße, Jörg

Mathias
Beiträge: 7206
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Mathias »

Pascal hat so viele strings, aber eine echtte Alternative zum C wchar_t fehlt. In Linux ist dieser 4Byte und unter Windows 2Byte.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

Mathias hat geschrieben: Fr 13. Feb 2026, 17:11 Pascal hat so viele strings, aber eine echtte Alternative zum C wchar_t fehlt. In Linux ist dieser 4Byte und unter Windows 2Byte.
Das ist leider so.
Den UCS4String (4 Byte pro Zeichen) in Pascal habe ich im Artikel erwähnt ... https://pascalmagazin.de/grundlagen/str ... UCS4String
... aber leider wird er nicht so unterstützt wie die nativen Pascal-Strings.
Der UCS4String ist lediglich ein Array of UCS4Char (32 Bit) und kann nicht wie ein normaler String in den bekannten Funktionen genutzt werden.

Ich habe mal eine Unit programmiert, um zumindest den Umgang mit UCS4String zu vereinfachen, aber die Unit habe ich bisher noch nicht veröffentlicht.
Es wird in Pascal wohl eh nur ein Nischenthema bleiben.

siro
Beiträge: 779
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von siro »

Ersteinmal vielen Dank für den Artikel.
Das gibt eine gute Übersicht der verschiedenen String Varianten.

Als alter Pascaller fand ich den ürsprüngliche String garnicht schlecht.
Ein Längenbyte und dann die entsprechenden Ascii Character (jeweils ein Byte)
Die Funktion Length war natürlich blitzschnell, da nur das Nullte Byte aus dem Array gelesen werden musste.

Fürchterlich fand(find) ich das bei "C". Nullterminierter String:
Man muss sich komplett "durchhangeln" bis man auf eine Nullbyte trifft.

Dann kommt das UTF8, wobei hier ein einzelnes Zeichen in 1 bis 4 Bytes untergebracht ist.
Upps, das wir jetzt echt komplex wenn man Bytes z.B. aus einem Stream liest.
Wenn ich das richtig verstanden habe, kann man anhand des ersten Bytes erkennen ob das Zeichen 1,2,3 oder 4 Bytes belegt.
Hierfür gibt es wohl bestimmte Bitmuster.

Die Strings sind wirklich ein SEHR komplexes Thema.
Meist brauche ich mich aber garnicht darum kümmern und da bin natürlich nicht traurig drüber.

Var s:String;
caption:=s;

Das funktioniert einfach, ohne dass ich mir da Gedanken machen muss.

Beispiel:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var s:UnicodeString;    // egal welchen Stringtyp ich wähle, es funktioniert mit allen
begin
  s:='Hallo';
  caption:=s;
end;
Welchen Typ nimmt man aber nun für seine Anwendung ?
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

siro hat geschrieben: Fr 13. Feb 2026, 18:19 Welchen Typ nimmt man aber nun für seine Anwendung ?
Am besten einfach immer String!
Alle anderen Typen braucht man nur in Ausnahmefällen
- meistens nur dann, falls man sich low-level um Datenübertragung und Textkodierung kümmern will/muss.
siro hat geschrieben: Fr 13. Feb 2026, 18:19 var s: UnicodeString; // egal welchen Stringtyp ich wähle, es funktioniert mit allen
Jein, aber Vorsicht!

Code: Alles auswählen

var s: UnicodeString;
begin
  s:='Ein Inhalt nicht nur mit ASCII, sondern z.B. mit Umlauten ä ö ü'.;
  Label1.Caption:=s;  // dies könnte schief gehen
end;
Es kommt dann ... Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "TTranslateString".
Ich habe es gerade mal getestet und es hat auch mit Umlauten funktioniert (obwohl ich gedacht hätte, es würde nicht funktionieren).
Zumindest zeigt die Warnung, dass man hier nicht sicher sein kann und man nicht wahllos irgendeinen String-Typen nehmen sollte, sondern im Normalfall bei String bleiben sollte.
Zuletzt geändert von Jorg3000 am Fr 13. Feb 2026, 19:19, insgesamt 2-mal geändert.

Mathias
Beiträge: 7206
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Mathias »

Der UCS4String ist lediglich ein Array of UCS4Char (32 Bit) und kann nicht wie ein normaler String in den bekannten Funktionen genutzt werden.
Dies ginge ja noch, noch schlimmer es ist ein Integerwert,

Code: Alles auswählen

  UCS4Char            = 0..$10ffff;
  PUCS4Char           = ^UCS4Char;
{$ifdef CPU16}
  TUCS4CharArray      = array[0..32767 div sizeof(UCS4Char)-1] of UCS4Char;
{$else CPU16}
  TUCS4CharArray      = array[0..$effffff] of UCS4Char;
{$endif CPU16}
  PUCS4CharArray      = ^TUCS4CharArray;
{$ifdef FPC_HAS_FEATURE_DYNARRAYS}
  UCS4String          = array of UCS4Char;
{$endif}
somit gibt es in Pascal leider keinen echten 4Byte String, welche zu wchar_t unter Linux kompatibel ist, unter Windows kann man einfach den Pascal WideString nehmen,
Fürchterlich fand(find) ich das bei "C". Nullterminierter String:
Man muss sich komplett "durchhangeln" bis man auf eine Nullbyte trifft.
Der ist halt einiges nativer als der Pascal String oder die dynamischen Arrays. Er hat kein LängenByte.
Dafür weis man beim PChar, was damit dem passiert. Beim Pascal String ist viel magie dahinter.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 7206
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Mathias »

Am besten einfach immer String!
Alle anderen Typen braucht man nur in Ausnahmefällen
- meistens nur dann, falls man sich low-level um Datenübertragung und Textkodierung kümmern will/muss.
Wen man gewisse C-lib anspricht braucht man solche Exoten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

Mathias hat geschrieben: Fr 13. Feb 2026, 18:59 noch schlimmer es ist ein Integerwert,
UCS4Char = 0..$10ffff;
Doch doch, das ist kompatibel, denn obwohl der Wert bis $10ffff in 3 Byte passen würde, wird es als 4-Byte-Integer im Speicher abgelegt.
Und am Ende eines UCS4String gibt es auch einen Null-Terminator (ebenfalls 32 Bit).
Die Zahl $10ffff stammt aus der Unicode-Spezifikation, d.h. in diesem Wertebereich befinden sich alle gültigen Unicode-Zeichen.
Zuletzt geändert von Jorg3000 am Fr 13. Feb 2026, 20:20, insgesamt 1-mal geändert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 7142
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von af0815 »

Meiner Meinung nach ist
Meiner Meinung nach ist das ein Compiler-Fehler, ....
hier nicht unbedingt gebraucht. Wenn man mit Core-Entwicklern diskutiert kommt immer raus: "It's per design", "it's Delphi compatible" oder "won't fix". Copyrigth der Aussagen liegt bei MvC.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

Meiner Meinung nach ist das ein Compiler-Fehler, ....
Hier habe ich mich zwischenzeitlich selber korrigiert, denn ich habe die Zuweisung String := UnicodeString vorhin nochmal anders ausprobiert - und da hat es dann doch mit Umlauten richtig funktioniert.
Dann wäre aber die Compiler-Warnung überflüssig. Hmm, keine Ahnung, ob es unter Umständen ein Problem sein könnte oder nicht.

siro
Beiträge: 779
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von siro »

Probleme handelt man sich recht schnell ein, wenn man die Funktion "length" benutzt:

Folgender Code gibt unterschiedliche Ergebnisse:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  s:='äöü';
  caption:=IntToStr(length(s));
end;  
Ich habe mal die folgenden Typen für den String s probiert:

Code: Alles auswählen

var s:Array of Char;  // Ergebnis 6
var s:String;         // Ergbenis 6
var s:ShortString;    // Ergebnis 6
var s:UTF8String;     // Ergebnis 12
var s:ShortString;    // Ergebnis 6
var s: UnicodeString; // Ergebnis 6
var s: WideString;    // Ergebnis 6
var s: UnicodeString; // Ergebnis 6

var s: UCS4String;    // geht garnicht...
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 432
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Jorg3000 »

siro hat geschrieben: Fr 13. Feb 2026, 23:43 wenn man die Funktion "length" benutzt
Achtung: Man darf UTF8String und UnicodeString/WideString nicht einfach eine Konstante zuweisen.
Das ist die Unstimmigkeit, die ich gestern zunächst als Compiler-Bug bezeichnet hatte. Ob es Bug oder Feature ist, weiß ich nicht.

Macht man es über einen Umweg, nämlich die Konstante erst einer String-Variablen zuzuweisen, dann die String-Variable an einen anderen Typ übergeben, funktioniert die Konvertierung richtig.

Bei UTF8String ist dann die Länge ebenfalls 6, und bei UnicodeString/WideString ist die Länge dann 3 - wie zu erwarten.

Und einen UCS4String muss man aus einem UnicodeString erzeugen, per UnicodeStringToUCS4String(), wobei der UnicodeString auch zunächst erst korrekt befüllt werden musste, siehe oben.
Die Länge des UCS4String erhält man ebenfalls über Length() aber abzüglich 1, weil man den NULL-Terminator abziehen muss. Allerdings liefert ein leeres Array das Ergebnis -1.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 7142
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von af0815 »

Wird das Wissen immer mit der offiziellen Compiler Dokumentation abgeglichen ? Weil dort wird doch vieles von den Besonderheiten erklärt bzw. definiert.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

siro
Beiträge: 779
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von siro »

Guten Morgen,
ich habe eben noch folgendes probiert:

Code: Alles auswählen

uses.....,LazUTF8;   // Hier ist die funktion UTF8Length implementiert 

var
    // s:string;            // 3
    // s:Array of Char;     // UTF8Length geht nicht
    // s:ShortString;       // 3
    // s:UTF8String;        // 6
    // s:ShortString;       // 3
    // s:UnicodeString;     // 6
    // s:WideString;        // 6
    s: UnicodeString;       // 6


procedure TForm1.FormCreate(Sender: TObject);
begin
  s:='äöü';
  caption:=IntToStr(UTF8Length(s));
end;
Ich dachte wenn ich UTF8String nehme, dann sollte UTF8Length auch funktionieren ? dem ist aber nicht so.

Ich finde es wirklich kompliziert die Länge eines Strings zu ermitteln.
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Mathias
Beiträge: 7206
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Grundlagen: String-Typen (Artikel im Pascalmagazin)

Beitrag von Mathias »

var s:UTF8String; // Ergebnis 12
Der ist ja echt speziell, ich hätte da auch 6 erwartet. Aber der ist wirklich 12.
Entspricht dies der UTF8 Norm ?

Ich habe es gerade getestet:

Code: Alles auswählen

var
  s8: utf8string = 'öäü';
  s: string = 'öäü';
  i: integer;
begin
  for i := 1 to Length(s) do begin
    WriteLn(byte(s[i]));
  end;
  WriteLn();
  for i := 1 to Length(s8) do begin
    WriteLn(byte(s8[i]));
  end;
  WriteLn(#10);
  s := 'abc';
  s8 := 'abc';
  for i := 1 to Length(s) do begin
    WriteLn(byte(s[i]));
  end;
  WriteLn();
  for i := 1 to Length(s8) do begin
    WriteLn(byte(s8[i]));
  end;
end.               
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten