Frage zu wchar_t in Visual Studio 2008



  • Hallo, ich benutze den Visual C++ 2008 Express Edition compiler. Leider funktioniert hier folgender Code nicht so, wie ich das will:

    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main()
    {
        wstring text(L" "); //stellt Euch hier ein paar kyrillische Buchstaben vor
                            //kann das Forum offensichtlich nicht anzeigen :)
        wcout<<text; //Konsole bleibt leer
        wofstream schreiben(L"wtest.txt");
        schreiben<<text; //das textdokument wird zwar erstellt, bleibt aber leer
        schreiben.close();
    }
    

    Ich habe schon im Release Modus unter Projekt -> konsolenanwendung-Eigenschaften -> Allgemein -> Zeichensatz auf Unicode und Multi-Byte Zeichensatz gestellt, allerdings ohne Erfolg. Was mache ich also falsch 😕



  • Kann dein Editor, mit dem du dir die Ausgabe anschaust, die Zeichen überhaupt anzeigen? Überprüf das doch mal...



  • Naja, das Textdokument ist 0 Byte groß. Zum Anschauen benutze ich einfach den Texteditor von Windows...
    Aber ich habe gerade folgendes gesehen:

    cout<<text.size(); //Gibt 5 aus, das stimmt auch
    
    wcout<<text.size(); //Gibt nichts aus
    

    Anscheinend kann meine Konsole nicht mit wcout umgehen Oo Kann das sein?



  • Hm, ich habe jetzt mal ein bisschen gegooglelt, aber keiner der Tipps konnte helfen.

    wstring text(L"\u0430\u043A\u043C\u0430\u043B"); //escapesequenzen statt den richtigen Buchstaben
    wcout<<text; //noch immer kein Output in die Konsole
    cout<<text.size(); //gibt 5 aus (was stimmt)
    wcout<<text.size(); //immernoch kein Output
    
    wofstream schreiben(L"wtest", ios::binary); //binär in Datei schreiben
    schreiben<<text;                            //wieder wird eine leere, 0 byte große
                                                //Datei namens "wtest" erstellt
    schreiben.close();
    

    Und das sowohl bei "unicode" als auch "multi-byte" projekt Settings.





  • Ich hoffe du hast schon geprüft, ob der Code mit lateinischen Buchstaben so funktioniert wie er soll?



  • It0101 schrieb:

    Ich hoffe du hast schon geprüft, ob der Code mit lateinischen Buchstaben so funktioniert wie er soll?

    Ja klar. Ich teste gerade mit folgendem Programm:

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    int main()
    {
        wstring wtext(L"\u0430\u043A\u043C\u0430\u043B"); //auch schon probiert: statt der escape sequenzen die kyrillischen Buchstaben
        string text("test");
    
        wofstream wschreiben("wtest"); //auch schon probiert: wofstream wschreiben(L"wtest");
        ofstream  schreiben("test");
    
        schreiben<<text;   // in "test" steht "test" drinne. Stimmt!
        wschreiben<<wtext; // "wtest" bleibt leer
    
        return 0;
    }
    

    Herausgefunden habe ich, dass die Windows Konsole nur ASCII anzeigen kann. Also beschränke ich mich jetzt auf das schreiben/lesen von Dateien.

    theta schrieb:

    Ev. hilfts weiter:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-244120-and-highlight-is-konsole+kyrillisch.html

    In einem Link in dem artikel habe ich jetzt folgenden Codeschnipsel gefunden:

    //include <locale>
    
    wofstream my_of("myfile.txt");
    
    locale loc(locale::classic(), new codecvt_utf8<wchar_t>);  // Locale: von Classic (US-ASCII) nach UTF-8
    my_of.imbue(loc);
    
    my_of << L"Hello" << endl;
    

    Allerdings kompiliert es bei mir nicht:

    1>.\main.cpp(35) : error C2061: Syntaxfehler: Bezeichner 'codecvt_utf8'
    1>.\main.cpp(35) : error C2664: 'std::locale::locale(const char *,std::locale::category)': Konvertierung des Parameters 1 von 'const std::locale' in 'const char *' nicht möglich
    1>        Kein benutzerdefinierter Konvertierungsoperator verfügbar, der diese Konvertierung durchführen kann, oder der Operator kann nicht aufgerufen werden
    

    Was mache ich hier falsch? ich will doch nur kyrillische Buchstaben in der Datei stehen haben 😃



  • Versuchs mal so:

    // Das müsste eigentlich funktionieren, ist aber jetzt nur mit UTF16 Little Endian getestet
    // Siehe auch http://de.wikipedia.org/wiki/Byte_Order_Mark
    template<typename ValueType>
    std::vector<char> getByteOrderMark()
    {
    	assert( CHAR_BIT == 8 );
    	assert( sizeof(unsigned short) == 2 );
    	assert( sizeof(unsigned int) == 4 );
    
    	const unsigned char utf8[] = { 0xEF, 0xBB, 0xBF };
    	const char* utf8ptr = reinterpret_cast<const char*>( utf8 );
    	if ( sizeof(ValueType) == 1 )
    		return std::vector<char>( utf8ptr, utf8ptr+sizeof(utf8) );
    
    	const unsigned short utf16 = 0xFEFF;
    	const char* utf16ptr = reinterpret_cast<const char*>( &utf16 );
    	if ( sizeof(ValueType) == 2 )
    		return std::vector<char>( utf16ptr, utf16ptr+sizeof(utf16) );
    
    	const unsigned int utf32 = 0x0000FEFF;
    	const char* utf32ptr = reinterpret_cast<const char*>( &utf32 );
    	if ( sizeof(ValueType) == 4 )
    		return std::vector<char>( utf32ptr, utf32ptr+sizeof(utf32) );
    
    	assert( 0 );
    	return std::vector<char>();
    }
    
    int main()
    {
        std::wstring kyrill = L"...";
        std::ofstream file( "test.txt", std::ios::binary );
    
        std::vector<char> bom = getByteOrderMark<wchar_t>();
    	file.write( &bom[0], bom.size() );
    	file.write( reinterpret_cast<const char*>(kyrill.c_str()), kyrill.length()*sizeof(wchar_t) );
    }
    


  • Wieso bietet C++ denn Mittel wie wofstream und wstring an, wenn man es am Ende (wie Bandestrand gezeigt hat) selbst implementieren muss 😕



  • Weil es einen Unterschied gibt zwischen "wie und wo speichere ich etwas" (std::wstring etc.) und "wie und wo gebe ich etwas aus" (std::wcout, std::fstream, etc.).
    Simon



  • C++ bietet dir die Infrastruktur, aber wenn du die Stream-Operatoren benutzt, dann benötigst du auch ein entsprechendes Locale um die Zeichenkette entsprechend zu speichern. Und dummerweise wurden keine Locales für die Standardzeichensätze spezifiziert. Eine Standardbibliothek welche diese mitliefert ist die von Dinkumware, allerdings kostet die ein bischen was.


Anmelden zum Antworten