UpperCase international

Groß im Vergleich: Case-Sensitivity von Ä bis Eszett

Ein Artikel von Jörg Rosenthal.
Getestet mit Lazarus 3.2 | FPC 3.2.2

In den wenigsten Fällen werden die Funktionen Upper– und Lower­Case ge­nutzt, um eine ge­wün­schte Form von Groß- und Klein­schrei­bung wirk­lich auf dem Bild­schirm aus­zu­geben. Häufig wird es ver­wen­det, um einen case-insensi­ti­ven Ver­gleich durch­zu­führen…

s := Trim( Edit1.Text );
if LowerCase(s) = 'start' then (* ...*) ;

Hat ein Anwender mit aktivierter Fest­stell­taste „sTART“ ein­ge­hämmert, kommt er in diesem Fall wegen des case-insensi­ti­ven Ver­gleichs trotz­dem weiter.

Neben bekannten Funktionen wie UpperCase und AnsiUpper­Case findet man in der Unit LazUTF8 überraschen­der­weise weite­re Funktio­nen, die mit „UTF8-“ be­ginnen: UTF8UpperCase, UTF8LowerCase und UTF8StringReplace. Wir schauen uns einmal die Ergebnisse an …

CodeErgebnisBemerkung
UpperCase('Süße')SüßEkleines ü und ß
AnsiUpperCase('Süße')SÜSSEnicht SÜẞE
UTF8UpperCase('Süße','de')SÜSSEnicht SÜẞE
AnsiLowerCase('SÜSSE')süsse
AnsiLowerCase('SÜẞE')süßeaus Groß-ẞ wird Klein-ß
UTF8LowerCase('SÜẞE','de')süßeaus Groß-ẞ wird Klein-ß

Die Beispiele demonstrieren mehrere Aspekte:

  1. UpperCase bzw. LowerCase küm­mern sich nur um ASCII-Buch­sta­ben, aber nicht um Umlaute.
  2. Umlaute und Eszett werden in der Ansi-Version AnsiUpper­Case berück­sich­tigt – man be­nö­tigt also für die deut­sche Sprache kein speziel­les UTF8Upper­Case.
  3. Doppel-S: In AnsiUpperCase und UTF8Upper­Case wird das kleine „ß“ durch Doppel-S er­setzt. Diese Er­set­zung wurde spe­ziell für die deutsche Sprache imple­men­tiert, denn das Eszett wird aus­schließ­lich im Deut­schen ver­wen­det.
    Leider kann die Ersatz­schrei­bung „SS“ nicht ein­fach per AnsiLower­Case rück­gängig ge­macht wer­den, weil nicht jedes Doppel-S zu einem Eszett wird, z.B. bei „WASSER“ zu „Wasser“.

Das große „ẞ“ ist seit 2017 Bestand­teil der offi­ziel­len Recht­schrei­bung und wird seit 2020 an­stelle des Doppel-S empfoh­len. Diese Empfeh­lung wird jedoch in FreePascal noch nicht um­ge­setzt. Aber die Um­wand­lung von Groß-ẞ zu Klein-ß funk­tio­niert pro­blemlos.

Umlaute und Eszett richtig vergleichen

Möchte man Wörter mit ä,ö,ü mitein­ander ver­glei­chen, genügt es die ANSI-Variante AnsiLower­Case oder AnsiUpper­Case zu ver­wen­den, welche die Umlaute be­rück­sich­ti­gen. Auch das Eszett wird be­rück­sich­tigt, jedoch ist dabei Vor­sicht ge­boten…

s := Trim( Edit1.Text );
if AnsiLowerCase(s) = 'anstoßen' then (* ... *);

          (* oder *)

s := Trim( Edit1.Text );
if AnsiUpperCase(s) = 'ANSTOSSEN' then (* ... *);

Beide if-Vergleiche funktionie­ren, wenn der Anwen­der „anstoßen“ oder „An­stoßen“ ein­gibt. Ist der Anwen­der jedoch in der Schweiz, wo kein „ß“ ver­wen­det wird, gibt er wahr­schein­lich ganz korrekt „an­stossen“ ein – und dann schlägt der erste Ver­gleich fehl, weil ein „ß“ er­wartet wird. Der zweite Vergleich funktio­niert jedoch für alle Schreib­weisen und ist des­halb vor­zu­ziehen! Der Claim am Anfang dieses Artikels „Groß im Ver­gleich“ dient hier als Merk­satz.

