Forum: PC-Programmierung stringlaenge in Abhaengigkeit von charmap begrenzen


von Dergute W. (derguteweka)


Lesenswert?

Moin,

Problem: Ich krieg in C diverse Strings, die in verschiedenen charmaps 
abgespeichert sind (die charmap ist mir jeweils bekannt). Die will ich 
in einen Buffer mit kleinerer Laenge quetschen, muss also "hinten" etwas 
abschneiden. Das wird aber unangenehm, weil bei verschiedenen 
Kodierungen ich den String nicht einfach an irgendeinem Byte absaebeln 
kann, ohne dass er "kaputt" geht.

Beispiel: Der String "ößäü" verschieden codiert, soll in einen 5 byte 
grossen Buffer rein (das 5. byte sollte dann immer die \0 Terminierung 
sein):
1
wk [ ~ ]$ printf "ößäü"  | hexdump -C
2
00000000  c3 b6 c3 9f c3 a4 c3 bc                           |........|
3
00000008
4
wk [ ~ ]$ printf "ößäü" | iconv -f UTF-8 -t ISO_6937-2 | hexdump -C
5
00000000  c8 6f fb c8 61 c8 75                              |.o..a.u|
6
00000007
7
wk [ ~ ]$ printf "ößäü" | iconv -f UTF-8 -t ISO_8859-1 | hexdump -C
8
00000000  f6 df e4 fc                                       |....|
9
00000004

Also kann ich den, wenn er utf8 ist, zufaellig direkt nach dem 4. byte 
abschneiden. Alles gut.
Wenn der ISO_9959-1 ist, ueberhaupt kein Problem, da passt er komplett 
in den Buffer.
AAAABER - wenn er ISO_6937-2 ist, muss ich den String schon nach dem 3. 
Byte beenden, denn wenn ich das 4. Byte noch mit reinnehme, sind das 
nurnoch die Diakritika des ä, also nur "ein halbes" Zeichen. Der String 
ist also am Ende nicht mehr komplett.

Da haben doch bestimmt schlaue Leute, die im Gegensatz zu mir, alle 
Zeichen in allen Charmaps virtuos beherrschen, irgendeine Funktion 
(wahrscheinlich in der glibc, Abteilung iconv oder iconvdata) dafuer 
geschrieben - die koennte so aussehen:
1
size_t tolleFunktion(char * string, size_t maxlen, char * charmap);

und mir die Groesse zurueckliefern, die kleinergleich maxlen ist und wo 
der String in der Codierung abgeschnitten werden darf.

Gibt's sowas, kennt das wer? Da bin ich doch sicher nicht der Erste mit 
so einer Problematik. (Fuer utf8 alleine wuerd' ichs ja noch hinkriegen, 
weil der "schoen" aufgebaute Multibytecharacters hat, aber bei allen 
anderen Codierungen ist das etwas Aufwand...)

Gruss
WK

von DPA (Gast)


Lesenswert?

Bei meinen Programmen gibt es immer nur UTF-8. Support für andere 
Kodierungen gibt es bei mir einfach nicht. Wozu auch, UTF-8 ist 
universal und geht für jede Sprache.

von Dergute W. (derguteweka)


Lesenswert?

DPA schrieb:
> Bei meinen Programmen gibt es immer nur UTF-8. Support für andere
> Kodierungen gibt es bei mir einfach nicht. Wozu auch, UTF-8 ist
> universal und geht für jede Sprache.

Ok, dann stell' doch mal ab morgen z.B. Videotext um auf UTF-8... :-)

Und auch bei reinem UTF-8 kann dieses Problem durch "combining 
characters" nochmal extrafies auftauchen:

https://www.cl.cam.ac.uk/~mgk25/unicode.html#comb

Gruss
WK

von Dr. Sommer (Gast)


Lesenswert?

Dergute W. schrieb:
> Problem: Ich krieg in C diverse Strings, die in verschiedenen charmaps
> abgespeichert sind (die charmap ist mir jeweils bekannt)

Wo kommt die charmap denn her? Ist die Teil des Programms? Wieso ist 
denn dann die Kodierung nicht fix (UTF-8 oder whatever)?

Dergute W. schrieb:
> Und auch bei reinem UTF-8 kann dieses Problem durch "combining
> characters" nochmal extrafies auftauchen:

Das kann doch bestimmt die libicu, aber halt nur für Unicode.

von Bauform B. (bauformb)


Lesenswert?

Evt. ein Ansatzpunkt:
1
mbrlen(3)
2
   determine number of bytes in next multibyte character
3
NOTES
4
   The behavior of mbrlen() depends on the LC_CTYPE category
5
   of the current locale.

von Walter T. (nicolas)


Lesenswert?

Ich verstehe das Problem nicht. In allen mir bekannten Encodings steht 
bei jedem Zeichen schon beim ersten Byte fest, ob es sich um ein 
Multi-Byte-Zeichen handelt. Also kann man einfach von vorn nach hinten 
normal durchgehen.

von foobar (Gast)


Lesenswert?

Ich gehe davon aus, dass du die C-Routine iconv(3) meinst (danach 
hattest du letztens gefragt): der musst du doch nur die korrekte Größe 
des Ausgabepuffers mitgeben - die liefert dann ein passendes E2BIG wenn 
der Platz nicht mehr ausreicht:

man 3 iconv
1
    ...
2
    4. The output buffer has no more room for the next converted
3
    character.  In this case it sets errno to E2BIG and returns
4
    (size_t) -1.
5
    ...

Nachträglich zu splitten ist so aufwendig wie iconv selbst, da du dafür 
jede mögliche Kodierung kennen und entsprechend splitten musst.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Danke fuer's Aufzeigen des Walds, den ich vor lauter Baeumen nicht mehr 
gesehen hab'. Natuerlich geht's so. Irgendwie hatte ich 
faelschlicherweise angenommen, dass wenn iconv ein E2BIG macht, es dann 
garnichts in den Ausgangspuffer schreibt. Tut's aber, und so wie's 
aussieht, genauso wie ich's brauch'. Danke nochmal.

Gruss
WK

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.