Verstehe Unicode nicht
-
Was die Probleme bei der Verarbeitung angeht: da gehts z.B. darum bei diversen Codepages rauszubekommen welche Bytes "zusammen gehören".
Dann gibt's noch die tollen Uneindeutigkeiten, viele haben Zeichen mehrere Codepoints in Unicode, und viele zeichen die einen eigenen Codepoint haben sind auch als mehrere Codepoints darstellbar.Wenn man das ganze dann auf den Schirm bringen will wird's richtig lustig, da muss man sich dann auf einmal mit Dingen wie der Leserichtung beschäftigen, bzw. mehr oder weniger komplizierten Shaping Regeln (im Arabischen z.B. gibt es für ein und den selben Codepoint mehrere Zeichen, je nachdem was drumherum steht). Oder ... um z.B. bei einem Thai Text rauszubekommen wo man eine Zeile umbrechen darf braucht man ein Wörterbuch - da keine Spaces kodiert werden. Bei japanischen Texten muss man wiederum ein paar (relativ einfache) Regeln befolgen - hier werden zwar auch keine Spaces verwendet, dafür kann man fast überall umbrechen.
Was die Schriftarten angeht: es gibt einige "ziemlich vollständige", z.B. "Arial Unicode" - da ist dann auch Japanisch und Chinesisch mit dabei.
Andere Zeichen wie z.B. für indische Schriften findet man aber kaum in einer Schriftar.----
In C++ gibt es für die erwähnten Aufgaben keine (bzw. nur ungenügende) Funktionen in der Standard Library, daher sagt man C++ unterstützt Unicode nicht. Wenns dagegen nur darum geht Unicode Texte von A nach B zu schaufeln, oder als Dateinamen o.Ä. zu unterstützen ist es relativ einfach, da man in diesen Fällen meist die Strings 1:1 durchreichen kann ohne sie angreifen zu müssen.
-
Wie sieht es eigentlich mit Unicode String-Literatlen aus, wenn man glib::ustring verwendet?
Würde z.B. folgendes funktionieren:
glib::ustring mystr = "さようなら";

-
U. T. F. schrieb:
Wie sieht es eigentlich mit Unicode String-Literatlen aus, wenn man glib::ustring verwendet?
Würde z.B. folgendes funktionieren:
glib::ustring mystr = "さようなら";

wenn die Code-Datei in UTF8 abgespeichert ist: Ja.
-
Gibt es glib::ustring auch als separate Library? Oder eine andere kleine Library, die eine unicode string Klasse bereitstellt?
-
Warum benutzt du nicht std::wstring?
-
Artchi schrieb:
Warum benutzt du nicht std::wstring?
std::wstring == std::basic_string<wchar_t>
sizeof(wchar_t) == 16
sizeof(ein_unicode_zeichen) > 16
-
std::wchar kann verhältnissmäßig gut UTF-16 unterstützen. UTF-8 und UTF-32 hingegen gehen mit std::wstring nicht direkt.
Es ist eindeutig FALSCH, dass ein Unicode-Zeichen größer als 16 bit ist. Das /kann/ so sein, gerade in UTF-8 sind viele Zeichen (US-ASCII) < 16bi (um genau zu sein 8bit) groß.
Glib::ustring gehört IMHO zur GNOME oder GTK+ Bibliotek.
-
UniCode schrieb:
sizeof(wchar_t) == 16
Bei mir ist sizeof(wchar_t) == 2.