Anpassung an Türkisch

Es überrascht, in der Lazarus-Unit LazUTF8 die Funktio­nen UTF8Lower­Case, UTF8Upper­Case und UTF8String­Replace zu fin­den, denn auch AnsiUpper­Case, AnsiLower­Case und StringReplace leis­ten an­schei­nend alles, was man braucht.

Die UTF8-Varian­ten haben jedoch einen optio­nalen Extra-Para­meter für die Sprache des Textes, z.B. ‚tr‘ als Sprach­code für Türkisch. Der Grund ist, dass im Tür­ki­schen der Buch­stabe „i“ in zwei Varian­ten exis­tiert, was die Ansi-Funktio­nen nicht be­rück­sich­ti­gen. Diese Sonder­behand­lung wird nur durch­ge­führt, wenn ‚tr‘ oder ‚az‘ als Sprache an­ge­geben ist. Und UTF8String­Replace be­zieht diese Be­sonder­heit bei der Option rfIgnoreCase eben­falls mit ein.

if UTF8UpperCase('istanbul', 'tr') = 'İSTANBUL' then (* ... *); 

Nur die UTF8-Funktion mit der Sprach­code-Angabe ‚tr‘ macht aus dem ersten Zeichen „i“ das im Türki­schen richtige „İ“ (groß und mit Punkt) und aus einem kleinen „ı“ (ohne Punkt) ein „I“.

Bezüglich der Benennung der Funktio­nen als „UTF8-„: Das Thema Groß- und Klein­schrei­bung hat eigent­lich über­haupt nichts mit der UTF-8-Kodie­rung zu tun, sondern be­dient eher die Internatio­na­li­sie­rung. Man hätte die An­pas­sung für das tür­ki­sche „i“ ebenso gut in UTF-16-Funktio­nen für UnicodeString ein­bauen kön­nen (wo sie nun feh­len), aber in Laza­rus ist UTF-8 der Stan­dard, wes­halb sich wohl die Ent­wick­ler der Unit LazUTF8 der Sache an­ge­nom­men haben.

Geschichtliches
Ursprüng­lich gab es im latei­ni­schen Alpha­bet nur die Buch­staben, die wir heute als Groß­buch­staben kennen und als Majuskeln (lateinisch: capitalis) be­zeich­net werden. Die Klein­buch­staben (Minuskeln) wurden ab dem Früh­mittel­alter ent­wor­fen, denn in Klöstern hatte man den Wunsch, mit Schreib­federn schneller schrei­ben zu kön­nen. Deshalb wurde die Schreib­schrift ent­wickelt, in der über­wiegend die ge­schwun­ge­nen und ver­bun­de­nen Minuskeln ver­wen­det werden.


Für Setzereien (Buchdruck) und seit der Ein­füh­rung von Schreib­maschinen sind die zusätz­lichen Klein­buch­staben eigent­lich kein Vor­teil mehr. Aller­dings sind die Minuskeln nicht nur seit tausend Jahren eta­bliert, sondern auch beim Lesen nütz­lich: die Klein­buch­staben ver­bessern die Les­bar­keit langer Texte ganz deut­lich. Und speziell im Deut­schen, wo Substan­tive mit einem Groß­buch­staben be­gin­nen, gibt es zudem einen kleinen Vor­teil durch schnel­leres Er­kennen wich­ti­ger Wörter im Text.

Übrigens, der Begriff „upper case“ bezog sich in einer Setze­rei auf das obere Fach des Setz­kastens, wo die großen Druck­lettern auf­bewahrt wur­den. Das „lower case“ war das untere Fach mit den klei­nen Lettern.

Fazit zu AnsiUpperCase

Bewegt man sich mit seinem Programm sprach­lich nur im west­europä­ischen Raum, genügt AnsiUpper­Case für case-insensi­tive Ver­gleiche. Ob sich die Ansi-Variante auch zu­ver­läs­sig z.B. für das grie­chi­sche oder kyril­li­sche Alpha­bet eignet, konnte ich noch nicht in Er­fah­rung brin­gen.
Wenn man Texte auf internationa­ler Ebene ver­arbei­tet, sollte man sicherheits­halber auf UTF8Upper­Case zurück­grei­fen. Allerdings ergibt das nur Sinn, wenn man den Sprach­code, z.B. ‚tr‘, des je­weili­gen Text-Inhalts kennt, denn sonst ver­hält sich UTF8Upper­Case nicht anders als AnsiUpper­Case.