std::locale wirt exception



  • Die Lösung wurde doch schon genannt: Benutze den compilerspezifischen String.



  • Michael E. schrieb:

    Die Lösung wurde doch schon genannt: Benutze den compilerspezifischen String.

    Danke 🙂 ! Aber wo wurde die denn genannt? Im anderen Link?


  • Mod

    Hacker schrieb:

    Michael E. schrieb:

    Die Lösung wurde doch schon genannt: Benutze den compilerspezifischen String.

    Danke 🙂 ! Aber wo wurde die denn genannt? Im anderen Link?

    Also compilerspezifisch ist nicht ganz richtig, eher plattformspezifisch. Plattformunabhängig sind nur die locales "C" (im Prinzip US-Englisch) und "" (die Systemlocale). Die anderen musst du eben nachschlagen. Wobei ich noch nie den Grund verstanden habe, wieso man etwas anderes nehmen sollte als "" (oder "C"), denn ich will nicht, dass ein Programm plötzlich eine ungewöhnte Locale benutzt, bloß weil es von einem Deutschen programmiert wurde. Da ist doch der ganze Sinn von Loacales futsch, wenn das Programm nicht die Systemlocale (und damit meine Sprache) benutzt (oder wenn es sein muss die Standardlocale), sondern die Sprache des Programmierers. Wieso hätte mich als Nutzer zu interessieren, wie der Programmierer in der Schule seine Dezimaltrennzeichen geschrieben hat? Oder noch schlimmer wird's wenn das Programm noch einen andere Zeichensatz erzwingt als den meiner Ausführungsumgebung. Ich wüsste nicht einmal aus dem Kopf, wie ich in meiner Konsole ein UTF-32 Zeichen tippen kann.



  • SeppJ schrieb:

    Hacker schrieb:

    Michael E. schrieb:

    Die Lösung wurde doch schon genannt: Benutze den compilerspezifischen String.

    Danke 🙂 ! Aber wo wurde die denn genannt? Im anderen Link?

    Also compilerspezifisch ist nicht ganz richtig, eher plattformspezifisch. Plattformunabhängig sind nur die locales "C" (im Prinzip US-Englisch) und ....

    Naja, jedenfalls funktioniert das "Programm" mit der system-lokale auch nicht - und wenn man dann (deiner Argumentation folgend) keine anderen nehmen sollte, hat man ja keine Wahl, als toupper, bzw. tolower selbst zu implementieren.


  • Mod

    So so! es funktioniert also nicht. Lies dir doch bitte mal den ersten Link in meiner Signatur gründlich durch und stell dann noch einmal eine brauchbare Frage.

    (Dass ich das mal bei jemandem mit 1500 Beiträgen schreiben muss 🙄 )

    P.S.: Du sagst also, dass
    http://ideone.com/jbkvZ
    bei dir eine Exception wirft?



  • SeppJ schrieb:

    So so! es funktioniert also nicht. Lies dir doch bitte mal den ersten Link in meiner Signatur gründlich durch und stell dann noch einmal eine brauchbare Frage.

    (Dass ich das mal bei jemandem mit 1500 Beiträgen schreiben muss 🙄 )

    Ok.

    Nein, es funktioniert nicht, da es einfach Umlaute ignoriert (was Michael E. furchtbar blöd findet - und ich auch). Das sollte es aber nicht, wenn das globale locale auf German gesetzt wurde. Also? 🤡


  • Mod

    Hacker schrieb:

    Nein, es funktioniert nicht, da es einfach Umlaute ignoriert (was Michael E. furchtbar blöd findet - und ich auch). Das sollte es aber nicht, wenn das globale locale auf German gesetzt wurde. Also? 🤡

    So so! "Es" "ignoriert" Umlaute. Dann ist ja jetzt alles klar.



  • SeppJ schrieb:

    Hacker schrieb:

    Nein, es funktioniert nicht, da es einfach Umlaute ignoriert (was Michael E. furchtbar blöd findet - und ich auch). Das sollte es aber nicht, wenn das globale locale auf German gesetzt wurde. Also? 🤡

    So so! "Es" "ignoriert" Umlaute. Dann ist ja jetzt alles klar.

    Kennst du den anderen Thread nicht?

    #include <iostream>
    #include <string>
    
    void firstToupperOtherTolower(std::string& str)
    {
          if(str.length())
                str.at(0) = toupper(str.at(0));
    
          for(std::string::size_type a(1);a < str.length();++a)
                str.at(a) = tolower(str.at(a));
    }
    
    int main()
    {
          std::locale::global(std::locale(""));
    
          std::string vorname, nachname;
          std::cout << "Bitte Vornamen eingeben: ";
          std::getline(std::cin, vorname);///PI zuliebe
          std::cout << "Bitte Nachnamen eingeben: ";
          std::getline(std::cin, nachname);
    
          firstToupperOtherTolower(nachname);
          firstToupperOtherTolower(vorname);
    
          std::cout << "Ihr Name ist " << vorname << ' ' << nachname << '\n';
    }
    

    Eingabe: oNI oNI Ausgabe: Oni Oni
    Eingabe: öLÄ öNÜ Ausgabe: ölÄ önÜ





  • Michael E. schrieb:

    http://www.cplusplus.com/reference/std/locale/ctype/tolower/
    http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=stricmp#Answ

    Erstes Kenn ich (natürlich) schon, zweites hat mit meiner Fragem Problem nichts zu tun (strings case-insensitive vergleichen!?) 😕



  • Hacker schrieb:

    std::getline(std::cin, vorname);///PI zuliebe
    

    wat



  • 314159265358979 schrieb:

    Hacker schrieb:

    std::getline(std::cin, vorname);///PI zuliebe
    

    wat

    Hattest dich doch letztens mit Werner Salomon gezofft? 😃



  • ney.



  • Hacker schrieb:

    Erstes Kenn ich (natürlich) schon,

    Warum benutzt du es dann nicht?

    zweites hat mit meiner Fragem Problem nichts zu tun (strings case-insensitive vergleichen!?) 😕

    Es würde helfen, wenn du dir das mal durchliest, statt schon vorher zu sagen, dass das nichts mit dem Thema zu tun haben soll. Tipp: Wie könnte man wohl Strings case-insensitiv vergleichen?



  • Tja, bin eben zu schnell. Aber auch so:

    Michael E. schrieb:

    Wie könnte man wohl Strings case-insensitiv vergleichen?

    Die std::transform Methode ist laut (dem bisher sehr zuverlässigem C++-reference) äquivalent zu:

    template < class InputIterator, class OutputIterator, class UnaryOperator >
      OutputIterator transform ( InputIterator first1, InputIterator last1,
                                 OutputIterator result, UnaryOperator op )
    {
      while (first1 != last1)
        *result++ = op(*first1++);  // or: *result++=binary_op(*first1++,*first2++);
      return result;
    }
    

    Was resultiert zu mit Input & OutputIterator = std::basic_string<char>::iterator, UnaryOperator = tolower/toupper:

    OutputIterator transform ( std::string::iterator first1, std::string::iterator last1,std::string::iterator result, int(*)(int) op )
    {
      while (first1 != last1)
        *result++ = tolower(*first1++);  
      return result;
    }
    

    WAs im Endeffekt wieder nur das macht, was die anderen "Versuche" auch fabrizieren. Ohne den globalen locale vorher zu verändern wird sich hier auch nichts verändern.



  • EDIT: Ha! Wirft eine Exception. Ha SepJ! 😮 😃



  • void firstToupperOtherTolower(std::string& str)
    {
          if(str.length())
                str.at(0) = std::toupper(str.at(0));
    
          for(std::string::size_type a(1);a < str.length();++a)
                std::transform<std::string::iterator, std::string::iterator, int(*)(int)>(str.begin(), str.end(), str.begin(), std::tolower);
    }
    

    1. "Capitalize" wäre ein passenderer Name.
    2. Wieso checkst du zuerst die Stringlänge und verwendest dann at, das nochmal checkt?
    3. Wieso gibst du bei transform explizit der Template-Parameterliste an?



  • SeppJ schrieb:

    Wobei ich noch nie den Grund verstanden habe, wieso man etwas anderes nehmen sollte als "" (oder "C"), denn ich will nicht, dass ein Programm plötzlich eine ungewöhnte Locale benutzt, bloß weil es von einem Deutschen programmiert wurde. Da ist doch der ganze Sinn von Loacales futsch, wenn das Programm nicht die Systemlocale (und damit meine Sprache) benutzt (oder wenn es sein muss die Standardlocale), sondern die Sprache des Programmierers.

    Na es könnte sein dass man dem Programmierer User eine Option anbieten möchte die Sprache/Locale selbst auszuwählen, unabhängig von der im OS eingestellten Sprache.

    Denk an Embedded Systems. Kann schnell passieren dass man während das Programm läuft die Sprache/Locale umschalten möchte.



  • Ethon schrieb:

    void firstToupperOtherTolower(std::string& str)
    {
          if(str.length())
                str.at(0) = std::toupper(str.at(0));
     
          for(std::string::size_type a(1);a < str.length();++a)
                std::transform<std::string::iterator, std::string::iterator, int(*)(int)>(str.begin(), str.end(), str.begin(), std::tolower);
    }
    

    1. "Capitalize" wäre ein passenderer Name.
    2. Wieso checkst du zuerst die Stringlänge und verwendest dann at, das nochmal checkt?
    3. Wieso gibst du bei transform explizit der Template-Parameterliste an?

    Deine Fragen sind total berechtigt, also

    1. Ja, hast Recht.
    2. Damit keine Exception geworfen wird. (Oder soll sie das dann gerade? Wäre dann aber nicht erkennbar, was genau das Problem ist (für den Anwender der Funktion). Also lieber doch so)
    3. Komischerweise gibt das bei mir folgende Fehler:

    GCC 4.6.2 schrieb:

    No matching function to call for ... BLABLABLA



  • std::transform() N mal über den ganzen String drüberzulassen (N = Länge des Strings) macht auch so überhaupt keinen Sinn.

    if (str.size() > 0)
    {
        str[0] = std::toupper(str[0]);
        std::transform(str.begin() + 1, str.end(), str.begin() + 1, std::tolower);
    }
    

Anmelden zum Antworten