Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller und Codepages


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

ich ärgere mich gerade über die mangelnde Darstellung von Umlauten und 
Sonderzeichen auf meinem Mikrocontrollerprojekt. Darstellung/Schriftart 
sind ein anderes Thema - hier angesprochen: 
Beitrag "Grafik-LCD: Schriftarten mit Umlauten/Sonderzeichen" - jetzt geht es mir um die 
konkrete Umsetzung zwischen den Zeichenketten im Flash und der 
Darstellung auf dem Display.

Bislang habe ich eine eigene Codepage-Funktion verwendet, die von putc() 
aufgerufen wurde. Für alles zwischen 'A' 'Z' wurde einfach der 
entsprechende Offset für das Array mit den Zeichensatzdaten addiert. 
Zeichen darüber (Umlaute, 'ß', 'µ' etc.) wurde mit einer länglichen 
switch-case-Orgie der entsprechende Array-Eintrag oder der Eintrag des 
Ersatzzeichens (Rechteck) zugeordnet.

Für die Textstrings selbst habe ich darauf geachtet, daß meine 
Quelltextdateien im WINDOWS-1252-Format gespeichert wurden. Mit dem GCC 
unter Windows hat das ganz gut geklappt, daß man Texte einfach im 
Klartext speichern konnte.

Da ich das Thema demnächst wieder neu angehen muß, will ich auch den 
Codepage-Mechanismus noch einmal überdenken.

Was mir an meiner Lösung nicht gefallen hat: Habe ich den Quelltext in 
einer/für eine Linux-Umgebung gebaut, funktionierte die Darstellung der 
Sonderzeichen auf dem "virtuellen Display" nicht mehr.

Komplett von char auf wchar umstellen ist vermutlich nicht sinnvoll auf 
einem kleinen Mikrocontroller. Also bietet sind entweder UTF-8 oder der 
Verbleib auf Codepage 1252 an.

Lange Rede kurzer Sinn: Wenn ich das quadratische Rad mal wieder neu 
erfinden muß, interessiert es mich, wie es andere machen.

Viele Grüße
W.T.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Für Sonderzeichen, die ich selbst erfinde (Notenschlüssel, 
Lautsprecherchen, Klinkenstecker, Glöckchen usw.) nutze ich den Bereich 
der ASCII Steuerzeichen von 0x01 bis 0x1F (bis auf CR und LF).
Wenn ich ä,ö oder ü im Zeichensatz brauche, schmeisse ich meistens die 
geschweiften Klammern und den | raus - als Grossbuchstaben habe ich die 
aber nie benötigt, also nur als Kleinbuchstaben.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Lange Rede kurzer Sinn: Wenn ich das quadratische Rad mal wieder neu
> erfinden muß, interessiert es mich, wie es andere machen.

Du kannst dem Compiler mitteilen, welche Codierung für den Quelltext 
verwendet wird, und welche Codierung für die Ausgaben verwendet werden 
soll.

Das geschieht mit den Optionen

-finput-charset=

für den Quelltext

und

-fexec-charset=

für die Ausgabecodierung.

von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

danke für die sehr hilfreichen Antworten!

Rufus Τ. F. schrieb:
> Das geschieht mit den Optionen
>
> -finput-charset=
>
> für den Quelltext
>
> und
>
> -fexec-charset=

Danke für die Information. Irgendwann hatte ich das auch mal gefunden 
und wieder vergessen. Das würde sowohl eine Migration von CP-1252 auf 
UTF-8 erleichtern, als auch problemlos den Status quo auch unter Linux 
nutzbar lassen (wahrscheinlich wird nur die Input-Codepage falsch 
interpretiert). Sehr schön.

Matthias S. schrieb:
> Für Sonderzeichen, die ich selbst erfinde (Notenschlüssel,
> Lautsprecherchen, Klinkenstecker, Glöckchen usw.)

Auch interessant. Ich nutze für solche Sachen frei positionierbare 
Piktogramme, da ich da sowieso keine Zeilenausrichtung, Vorschub, 
verschiedene Größen etc. benötige.

