UTF-8 'durchschleifen'/konvertieren
-
.filmor schrieb:
Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.
Autsch. ok, da braucht man nen eigenen char type. langsam dämemrts mir, warum utf support als standard proposal abgelehnt wurde.
-
sososo schrieb:
.filmor schrieb:
Length geht per Definition nicht anständig und ist auch wenig sinnvoll. find und replace tun's, wenn ich nach UTF-8 suche und mit UTF-8 ersetze. Wo ist das Problem?
Das ist ja ein extremer Aufwand, dann musst du jede Benutzereingabe, Konstante usw. zuerst nach UTF-8 Konvertieren. So gut wie keine Funktion gibt dir UTF-8 zurück, wenn du jetzt einmal zu konvertieren vergisst, dann hast du so nen dummen Fehler nach dem du ewig suchst.
Das ist im wesentlichen auch ein Punkt von mir.
Ich weiß das Unicode weit mehr als UCS-2 ist (Sorry, ich beschränke mich bei meinen Beispiel jetzt erstmal auf das System das ich kenne: Windows), aber nichts desto trotz wird man es ohnehin schwer haben in Bereichen die vom System nativ nicht abgedeckt werden sinnvoll zu arbeiten. Und innerhalb eines Systemes ist es durchaus ein möglicher 90% Weg, sich auf einen Kompromiss zu beschränken.
Ich hätte nichts dagegen wenn ich einen (möglichst portablen) Weg finde um mit UTF8 bis UTF-32 wirklich sinnvoll arbeiten zu können (Von dem Dateihandling bis zur UI), nur ist die sinnvolle Beschreibung wie man damit in Programmiersprachen gut umgeht entweder kaum vorhanden, oder es sind einfach zuviel Mülltreffer beim googlen um damit ernsthaft zu arbeiten. Sorry, ich erwarte das man nicht erst den ganzen Unicode-Standard durchackern muss um mit Unicode arbeiten zu können. Mich interessiert auch bei einem Container nicht die konkrete Umsetzung (auch wenn ich vielleicht den ein oder anderen schon selbst implementiert habe).
Das Problem liegt ja nicht nur bei C++ mit seiner mangelnden Unterstützung, sondern es gibt genügend andere Sprachen die wenn sie Unicode anbieten intern auch mit einem mehr oder weniger weitreichenden Kompromiss arbeiten.
cu André
-
Wo liegt denn das Problem? Die Kombinations„zeichen“ werden ja erst relevant, wenn man den Text tatsächlich rendern will und da muss man eh sukzessive Vorgehen (also ist's egal, ob man wahlfreien Zugriff hat), entsprechendes gilt für die meisten Parser. Normalisierungsroutinen sind nicht so schwer zu schreiben und abgesehen davon auch gut verfügbar. Mir fällt wirklich kein Fall ein, in dem ich Random-Access /und/ Unicode bräuchte …
otze schrieb:
.filmor schrieb:
Mir geht's vor allem um solche Späße. Die machen alle Vorteile bis auf die beinahe garantierte Validität von UTF-32 oder ähnlichem zunichte.
Autsch. ok, da braucht man nen eigenen char type.
Eben nicht. UTF-8 in char ftw!
@asc: UCS-2 hilft dir da mal überhaupt nicht weiter. Die Combining Characters gibt's da auch. Mir geht's nicht um UTF-16, das ist eh total verkorkst, sondern um beliebige Fixed-Byte-Encodings für Unicode, also UTF-32 oder die UCS-2-Untermenge von UTF-16. Es nutzt einfach nichts.
-
Ja genial!
Jetzt folge ich nicht mehr mit Abstand, sondern ich renne ziellos durch die dunklen Gassen dieser was-auch-immer.....
Entschuldigt bitte, wenn ich jetzt immer noch nicht weiß, was ich machen kann und wenn ich nicht mehr viel verstanden habe.
Vielleicht könnt Ihr Euch gemeinsam auf Antworten zu 1-5 (siehe erste Seite) einigen, zumindest partiell?!
Im Prinzip möchte ich natürlich viele Sonderzeichen abdecken, aber wenigstens die dt. Umlaute und die Standards der verbreiteteren Sprachen wäre sinnig....hilfe!
-
IMHO solltest du für alles std::string mit UTF-8 benutzen (dokumentieren nicht vergessen ;)) und nur für den allerletzten Schritt die Umwandlung zu der geforderten Kodierung durchführen.
Aber die ist doch bei LPCTSTR gar nicht eindeutig, oder?
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei. Wenn du Boost nicht verwenden möchtest kannst du einfach die utf8_codecvt_facet.hpp und die entsprechende .cpp-Datei nehmen, die benötigen AFAIK keine anderen Boost-Bibliotheken außer Boost.Config und davon kannst du den Code einfach rauswerfen (ist nur Präprozessorkram).
-
.filmor schrieb:
IMHO solltest du für alles std::string mit UTF-8 benutzen (dokumentieren nicht vergessen ;)) und nur für den allerletzten Schritt die Umwandlung zu der geforderten Kodierung durchführen.
Aber die ist doch bei LPCTSTR gar nicht eindeutig, oder?
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei. Wenn du Boost nicht verwenden möchtest kannst du einfach die utf8_codecvt_facet.hpp und die entsprechende .cpp-Datei nehmen, die benötigen AFAIK keine anderen Boost-Bibliotheken außer Boost.Config und davon kannst du den Code einfach rauswerfen (ist nur Präprozessorkram).Aber wozu dieser ganze Aufwand, dass man überall an UTF-8 denken muss, wenn es am Schluss doch LPCTSTR also 16 bit Unicode wird?
Für wen soll den das Programm sein?
-
.filmor schrieb:
Bei dem Schritt könnte jedenfalls diese codecvt-Facette helfen, Beispiel ist auch dabei.
Das ist kein encoding nach wchar_t, sondern einfach nach utf32:
utf8_codecvt_facet is a specialization of std::codecvt specifically designed to handle the case of translating between UTF-8 and UCS-4.
-
Ja, aber UTF-32 ist bis 0xFFFF kompatibel zu UTF-16.
-
und danach willst du unkontrolliert zeichensalat produzieren?
-
Also ersteinmal thx an .filmor für den Versuch.
Dann Dank an alle anderen, die sich beteiligen, danach eine Antwort:
Ich sammle INet-Info und gebe sie auf's Display der Logitech G15 aus, auf den im Logitech-SDK mitgelieferten Wrapper.Bitte nicht falsch verstehen, ich bin dankbar für jeden Beitrag (auch wenn ihr mich regelmäßig abhängt), aber vielleicht können diejenigen, die '.filmor's Versuch 'zerpflückt' haben, einen eigenen Vorschlag machen.
Wie würdet ihr denn vorgehen?Der Vorteil für mich ist, dass ich mit den Vorschläge mehr anfangen kann, als mit Eurer Diskussion danach
Zwischenfrage: Habe ich denn überhaupt eine Chance, den UTF-8-Krams gleich zu konvertieren, um danach mit dem normalen std::string zu arbeiten?
Oder analoges dazu, wenn ich alle meine jetzigen std::string's in std::wstring's ändere?
Und noch eine Frage:
Wo genau ist denn jetzt bei mir das Problem, wenn die Sonderzeichen nicht (korrekt) am Display ankommen? Darin, dass ich std::string benutzte, das ich den utf-8 codierten std::string manipuliere (gibt's das so? - mache ich auch nicht immer, geht trotzdem nicht) oder darin, dass die Übergabe ans Display einfach mit c_str() gemacht wird (gleich muss ich mir wohl etwas anhören...)?
Vielleicht kann man auch da ansetzen.
-
SammyRukka schrieb:
Bitte nicht falsch verstehen, ich bin dankbar für jeden Beitrag (auch wenn ihr mich regelmäßig abhängt), aber vielleicht können diejenigen, die '.filmor's Versuch 'zerpflückt' haben, einen eigenen Vorschlag machen.
Wie würdet ihr denn vorgehen?Da ich von den Standardfällen ausgehe würde ich tatsächlich die Gefahr eines gewissen Informationsverlustes in Kauf nehmen und intern auf eine 16 bzw. 32 bit-Repräsentation (std::wstring) konvertieren. Da sich aber .filmor scheinbar so gut damit auskennt kann er ja mal sagen wie man mit UTF-8 sinnvoll in einem C++ Programm arbeitet (Vom Einlesen bis hin zur UI-Darstellung). Und das an besten noch mit sinnvollen Quellen im Internet oder in Buchform, nach denen ich schon seit Jahren vergeblich suche (Und es kann nicht sein das man sich eine eigene UTF-8 Bibliothek schreiben muss).
Vielleicht ist ja das hier (ICU) etwas für dich.
cu André
-
Schau dir mal an, wie die einzelnen Codierungen (ASCII, UTF-8 UNICODE) aufgebaut sind. Schau nach, was dieses Logitech G15 Display bzw. das Famework dazu kann. Dann kannst du dir ganz leicht überlegen, ob es sinnvoll ist bis zum Ende UTF-8 durchzuschleifen (mit allem was du dabei bedenken musst) oder ob es besser ist gleich beim Einlesen zu konvertieren.
-
@vorschlag:
SammyRukka schrieb:
Zwischenfrage: Habe ich denn überhaupt eine Chance, den UTF-8-Krams gleich zu konvertieren, um danach mit dem normalen std::string zu arbeiten?
Oder analoges dazu, wenn ich alle meine jetzigen std::string's in std::wstring's ändere?Bei der Diskussion habe ich den Faden verloren, deshalb ja die Frage. Meinetwegen kann ich gleich konvertieren. Ich hänge nicht so am UTF. Es soll am Ende halt nur normal aussehen, damit meine ich wenigstens die Umlaute.
-
So, sorry, Aber ich habe jetzt 2 Stunden versucht und blicke gar nicht mehr durch:
- Muss ich dem Compiler (VS5 Express) noch etwas mitgeben, Zeichensatz, Unicodedateien oder so was?
- Mit welchem Datentyp muss ich denn nun arbeiten? Nach wstring komme ich, den bekomme ich aber nicht in einen LPCTSTR. string benutzen und zur Ausgabe konvertieren, gern, aber wie?
- ...?
-Jetzt brauche ich eine Woche Urlaub, gut, dass ich sie auch habe
-
Ojjj, hab ich Euch jetzt verschreckt?
Jetzt habe ich auch uftcpp getestet.
Naja, Test ist übertrieben. Ich habe den Kram eingebunden, das Bsp. läuft auch, nur frage ich mich jetzt, wie ich aus dem utf-8- einen normalen std::string machen soll.
Will sagen: Wie zum T. soll ich das utfcpp anwenden (Sry, bin zu blöd!).
-
Dafür musst du gar nichts machen. std::string benutzt char, was auf allen mir bekannten Plattformen 8-Bit groß ist und damit ohne weiteres UTF-8-Daten halten kann (steht auch irgendwo in der obigen Diskussion ;)).
Die Verwendung ist jetzt relativ simpel: Wenn du UTF-8-Daten einliest machst du nichts außer der Validitätschecks (die sind in utfcpp implementiert).Wenn du dann die Daten in UTF-16 benötigst, dann konvertierst du mit der Bibliothek entsprechend, da das ganze mit Iteratoren arbeitet sollte dafür ein simples std::copy in den Puffer genügen.
-
ist das so schwer zu kapieren wie die Codierungen ausschauen und wie man sie speichert? Hast du dir jemals nen Wikipediaartikel dazu angschaut oder probierst du nur planlos rum?
-
@filmor: Grundsätzlich danke, konkret weiß ich immer noch nicht weiter (s.u.).
@mal ehrlich: Meinst Du denn eigentlich, ich stelle mich mit Absicht dumm, um Euch zu ärgern?!Ich habe doch auch konkrete Fragen gestellt, darauf bekommt man dann aber keine konkreten Antworten. Ich habe Jahre lang Java gemacht und deshalb doch ein wenig das Gefühl für diesen ganzen Zeichenketten-Gump bei C/C++ verloren und durch die 18.000 typedef's dafür steige ich tatsächlich nicht mehr durch. Ich habe mich einfach auch daran gewöhnt, mich mit der Fachlichkeit zu beschäftigen und nicht mit irgendwelchen technischen Unzulänglichkeiten. Das kommt mir ein wenig so wie Linux vor. Das kann ich auch installieren, benutzen und ich komme einigermaßen von A nach B, ab deshalb kann ich noch lange nicht mal eben den Kernel selbst anpassen - was aufgrund der Masse an Doku aber vermutlich einfacher wäre als das hier.
Was weiß ich denn, ob ich einen UTF-16 benötige? Ich will den Kram doch nur auf dem Display ausgeben und dazu brauche ich einen LPCTSTR, was auch immer genau dahinter steckt.
Und nein, ich probiere nicht einfach nur rum, ich verstehe das meiste für sich allein auch, habe nur keine Ahnung, wie ich das zusammenführen soll. Und bei der Diskussion vorher scheint das ja auch nicht sooo einfach zu sein.Wenn das so einfach wäre, dann hätte man vermutlich auch Xfache Beispiele dafür gefunden.
Und was ist mit den Fragen zur IDE, wenn's gar nichts damit zu tun hat, dann kann auch das erwähnt werden. Nicht, dass es am Ende an der Konfiguration scheitert.
Dann helft doch bitte konkret! Ich will hier keinen Code abstauben, aber nach einer Woche erfolglosem Suchen, Lesen und Testen ist das evtl. das einzige, was mir hilft.
Bei Umlauten kommen halt immer 2 Zeichen bei raus, klar, es wird halt jedes Byte einzeln betrachtet, nur wie ändere ich das und wo an der Stelle hilft mir uftcpp?!Da das aber so einfach ist, kann ja evtl. jmd die 3 Zeilen Code hier posten.
---- Entschuldigung ----
Entschuldigt bitte die Ausschweifungen und den vielleicht auch nicht immer passenden Ton. Mir ist hier im Forum schon viel geholfen worden, wenn auch nicht immer wirklich direkt. Trotzdem bin ich nach einer Woche erfolglosem Suchen so weit, dass ich mich etwas über einen solchen Kommentar ärgere, erst recht, wenn nur so ein Kommentar, ohne Ansatz einer Hilfe kommt. Und ja, inzwischen probiere ich vermutlich wirklich nur noch herum - was bleibt mir denn anderes übrig.
Versuch doch einfach jmd. zu verstehen, der nicht Jahrzehnte lang C programmiert hat und deshalb auch nicht jedes Bit persönlich kennt.
-
Es wäre aber sehr hilfreich, wenn du dich mal zu den Vorschlägen konkret äußern würdest. „Hilft mir nicht weiter“ ist keine sinnvolle Problembeschreibung.
Dann mal los:
std::string ist vereinfacht ein Array von char. char ist 8-Bittig, damit ist std::string ein Array von 8-Bit-Elementen. UTF-8 ist (wie man der Wikipedia entnehmen kann) eine Kodierung, die genau solche 8-Bit-Elemente als Speicher braucht.
Nun bekommst du Daten in diesem Format und validierst sie nach Erhalt zur Sicherheit mit utfcpp (utf8::is_valid).
Dann machst damit irgendwas tolles und willst es an eine Funktion übergeben, die LPCTSTR übernimmt. Das ist (soweit ich weiß, ich programmiere keinen WinAPI-Kram) abhängig von davon, ob UNICODE gesetzt ist, ein Array von wchar_t, UTF-16-kodiert (die Unterscheidung UCS-2/UTF-16 sei irrelevant) oder ein Array von char, ANSI-kodiert.
Gehen wir von ersterem Fall aus (kannst du ja forcieren mit#ifndef UNICODE #error "Ich will aber!!!" #endif
. Dann machst du in etwa folgendes:
// zu übergebende Daten UTF-8-kodiert in daten vom Typ std::string TCHAR* buffer = new TCHAR[daten.size() + 1]; // Möglicherweise mehr als notwendig, aber auf jeden Fall genug. utf8::utf8to16 (daten.begin (), daten.end (), buffer); tolle_funktion_tm (buffer); delete[] buffer;
-
Kann im Moment nur kurz ins Forum sehen.
Danke für die Antwort, ich werde das hoffentlich morgen abarbeiten können.---
Bin da doch nicht ganz davon gekommen...
Muss ich UNICODE einfach per define setzen oder ist das ein Compilereinstellung? Mit dem 'Unicode-Ausgabedateien verwenden' von Visual Studio Express hat das wohl nichts zu tun, oder?Und dann zum Verständnis: Wenn ich UNICODE nicht setzen würde, dann könnte ich den UTF-8-Krams auch nicht verarbeiten, weil LPCTSTR dann wieder nur ein char* wäre und dann wiederum jedes Byte dargestellt werden würde, so wie jetzt.
wchar_t * aber führt zum Erfolg, weil es 'multibyte'-tauglich ist (Oha, da schwanke ich jetzt).