Umlaute in C



  • Hi(gh)!

    Und weiter geht es mit ERLENKÖTTER, Helmut: C - Programmieren von Anfang an... auf Seite 60 ist in den erklärenden Anmerkungen zum Programmskript "bspl0019.c" zu lesen, dass die (in ctype.h enthaltenen) Funktionen toupper() und tolower() mit Umlauten (das große ẞ gab es damals noch nicht) nicht funktionieren... das fand ich interessant und wollte es dann gleich mal ausprobieren:

    #include <stdio.h>
    #include <ctype.h>
    
    main()
    {
      char eingabe;
      printf("\nGeben Sie ein deutsches Sonderzeichen als Großbuchstabe ein (Umlaut oder ẞ): ");
      scanf("%c",&eingabe);
      if ( !(eingabe =='Ä' || eingabe=='Ö' || eingabe=='Ü' || eingabe=='ẞ'))
        printf("Dies war leider kein passendes Zeichen!\n");
      else
      {  
        eingabe=tolower(eingabe);
        printf("\nIhre Eingabe als Kleinbuchstabe: %c\n",eingabe);
      }
    }
    

    Beim Komplieren (im C90-Modus) wirft gcc vier Warnmeldungen (jeweils mit unterschlängeltem Sonderzeichen):

    warning: multi-character character constant [-Wmultichar]
    12 | if ( !(eingabe =='Ä' || eingabe=='Ö' || eingabe=='Ü' || eingabe=='ẞ'))

    und wenn ich das Programm dann starte, wird die if-Bedingung auch bei Eingabe von Ä, Ö, Ü oder ẞ nie falsch!

    Multi-character constant: klar, das sind Zeichen, die anders als Standard-ASCII mit mehr als einem Byte kodiert sind... was hat es mit dem Kommandozeilen-Switch -Wmultichar auf sich?

    Bis bald im Khyberspace!

    Yadgar



  • Die Textkodierung wird durch die C Norm nicht festgelegt, da so ziemlich jede Plattform eine eigene Kodierung nutzte. IBMs Mainframes nutzen die EBCDIC Kodierung andere nutzten ASCII. ASCII definiert aber nur Zeichen für US Englisch in den unteren 7Bit eines Bytes, so dass es verschiedene DOS Codepages gibt, für die Kodierung der jeweiligen Sonderzeichen der anderen Sprachen innerhalb dieser unteren 7Bit. ISO hat dann 8Bit Kodierungen für die wichtigsten Sprachen definiert. UNIX nutzt als Standard ISO-Latin-1 8859-1, was das Umstellen der Codepages für „den Westen“ ersparte. ISO 8859-15 (bzw. ISO Latin-9) ist die Variante mit dem Euro-Zeichen. Windows nutzte hingegen eine daran angelehnte Kodierung, die aber nicht exakt gleich war.

    • Du musst festlegen für welche Plattform Du das Programm schreiben willst.
    • Die Textdatei muss entsprechend kodiert abgespeichert werden.
    • Wahrscheinlich musst Du auf der Kommandozeile die Locales anpassen, so dass das auch korrekt interpretiert wird.

    Neue Texteditoren verarbeiten Text als Unicode und speichern ihn meist als UTF-8 ab. Hier solltest Du darauf achten, dass das in der passenden Kodierung geschieht.



  • Der von Dir hier gepostete Code enthält das große ẞ, was in ISO-Latin-1 nicht kodierbar ist.



  • @Yadgar
    Vorausgesetzt du arbeitest in einer UTF-8-Umgebung: "Ä" ist entweder die UTF-8-Sequenz 0xC3 0x84 (Unicode: Ä - LATIN CAPITAL LETTER A WITH DIAERESIS) oder 0x41 0xCC 0x88 (Unicode: A + ◌̈ - LATIN CAPITAL LETTER A + COMBINING DIAERESIS).

    Wenn man einem char-Literal wie in diesem Fall mehrere Zeichen zuweist (z.B. char c = 'ABC';) dann gibt es erstens diese Warnung und was für ein char daraus letztendlich gemacht wird, ist soweit ich weiß "implementation-defined".

    Meines Wissens dürfte z.B. ein GCC die beiden Zeichen als int interpretieren, also entweder der int 0xc384 oder 0x41cc88. Dieser wird dann bei der Zuweisung in einen char konvertiert, d.h. die führenden Bits werden einfach "abgeschnitten". Also entweder 0x84 oder 0x88.

    Im Windows-1252 oder ISO-8859-1-Zeichensatz dürften das die Zeichen „ und ˆ sein. Die kannst du ja mal ausprobieren. Aber ohne Garantie, weil eben "implementation defined" und auch noch stark abhängig vom Zeichensatz der Konsole und der .c-Datei 😉



  • @Finnegan sagte in Umlaute in C:

    Wenn man einem char-Literal wie in diesem Fall mehrere Zeichen zuweist (z.B. char c = 'ABC';) dann gibt es erstens diese Warnung und was für ein char daraus letztendlich gemacht wird, ist soweit ich weiß "implementation-defined".

    Der Grund ist, dass es damals keinerlei Festlegung gab wie groß ein char sein musste. Mein persönliches historisches Lieblingsbeispiel ist UNICOS. Da ist ein char 64Bit groß. Die Single UNIX Spec definiert später ein charals immer 8Bit groß. Aber das sind Festlegungen außerhalb der ISO C Norm.



  • @john-0 sagte in Umlaute in C:

    Der Grund ist, dass es damals keinerlei Festlegung gab wie groß ein char sein musste. Mein persönliches historisches Lieblingsbeispiel ist UNICOS. Da ist ein char 64Bit groß. Die Single UNIX Spec definiert später ein charals immer 8Bit groß. Aber das sind Festlegungen außerhalb der ISO C Norm.

    Das spielt sicher auch mit rein, aber sollte dann z.B. 'A' nicht eher für einen 64-bit Integer stehen, z.B. 0x0000000000000041? Nach dem Schema für char-Literale mit mehreren Zeichen müsste da auch der Code für entweder das erste oder das letzte Zeichen rauskommen (denke auch noch von Endianness abhängig).

    Ansonsten: Ich hab ich in meinem Beitrag auch noch eine "UTF-8-Umgebung" erwähnt. Mir kommt grad noch in den Sinn, dass z.B. unter Windows die Konsole primär mit UTF-16 arbeitet. Das macht es nochmal etwas komplizierter abzuschätzen, was bei dem Programm wirklich passiert. Eventuell kann man nämlich wirklich kein Zeichen eingeben, bei dem die Bedingung greift (keinen Nerv grad zu überlegen, mit welcher Eingabe man da "tricksen" könnte. Das da oben reicht mir für heute 😉 ).


Anmelden zum Antworten