Walter T. schrieb:
> Bislang habe ich eine eigene Codepage-Funktion verwendet, die von putc()
> aufgerufen wurde. Für alles zwischen 'A' 'Z' wurde einfach der
> entsprechende Offset für das Array mit den Zeichensatzdaten addiert.
> Zeichen darüber (Umlaute, 'ß', 'µ' etc.) wurde mit einer länglichen
> switch-case-Orgie der entsprechende Array-Eintrag oder der Eintrag des
> Ersatzzeichens (Rechteck) zugeordnet.

Wie sieht es damit aus? Gibt es bessere Implementierungsmöglichkeiten 
für schwach gefüllte Tabellen als switch-case-Reihen? (Irgendwie fühle 
ich mich immer etwas merkwürdig, wenn ich etwas, was eigentlich Daten 
sind, als Funktion implementiere.)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Wie sieht es damit aus? Gibt es bessere Implementierungsmöglichkeiten
> für schwach gefüllte Tabellen als switch-case-Reihen?

Naja, wenn 256 oder 128 Bytes Speicher nicht weh tun, kannst Du das als 
simple Tabelle anlegen.

Zeichen rein - Zeichen raus. Für nicht codierte Zeichen wird ein 
Defaultzeichen verwendet.

256 Byte-Tabellen sind am simpelsten, bei 128 Zeichen kommt vor den 
Tabellenzugriff noch eine Prüfung, ob Bit 7 gesetzt ist, und nur dann 
der Tabellenzugriff.
1
const char chartable[256] =
2
{
3
  0x00,
4
  0x01,
5
  0x02,
6
...
7
  0xFF
8
};
9
10
11
get_char_for_display(char c)
12
{
13
  return (chartable[c]);
14
}

oder
1
const char chartable[128] =
2
{
3
  0x00,  // Zeichen für 0x80
4
  0x01,
5
  0x02,
6
...
7
  0x7F   // Zeichen für 0xFF
8
};
9
10
11
get_char_for_display(char c)
12
{
13
  if (c & 0x80)
14
    return (chartable[c & 0x7f]);
15
  return (c);
16
}

Man müsste das halt mal mit der Codegröße Deines realen 
switch-case-Beispiels vergleichen.

von Walter T. (nicolas)


Lesenswert?

Rufus Τ. F. schrieb:
> Naja, wenn 256 oder 128 Bytes Speicher nicht weh tun, kannst Du das als
> simple Tabelle anlegen.

Stimmt **facepalm**. Die ganze Codepage-Tabelle ist ja nicht größer als 
ein einziges, popeliges 32x32-Pixel-Pikrogramm (solange ich nicht auf 
UTF wechsele).

Manchmal braucht man eine Diskussion, um auf das Offensichtliche zu 
stoßen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Rufus Τ. F. schrieb:
> Du kannst dem Compiler mitteilen, welche Codierung für den Quelltext
> verwendet wird
Das gilt dann aber leider für alle inkludierten Dateien auch, und da die 
System-Header vermutlich alle ASCII sind bekommt man Probleme, wenn man 
z.B. UTF-16 einstellt. Über die Prefixe der String-Literale hat man 
etwas mehr Flexibilität, aber die 8-Bit-Codepages kann man darüber 
leider nicht auswählen:
http://en.cppreference.com/w/cpp/language/string_literal

von Arne (Gast)


Lesenswert?

Matthias S. schrieb:
> Für Sonderzeichen, die ich selbst erfinde (Notenschlüssel,
> Lautsprecherchen, Klinkenstecker, Glöckchen usw.) nutze ich den Bereich
> der ASCII Steuerzeichen von 0x01 bis 0x1F (bis auf CR und LF).
> Wenn ich ä,ö oder ü im Zeichensatz brauche, schmeisse ich meistens die
> geschweiften Klammern und den | raus - als Grossbuchstaben habe ich die
> aber nie benötigt, also nur als Kleinbuchstaben.

Das ist dann uebrigens ISO 646 -- fuer die Grossbuchstaben wird [\] 
verwendet, die Tilde fuer Eszett.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Das gilt dann aber leider für alle inkludierten Dateien auch, und da die
> System-Header vermutlich alle ASCII sind bekommt man Probleme, wenn man
> z.B. UTF-16 einstellt.

