Verstehe Unicode nicht



  • 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> >' requested

    test.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;

    }`



  • #include<iostream>
    #include<string>
    using namespace std;
    
    int main() {
      std::string test = "你好";
      cout << test << endl;
      for(size_t i = 0; i < test.size(); ++i)
        std::cout << "0x"
                  << std::hex
                  << static_cast<unsigned>(static_cast<unsigned char>(test[i]))
                  << '\n';
    }
    
    # g++ -Wall -W -std=c++98 foo.cpp
    # ./a.out
    你好
    0xe4
    0xbd
    0xa0
    0xe5
    0xa5
    0xbd
    

    Das erste Beispiel (mit wstring) funktioniert so nicht, da wstring-Literale mit einem L beginnen (also anstelle "foo", L"foo") und du solltest wcout benutzen. Denk dran, dass du auch dein Terminal entsprechend einstellen musst oder ein locale bei wcout setzen!

    warum das ustring Beispiel nicht funktioniert, weiß ich jetzt nicht. Habe aber auch kein glibmm da, um das zu überprüfen.



  • UNICODE Strings sollte man IMO nicht in C++ Source Files packen. Zumindest nicht wenn man möchte dass alles reibungslos funktioniert. 😉



  • Und wie würdest du dann obiges Beispiel schreiben?



  • rüdiger schrieb:

    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.

    Ja, laut Standard muss wchar_t jedoch den maximalen Code-Point fassen können. Das heißt, es ist ganz klar als feste Zeichenbreite definiert. Wäre dem nicht so, wären die ganzen Standard-Konveriertungsfunktionen zwischen breiten Zeichen (wchar_t()) und Multibyte-Kodierungen (mittels char) auch relativ sinnlos.
    Aber selbst wenn die Standards in dem Punkt gebrochen werden, ändert das nichts daran, dass zwei Bytes für die mit Abstand meisten Zeichen ausreichen. In der gewöhnlichen Praxis wird man also vermutlich nie einen Unterschied zwischen UTF-16 und UCS-2 bei internen Repräsentationen bemerken. (Was natürlich nicht davon ablenken soll, dass man damit nicht auf Nummer sicher geht.)

    wcout kann übrigens mitunter ziemlich (Standard-)locale-resistent sein. Sicher ist man dagegen mit File-Streams (wofstream) - die haben mir in dem Punkt noch keinen Ärger gemacht.



  • edocinU schrieb:

    Und wie würdest du dann obiges Beispiel schreiben?

    Keine Ahnung was du da für Zeichen benutzt hast. Aber UCS und Unicode gibt man am besten in dieser Form ein:

    L"\u06A1\u0609\u06A0"
    

    Um genau zu sein: U-Escapes. Weiß nicht ob das U jetzt für UCS oder Unicode steht.



  • C++ ist noch nicht dazu geeignet, Unicode Strings zu verarbeiten. Vielleicht ändert sich das ja mit C++0x. Aber bis dahin würde ich an deiner Stelle einfach Perl verwenden. Damit geht das einfacher und unkompliziert:

    `#!/usr/bin/perl

    use Encode;

    binmode(STDOUT, ":utf8");

    my $test = decode_utf8("さくら");

    print($test, "\n");

    print(substr(test,0,1),substr(test, 0, 1), substr(test, 1, 1), substr($test, 2, 1), "\n");`

    Ausgbe wie erwartet:
    さくら
    さくら

    😋 👍



  • --------------------------
                             /|  /|  |                          |
                             ||__||  |       Trolle bitte       |
                            /   O O\__           nicht          |
                           /          \         füttern!        |
                          /      \     \                        |
                         /   _    \     \ ----------------------
                        /    |\____\     \     ||
                       /     | | | |\____/     ||
                      /       \|_|_|/   |    __||
                     /  /  \            |____| ||
                    /   |   | /|        |      --|
                    |   |   |//         |____  --|
             * _    |  |_|_|_|          |     \-/
          *-- _--\ _ \     //           |
            /  _     \\ _ //   |        /
          *  /   \_ /- | -     |       |
            *      ___ c_c_c_C/ \C_c_c_c____________
    


  • Artchi schrieb:

    --------------------------
                             /|  /|  |                          |
                             ||__||  |       Trolle bitte       |
                            /   O O\__           nicht          |
                           /          \         füttern!        |
                          /      \     \                        |
                         /   _    \     \ ----------------------
                        /    |\____\     \     ||
                       /     | | | |\____/     ||
                      /       \|_|_|/   |    __||
                     /  /  \            |____| ||
                    /   |   | /|        |      --|
                    |   |   |//         |____  --|
             * _    |  |_|_|_|          |     \-/
          *-- _--\ _ \     //           |
            /  _     \\ _ //   |        /
          *  /   \_ /- | -     |       |
            *      ___ c_c_c_C/ \C_c_c_c____________
    
    --------------------------
                             /|  /|  |                          |
                             ||__||  |       Trolle bitte       |
                            /   O O\__           nicht          |
                           /          \         füttern!        |
                          /      \     \                        |
                         /   _    \     \ ----------------------
                        /    |\____\     \     ||
                       /     | | | |\____/     ||
                      /       \|_|_|/   |    __||
                     /  /  \            |____| ||
                    /   |   | /|        |      --|
                    |   |   |//         |____  --|
             * _    |  |_|_|_|          |     \-/
          *-- _--\ _ \     //           |
            /  _     \\ _ //   |        /
          *  /   \_ /- | -     |       |
            *      ___ c_c_c_C/ \C_c_c_c____________
    


  • @Artchi:
    Es ist leider wirklich so, dass sich C++ (im Gegensatz zu z.B. Perl) mit Unicode noch recht schwer tut. Selbst mit Glib::ustring scheint es ja nicht richtig zu funktionieren (auch wenn ich es selbst noch nicht getestet habe).



  • Hihi.
    Perl, PHP, Java etc. setzen im Normalfall C oder C++ Libraries ein um mit Unicode zu arbeiten. Oft ist es einfach die (leider sehr schrottige) ICU.
    Und die kann man genausogut in C++ verwenden.


Anmelden zum Antworten