Locales: C versus C++



  • Hi,

    ich habe gerade etwas mit Locales herumgespielt und verstehe nicht, weshalb es bei den verwendbaren Locale-Namen einen Unterschied zwischen C und C++ gibt.

    Also dass bei verschiedenen Betriebssystemen verschiede Locales zur Verfügung stehen ist klar. Aber warum sogar bei C vs C++? Was ich mit C meine ist die Funktion setlocale und bei C++ mein ich eben std::locale().
    So kann ich ohne Probleme setlocale(LC_ALL, "POSIX") machen, aber ein 'locale l("POSIX")' fliegt mir sofort um die Ohren: ungültiger Locale-Name. Das geht lustig weiter mit "UTF-8" geht bei setlocale, aber nicht bei locale. Auch "de_DE.ISO-8859-1" geht mit setlocale, aber nicht mit locale() - so zieht sich das durch alle Locales hindurch. Praktisch alle Locales gehen mit setlocale, praktisch keine mit locale() von C++. Warum?
    Auch merkwürdig finde ich, dass "C" nicht mit setlocale geht. Ich dachte das Locale müsste jede C/C++-Implementierung anbieten? Blick da echt nicht mehr durch. Wieso geht das so drunter und drüber?

    Also was mich am meisten stresst ist, dass ein Locale-Name, der für setlocale überhaupt kein Problem ist, bei locale() plötzlich eine Exception auslöst von wegen schlechter Locale-Name. Das Problem hab ich sowohl unter Windows als auch unter Linux und Mac. Compiler ist bei allen drei der GCC in verschiedenen Versionen ....

    Kann mir da einer weiterhelfen? Blick nicht mehr durch.



  • explicit locale(const char* std_name);
    6 Effects: Constructs a locale using standard C locale names, e.g. "POSIX". The resulting locale implements semantics defined to be associated with that name.
    7 Throws: runtime_error if the argument is not valid, or is null.
    8 Notes: The set of valid string argument values is "C", "", and any implementation-defined values.



  • Das weiß ich, davon red ich doch gerade. Vielleicht hätte ich noch dazu sagen sollen, dass ich sowohl Google als auch die C/C++-Spezifikationen bereits auf den Kopf gestellt habe. Aber ich sehe schon, ohne Quellcode, so dass es jeder bei sich nachvollziehen kann, bin ich einfach ein Depp, der irgendwas hinfantasiert. Also folgender Code:

    #include <iostream>
    #include <locale>
    using namespace std;
    
    void testLocale(const char* name)
    {
        string sp(20 - strlen(name), ' ');
        cout << name << ": " << sp;
        cout << "(C: "; cout.width(10);
        if(!setlocale(LC_ALL, name))
            cout << " ok";
        else
            cout << " nicht ok";
        cout << " / C++: "; cout.width(10);
        try {
            locale  loc(name);
            cout << " ok";
        }
        catch(exception &e) { cout << " nicht ok"; }
        cout << ")" << endl;
    }
    
    int main()
    {
        const char* locales[] = {"C", "POSIX", "de", "de_DE", "german", "UTF8", "UTF-8", "ISO-8859-1"};
        string de = "de_DE.";
        for(int i=0; i<8; i++)
            testLocale(locales[i]);
        for(int i=0; i<8; i++)
            testLocale((de+locales[i]).c_str());
        return 0;
    }
    

    Ergibt folgende Ergebnisse:

    Unter Ubuntu Linux mit dem GCC 4.2.3:

    C:                    (C:   nicht ok / C++:         ok)
    POSIX:                (C:   nicht ok / C++:         ok)
    de:                   (C:         ok / C++:   nicht ok)
    de_DE:                (C:         ok / C++:   nicht ok)
    german:               (C:         ok / C++:   nicht ok)
    UTF8:                 (C:         ok / C++:   nicht ok)
    UTF-8:                (C:         ok / C++:   nicht ok)
    ISO-8859-1:           (C:         ok / C++:   nicht ok)
    de_DE.C:              (C:         ok / C++:   nicht ok)
    de_DE.POSIX:          (C:         ok / C++:   nicht ok)
    de_DE.de:             (C:         ok / C++:   nicht ok)
    de_DE.de_DE:          (C:         ok / C++:   nicht ok)
    de_DE.german:         (C:         ok / C++:   nicht ok)
    de_DE.UTF8:           (C:   nicht ok / C++:         ok)
    de_DE.UTF-8:          (C:   nicht ok / C++:         ok)
    de_DE.ISO-8859-1:     (C:         ok / C++:   nicht ok)
    

    Unter Mac OS X mit Apple/GCC 4.0.1:

    C:                    (C:   nicht ok / C++:         ok)
    POSIX:                (C:   nicht ok / C++:         ok)
    de:                   (C:         ok / C++:   nicht ok)
    de_DE:                (C:   nicht ok / C++:   nicht ok)
    german:               (C:         ok / C++:   nicht ok)
    UTF8:                 (C:         ok / C++:   nicht ok)
    UTF-8:                (C:         ok / C++:   nicht ok)
    ISO-8859-1:           (C:         ok / C++:   nicht ok)
    de_DE.C:              (C:         ok / C++:   nicht ok)
    de_DE.POSIX:          (C:         ok / C++:   nicht ok)
    de_DE.de:             (C:         ok / C++:   nicht ok)
    de_DE.de_DE:          (C:         ok / C++:   nicht ok)
    de_DE.german:         (C:         ok / C++:   nicht ok)
    de_DE.UTF8:           (C:         ok / C++:   nicht ok)
    de_DE.UTF-8:          (C:   nicht ok / C++:   nicht ok)
    de_DE.ISO-8859-1:     (C:         ok / C++:   nicht ok)
    

    Unter Windows XP SP3 mit MinGW/GCC 3.4.5:

    C:                    (C:   nicht ok / C++:         ok)
    POSIX:                (C:         ok / C++:         ok)
    de:                   (C:         ok / C++:   nicht ok)
    de_DE:                (C:         ok / C++:   nicht ok)
    german:               (C:   nicht ok / C++:   nicht ok)
    UTF8:                 (C:         ok / C++:   nicht ok)
    UTF-8:                (C:         ok / C++:   nicht ok)
    ISO-8859-1:           (C:         ok / C++:   nicht ok)
    de_DE.C:              (C:         ok / C++:   nicht ok)
    de_DE.POSIX:          (C:         ok / C++:   nicht ok)
    de_DE.de:             (C:         ok / C++:   nicht ok)
    de_DE.de_DE:          (C:         ok / C++:   nicht ok)
    de_DE.german:         (C:         ok / C++:   nicht ok)
    de_DE.UTF8:           (C:         ok / C++:   nicht ok)
    de_DE.UTF-8:          (C:         ok / C++:   nicht ok)
    de_DE.ISO-8859-1:     (C:         ok / C++:   nicht ok)
    

    Und jetzt noch einmal meine Frage: Hä? 🤡
    Wäre immer dieselbe GCC-Version betroffen, würd ich "Bug!" schreien. Aber so? Jemand eine Idee? Warum geht "C" bei C nicht? Und vor allem warum unterscheiden sich C und C++?



  • Ich habs mir ja schon immer gedacht, dass C++ nicht für sowas taugt.



  • Locali schrieb:

    Warum geht "C" bei C nicht?

    Es geht doch. Nur wertest du das Ergebnis von setlocale gerade verkehrt aus.



  • Oh, stimmt. Ist mir gar nicht aufgefallen. Danke für den Hinweis! Damit hat sich das Rätsel um die C-Locale also erledigt und alle "ok" werden bei C zu "nicht ok" und andersrum. Bleibt aber noch das Rätsel, wieso es für setlocale andere Locales gibt als für locale(). Also warum z. B. UTF-8 mit setlocale geht, während locale() gleich eine panische Exception wirft.


Anmelden zum Antworten