Warum sollte man ausgerechnet UTF-16 verwenden? UTF-8 sollte doch 
genügen, und ist verbreiteter Standard.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Rufus Τ. F. schrieb:
> UTF-8 sollte doch
> genügen, und ist verbreiteter Standard.
Sag das den Windows-Programmierern ;-) Aber du hast schon Recht, bei den 
ASCII-kompatiblen Encodings wie UTF-8 sollte es unproblematisch sein. 
UTF-8 ist ja sowieso die Standardeinstellung. Man sollte nur im 
Hinterkopf behalten dass -finput-charset nicht alles kann...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Sag das den Windows-Programmierern ;-)

Selbst Visual Studio verwendet UTF-8 als Defaultcodierung für Quelltext. 
Die 16-Bit-Unicode-Variante ist weniger für Quelltext, als für Gebrauch 
der schon sehr lange existierenden Win32-API erforderlich.

UTF-8 hat halt einen großen Nachteil: Funktionen wie strlen werden 
ziemlich aufwendig.

von Jim M. (turboj)


Lesenswert?

Rufus Τ. F. schrieb:
> UTF-8 hat halt einen großen Nachteil: Funktionen wie strlen werden
> ziemlich aufwendig.

Das sind sie aber auch bei UTF-16, denn Unicode passt schon lange nicht 
mehr in nur 16 Bits hinein. Für moderne neue Emoticons braucht es 32 
Bits...

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Kommt drauf an was man will... Wenn man nur die Anzahl an belegten Bytes 
braucht, reicht strlen(). Wenn man die Anzahl an einzelnen Zeichen 
("grapheme clusters") braucht ists unabhängig von der Kodierung sehr 
kompliziert, da mehrere Codepoints zusammen ein "Zeichen" ergeben 
können, und es auch noch verschiedene Varianten gibt, diese 
darzustellen. Siehe:
https://www.unicode.org/faq/char_combmark.html#7
Dafür benutzt man am Besten eine Bibliothek wie libicu: 
http://site.icu-project.org/

von c-hater (Gast)


Lesenswert?

Jim M. schrieb:

> Rufus Τ. F. schrieb:
>> UTF-8 hat halt einen großen Nachteil: Funktionen wie strlen werden
>> ziemlich aufwendig.
>
> Das sind sie aber auch bei UTF-16, denn Unicode passt schon lange nicht
> mehr in nur 16 Bits hinein.

Deswegen ist das, was bei Windows Verwendung findet, eben auch nicht 
UTF-16, sondern UCS-16. Sprich: die Zeichenbreite ist konstant 16 Bits.

Klar: Etliche Unicode-Zeichen lassen sich damit nicht codieren. Aber 
wenn man nicht gerade unbedingt die neuesten Hirn-Blähungen der 
Emoticon-Szene benötigt oder was mit historischen Sprachen zu tun hat, 
dann reicht der Zeichenvorrat locker aus. Alle lebenden Schriftsprachen 
können damit dargestellt werden und dazu noch ein Unmasse von mehr oder 
weniger nützlichen weiteren Zeichen.

Außerdem darf man nicht vergessen: die Zeichenketten sind nur der weit 
kleinere Teil des Datenmülls im Speicher. Der Hauptverbrauch entsteht 
durch die Font-Glyphen, die zu seiner Darstellung nötig sind. Was nützt 
eine Codierung, die 4T Zeichen repräsentieren kann, wie etwa UTF-8 oder 
UTF-16, wenn die allermeisten dieser Zeichen dann doch wieder nur als 
"default char" dargestellt werden können, weil halt der verwendete Font 
sie nicht enthält...

So gesehen, ist das UCS-16 von Windows ein sehr, sehr guter Kompromiss, 
um den Resourcenverbrauch sowohl bezüglich des Speichers als auch 
bezüglich der Rechenzeit im Rahmen zu halten.

Und übrigens wird dieser Kompromiss längst nicht nur von Windows 
verwendet...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.