std::locale wirt exception



  • 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);
    }
    


  • 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)

    Mal zum Vergleich wie at und der Operator definiert sein können:

    char& at(size_t i)
    {
        if(i >= len)
            throw out_of_range();
        return data[i];
    }
    
    char& operator[](size_t i)
    {
        return data[i];
    }
    

    Klingelts? 😉
    at benutzt du gerade, wenn du möchtest dass der String die Länge selbst checkt, der Operator macht das nicht.

    3. Komischerweise gibt das bei mir folgende Fehler:

    Ja, seltsame Sache. Komischerweise hilft es, tolower anstatt std::tolower zu schreiben. Wieso? Keine Ahnung ...
    Warscheinlich gibt es irgendwo in locale eine überladene Version von tolower, du willst aber explizit die C-Version.



  • hustbaer schrieb:

    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);
    }
    

    Ah, Nein! Da hab ich im Code einfach Cut & Paste gemacht, ohne auf die Schleife zu achten 😃



  • Ethon schrieb:

    Warscheinlich gibt es irgendwo in locale eine überladene Version von tolower, du willst aber explizit die C-Version.

    Ah, stop. Die zweite erwartet auch eine locale-Instanz? Klar, dass du da Recht hast, hab ich so auf C++-Reference ARAIR nicht gesehen..(Edit: Obwohl es natürlich so da steht).



  • Mein Code war auch (grad bemerkt) gar nicht richtig, auch ohne Schleife. Jedenfalls ist die Funktion jetzt so:

    void Capitalize(std::string& str)
    {
          str.at(0) = std::toupper(str.at(0));
    
          std::transform(str.begin() + 1, str.end(), str.begin() + 1, boost::bind(std::tolower<char>, _1, std::locale("")));
    }
    


  • hustbaer schrieb:

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

    Dass der leere String auch kapitalisierbar ist und keine Ausnahme werfen sollte, könnte sich Hacker mal überlegen (ausserdem ist dein Code schneller als zwei mal at()).

    Aber dein Code führt zu UB:

    <a href= schrieb:

    man: toupper">If c is not an unsigned char value, or EOF, the behavior of these functions is undefined.



  • hüstler schrieb:

    hustbaer schrieb:

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

    Dass der leere String auch kapitalisierbar ist und keine Ausnahme werfen sollte, könnte sich Hacker mal überlegen (ausserdem ist dein Code schneller als zwei mal at()).

    Aber dein Code führt zu UB:

    <a href= schrieb:

    man: toupper">If c is not an unsigned char value, or EOF, the behavior of these functions is undefined.

    Stoppeldu. std::string ist ein typedef auf std::basic_string<char> , was wiederum für das interne Array den Char_T = char verwendet, was wiederum beim überladenen Index-Operator eben diesen Typ liefert. Also wo bitte übergebe ich keinen unsinged char ?



  • hüstler schrieb:

    Aber dein Code führt zu UB:

    <a href= schrieb:

    man: toupper">If c is not an unsigned char value, or EOF, the behavior of these functions is undefined.

    Hm..

    n1548 7.4.2.2 The toupper function schrieb:

    2 The toupper function converts a lowercase letter to a corresponding uppercase letter.
    Returns
    3 If the argument is a character for which islower is true and there are one or more
    corresponding characters, as specified by the current locale, for which isupper is true,
    the toupper function returns one of the corresponding characters (always the same one
    for any giv en locale); otherwise, the argument is returned unchanged.



  • @cooky451:

    7.4 Character handling <ctype.h>
    1 The header <ctype.h> declares several functions useful for classifying and mapping
    characters.172) In all cases the argument is an int, the value of which shall be
    representable as an unsigned char or shall equal the value of the macro EOF. If the
    argument has any other value, the behavior is undefined.

    @Hacker: Was ist wohl der Unterschied zwischen einem char und einem unsigned char ?



  • (war blödsinn)



  • hüstler schrieb:

    Aber dein Code führt zu UB:

    <a href= schrieb:

    man: toupper">If c is not an unsigned char value, or EOF, the behavior of these functions is undefined.

    Ja, hast Recht.
    Ich weiss schon warum ich die C++ Lokalisierungsfunktionen net mag 🙂



  • hüstler schrieb:

    @cooky451:

    7.4 Character handling <ctype.h>
    1 The header <ctype.h> declares several functions useful for classifying and mapping
    characters.172) In all cases the argument is an int, the value of which shall be
    representable as an unsigned char or shall equal the value of the macro EOF. If the
    argument has any other value, the behavior is undefined.

    @Hacker: Was ist wohl der Unterschied zwischen einem char und einem unsigned char ?

    Ich erinnere mich gerade an cooky451:

    char und unsigned char ist nicht dasselbe!


Anmelden zum Antworten