-
Wie breit wchar_t ist ist nicht standardisiert. Unter Windows (MSVC) sind es 2 Byte oder auch 16 Bit. Könnten aber woanders auch 32 Bit sein, oder 24 oder ... .
Man kann aber genausogut std::basic_stringboost::uint32\_t o.ä. nehmen.
Dann kann man da lustig 1 Element = 1 Codepoint machen, was einiges einfacher macht.
Natürlich kann es sein dass es irgendwann mal Zeichen gibt die selbst da nichtmehr reinpassen, aber ich denke auf die kann man dann getrost verzichten.
-
UniCode schrieb:
Gibt es glib::ustring auch als separate Library? Oder eine andere kleine Library, die eine unicode string Klasse bereitstellt?
Hmm, irgend wo gab es da was. War glaube ich bei Boost irgend ein Vorschlag oder irgend was was dort entwickelt wurde. Ansonsten kannst du ja auch glib::ustring aus der GLIBmm kopieren.
darthdespotism schrieb:
std::wchar kann verhältnissmäßig gut UTF-16 unterstützen.
wenn du std::wstring meinst: Nein, da basic_string erwartet, das ein Zeichen eine feste Breite hat. Das ist bei UTF-16 aber nicht gegeben
UTF-8 und UTF-32 hingegen gehen mit std::wstring nicht direkt.
UTF-32 geht sehr wohl, wenn wchar_t groß genug ist. Auf Mac OS X und Linux ist es entsprechend groß. Aber wie hustbaer schon gesagt hat, kann man ja auch einfach std::basic_stringstd::uint32_t nehmen
Es ist eindeutig FALSCH, dass ein Unicode-Zeichen größer als 16 bit ist.
Siehe UCS-2. Unicode benötigt 32 Bit. Alles andere (UTF-7, UTF-8, UTF-2, UTF-16) sind Encodings um diese 32 Bit abzubilden.
-
Ich würde mir folgende Frage stellen: benötige ich mehr als 65.000 verschiedene Zeichen? Wird mit 65.000 Zeichen bzw. UCS2 nicht schon praktisch alles wichtige abgedeckt? Ich meine jetzt nicht gerade Schriften wie die von den Azteken, Klingolisch oder so. Das ist wahrscheinlich nur bei UCS4 drin. Aber ganz ehrlich: für gängige Anwendungen müsste wstring ausreichen um die wichtigsten Schriftzeichen abzudecken.
Außerdem kann man sich ja auch mal nach dem nächsten C++0x richten, da wird es neue String-Typedefs geben:
u16string und u32string, neben string und wstring.Also würde ich mir in mein Programm sowas einrichten, wie:
typedef std::wstring mystring;Wenn der C++0x rauskommt und erste Implementierungen, braucht man nur das typedef einmalig in seinem Programm anpassen. Eine ganz tolle Sache, dieses typedef.
typedef std::u32string mystring;Wer Refactoring-Tools hat, kann auf das Typedef verzichten und brauch dann nur nen Mouseclick für die Änderung in seinen Projekten.
-
UniCode schrieb:
Artchi schrieb:
Warum benutzt du nicht std::wstring?
std::wstring == std::basic_string<wchar_t>
sizeof(wchar_t) == 16
sizeof(ein_unicode_zeichen) > 16Es wurde ja schon gesagt, unter Windows hat wchar_t üblicherweise zwei unter Linux vier Byte. Beides reicht meistens für den praktischen Einsatz von Unicode aus. Bei vier Byte ist das kein Thema, weil damit alle Unicode-Zeichen erfasst werden können. Aber auch mit den zwei Byte von Windows kommt man eigentlich gut aus. Denn mit zwei Byte pro Zeichen kann UCS-2 implementiert sein. Und das umfasst den Großteil der tatsächlich genutzten Unicode-Zeichen, alle europäischen Zeichen, Hebräisch, Arabisch, Chinesisch, Japanisch, Koreanisch, eigentlich fast alles. Außerhalb von UCS-2 liegen dagegen z.B. die historischen Schriften und Zeichen für Musik-Annotation. In der Praxis ist es also relativ wahrscheinlich, dass selbst UCS-2 völlig ausreichend ist.
-
minhen! Mein Reden!
Schliesslich wird Windows weltweit eingesetzt. Alle latainischen Schriften sind eh mit UCS2 abgedeckt. Ich habe hier Windows-Versionen in arabisch und hibräisch liegen. Also, mit UCS2 und somit wstring kann man sehr gut auskommen.Übrigens, UTF8 ist für Massendatenverarbeitung auch nicht gerade der Hit. Für den Transport von A nach B sicherlich am flexibelsten, aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t).
-
Wobei Windows intern UTF-16 und nicht UCS-2 verwenden soll. Dass UCS-2 aber für die meisten Einsätze ausreicht, macht beispielsweise Java vor.
-
Artchi schrieb:
Ich würde mir folgende Frage stellen: benötige ich mehr als 65.000 verschiedene Zeichen? Wird mit 65.000 Zeichen bzw. UCS2 nicht schon praktisch alles wichtige abgedeckt?
Gegenfrage: Wo ist das Problem UTF-32 zu unterstützen? Ist dir die Kleinigkeit es überhaupt Wert einen Gedanken daran zu verschwenden, was anderen Leuten wichtig ist und was nicht? Oder ob UCS-2 aussreicht und UCS-4 eher in betrunkener Karnevalslaune entstanden ist?
Ich meine jetzt nicht gerade Schriften wie die von den Azteken, Klingolisch oder so. Das ist wahrscheinlich nur bei UCS4 drin. Aber ganz ehrlich: für gängige Anwendungen müsste wstring ausreichen um die wichtigsten Schriftzeichen abzudecken.
wstring sagt doch gar nichts über die Größe oder den unterstützten Zeichensatz. Auf meinen Systemen ist wstring groß genug für UCS-4.
Außerdem kann man sich ja auch mal nach dem nächsten C++0x richten, da wird es neue String-Typedefs geben:
u16string und u32string, neben string und wstring.Hoffen wir es mal. Wobei ich den Sinn davon allem außer Kodierungern mit fester Breite (also zB utf32) in Programmen eh fragwürdig finde, außer man will alten Code wieder zum Leben erwecken. Ich speicher ja auch meine Arrays nicht Huffmann-Kodiert...
aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t)
unter Windows eben nicht!
-
rüdiger schrieb:
aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t)
unter Windows eben nicht!
Auch unter Windows. Denn wchar_t hat immer eine feste Zeichenbreite. Völlig egal welche, aber sie ist immer fest. Das ist doch gerade der Unterschied zwischen UTF-16 (variabel) und UCS-2 (fest).
-
rüdiger schrieb:
Gegenfrage: Wo ist das Problem UTF-32 zu unterstützen? Ist dir die Kleinigkeit es überhaupt Wert einen Gedanken daran zu verschwenden, was anderen Leuten wichtig ist und was nicht? Oder ob UCS-2 aussreicht und UCS-4 eher in betrunkener Karnevalslaune entstanden ist?
Ich habe lediglich den Fragesteller dazu angeregt, sich selber die Frage zu stellen, ob nicht UCS2 ausreichend wäre. Ich habe ihm nichts vorgeschrieben! Aber manchmal muß man Leute sensibilisieren da sie manchmal einfach Zeug nachplappern "UTF-8 ist das einzig wahre!". Dabei ist das völliger Blödsinn, so zu denken. Denn was bringt mir UTF-8 zur Laufzeit für einen Vorteil ggü. 16 oder 32 bit breiten Zeichencodes?
rüdiger schrieb:
wstring sagt doch gar nichts über die Größe oder den unterstützten Zeichensatz.
Muß es auch nicht. Es reicht wenn ein Zeichen breit genug ist. Was am Ende auf dem Bildschirm oder Drucker raus kommt, ist jemand anderes Zuständig - und nicht ein C++-Std-String.
rüdiger schrieb:
aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t)
unter Windows eben nicht!
Ein unvollständiger Satz, ohne Begründung. Weiß überhaupt nicht worauf du hinaus willst... 
-
minhen schrieb:
rüdiger schrieb:
aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t)
unter Windows eben nicht!
Auch unter Windows. Denn wchar_t hat immer eine feste Zeichenbreite. Völlig egal welche, aber sie ist immer fest. Das ist doch gerade der Unterschied zwischen UTF-16 (variabel) und UCS-2 (fest).
Sie ist doch nicht fest, wenn ich damit UTF-16 Strings darstelle. Ansonsten ist wchat_t einfach nicht breit genug unter den meisten Windows-Compilern, um alle Zeichen darzustellen, die das System darstellen kann.
Artchi schrieb:
rüdiger schrieb:
Gegenfrage: Wo ist das Problem UTF-32 zu unterstützen? Ist dir die Kleinigkeit es überhaupt Wert einen Gedanken daran zu verschwenden, was anderen Leuten wichtig ist und was nicht? Oder ob UCS-2 aussreicht und UCS-4 eher in betrunkener Karnevalslaune entstanden ist?
Ich habe lediglich den Fragesteller dazu angeregt, sich selber die Frage zu stellen, ob nicht UCS2 ausreichend wäre. Ich habe ihm nichts vorgeschrieben! Aber manchmal muß man Leute sensibilisieren da sie manchmal einfach Zeug nachplappern "UTF-8 ist das einzig wahre!". Dabei ist das völliger Blödsinn, so zu denken. Denn was bringt mir UTF-8 zur Laufzeit für einen Vorteil ggü. 16 oder 32 bit breiten Zeichencodes?
UTF-8 bringt den Vorteil, dass du damit ne Menge alter Software auf Unicode umrüsten kannst. Sicher sind Encodings für UTF-8/16 nicht ideal, wenn man mit diesen Strings auf Zeichenebene rumspielen will (wie ich schon sagte, man Huffmann-Enkodiert ja auch nicht seine Arrays). Aber wenn man zum Beispiel nur String-Literale hat, die man internationalisieren will, bietet UTF-8 vor allem einen Speicherplatz Vorteil.
Ich will ja auch nur lediglich sagen, das ich UTF32 nehmen würde, sobald ich mit Unicode Strings arbeiten muss. Da hinterfrage ich nicht ob 16Bit reichen. Sonst muss ich am Ende bei UTF-16 landen und dann hätte ich gleich UTF-8 nehmen können.
rüdiger schrieb:
wstring sagt doch gar nichts über die Größe oder den unterstützten Zeichensatz.
Muß es auch nicht. Es reicht wenn ein Zeichen breit genug ist. Was am Ende auf dem Bildschirm oder Drucker raus kommt, ist jemand anderes Zuständig - und nicht ein C++-Std-String.
Ich habe ja auch nichts anderes behauptet.
rüdiger schrieb:
aber für Runtime-Fälle ist eindeutig eine feste Zeichenbreite performanter (und somit wchar_t)
unter Windows eben nicht!
Ein unvollständiger Satz, ohne Begründung. Weiß überhaupt nicht worauf du hinaus willst... 
Windows benutzt so weit ich weiß wchar_t mit UTF-16. Also keine feste Zeichenbreite.
-
Bei mir klappt das mit Unicode überhaupt nicht. Ich habe folgenden Quelltext:
`#include<iostream>
#include<string>
using namespace std;
main()
{
wstring test = "
さくら";cout << test << endl;
cout << test[0] << test[1] << test[2] << endl;
}`
Abgespeichert als UTF-8 gibt folgende Compilerfehler:
test.cpp: In functionint main()':test.cpp:7: error: conversion from
const char[10]' to non-scalar typestd::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >' requestedtest.cpp:8: error: no match for 'operator<<' in 'std::cout << test'
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:63: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>&(*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:74: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>&(*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:86: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base&(*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:121: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:155: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:98: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/ostream:180: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/ostream:191: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/ostream:195: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/ostream:206: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:179: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:214: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:238: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/ostream:221: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:261: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:284: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/x86_64-pc-linux-gnu/3.4.6/include/g++-v3/bits/ostream.tcc:307: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]`
Abgespeichert als UTF-16, UTF-32, UCS-2 oder UCS-4 gibt es folgende Compilerfehler:
`test.cpp:1: error: stray '\255' in program
test.cpp:1: error: stray '\254' in program
test.cpp:1: error: invalid token
test.cpp:1:4: warning: null character(s) ignored
test.cpp:1:6: warning: null character(s) ignored
test.cpp:1: error: `i' does not name a type
test.cpp:1:8: warning: null character(s) ignored
[...]
test.cpp:2:3: warning: null character(s) ignored
test.cpp:2:4: invalid preprocessing directive #i
test.cpp:2:5: warning: null character(s) ignored
[...]
test.cpp:5:3: warning: null character(s) ignored
test.cpp:5: error: `m' does not name a type
test.cpp:5:5: warning: null character(s) ignored
[...]
test.cpp:7:33: warning: null character(s) ignored
test.cpp:7:36: warning: null character(s) preserved in literal
test.cpp:7:45: warning: null character(s) ignored
[...]
test.cpp:11:1: warning: null character(s) ignored
test.cpp:11:2: warning: no newline at end of file`
Wenn ich statt wstring einfach string nehme und das ganze als UTF-8 abspeichere, kompiliert es zwar, aber die Ausgabe ist nur:
さくら
さAusgabe sollte aber sein:
さくら
さくらWenn ich nun ustring verwende:
`#include<iostream>
#include<glibmm.h>
using namespace std;
using Glib::ustring;
main()
{
ustring test = "さくら";
cout << test << endl;
cout << test[0] << test[1] << test[2] << endl;
}`
und das ganze als UTF-8 abspeichere kompiliert es zwar auch, ich bekomme aber folgenden Laufzeitfehler:
`terminate called after throwing an instance of 'Glib::ConvertError'
zsh: abort ./a.out`
Könnt ihr mir helfen?
-
Ups. Den letzten quellcode hat das Forum kaputt gemacht. So ist es richtig:
`#include<iostream>
#include<glibmm.h>
using namespace std;
using Glib::ustring;
main()
{
ustring test = "
さくら";cout << test << endl;
cout << test[0] << test[1] << test[2] << endl;
}`