If Bedingung, variable und vorgegebene Parameter



  • Nathan schrieb:

    Das ist doch einfach genug?

    action.toLower();
    

    Wäre wohl deutlich einfacher und auch das was fast jedes andere Framework anbietet.



  • Dann schreibe es dir doch. 😉

    class MyString : public std::string
    {
    public:
        MyString(const std::string &str = "") : std::string(str) {}
    
        void toLower()
        {
            for (size_t i = 0; i < size(); ++i)
                operator[] (i) = std::tolower(operator[] (i));
        }
    };
    

    ungetestet.
    Und nein, ist gar nicht übertrieben... :p



  • Nathan schrieb:

    Dann schreibe es dir doch. 😉

    Ja, aber bitte nicht in Java-Manier. std::string ist nicht als Basisklasse konzipiert.

    In C++ hat man die Möglichkeit, freie Funktionen zu benutzen.

    void toLower(std::string& str);
    


  • ...



  • @Nexus:
    Ok, man merkt manchmal doch was ich zuerst gelernt habe...
    Ist aber schon lange her. 😃



  • Swordfish schrieb:

    krittikker schrieb:

    cvbnmcvb schrieb:

    Swordfish schrieb:

    std::transform( std::begin( action ), std::end( action ), std::begin( action ), std::tolower );

    gibts da in c++11 was einfacheres?

    Leider nein. Und der Code ist UB sowohl in C++98 als auch in C++11.

    Warum?

    Aus dem C-Standard:

    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.

    Der C++-Standard übernimmt die ganze C-Library ohne Änderungen, daher gilt das auch für C++.
    std::string besteht aus (möglicherweise signed) chars, diese werden implizit zu einem signed int gecastet. Der korrekte Weg wäre, sie zuerst in unsigned char zu casten und dann erst in einen int.



  • Nexus schrieb:

    In C++ hat man die Möglichkeit, freie Funktionen zu benutzen.

    void toLower(std::string& str);
    

    C++ nimmt aber keine string-Referenzen, sondern arbeitet da mit Iteratoren.

    template <typename Iter> void toLower(Iter from, Iter to);
    

    Jetzt will man aber auch eine Funktion, die uppercaset.

    template <typename Iter> void toLower(Iter from, Iter to);
    

    Schon hat man Code-Duplizierung.

    Vielleicht will man dem Benutzer auch erlauben, lower und upper-Case zu tauschen.

    template <typename Iter> void swapCase(Iter from, Iter to);
    

    3 mal der selbe Code!

    Also schreibt der findige Programmierer

    template <typename Iter, typename F> void transform(Iter from, Iter to, F action);
    

    und bietet Funktionen an, die die Aktion erledigen

    char toUpper(char c);
    char toLower(char c);
    char swapCase(char c); // vom Nutzer
    

    transform haben wir in der Standardbibliothek. Meine Kritik ist aber, dass die passenden toLower und toUpper fehlen. In der Praxis muss man jedesmal eine locale erstellen und sie an den to_upper-Aufruf binden (das macht C++11 immerhin einfacher, mit Lambda oder std::bind/mem_fun). Der offensichtliche Weg, den Swordfish gegangen ist, ist eben leider UB.



  • Also verwende einfach eine range-for Schleife und alles ist in Ordnung...



  • Der ganzen Code, den du gepostet hast, ist auch falsch (UB).



  • Meinetwegen, dann schreibe halt ein static_cast hin und sei glücklich...



  • krittikker schrieb:

    Vielleicht will man dem Benutzer auch erlauben, lower und upper-Case zu tauschen.

    Vielleicht will man aber auch nur einfachen Code und braucht die ganze Generizität nicht. Ein paar High-Level-Funktionen für Stringverarbeitung würden der Standardbibliothek echt nicht schaden. Zum Glück gibts Boost.StringAlgorithms.

    std::string hat etwa 111 Memberfunktionen, davon alleine 24 fürs Suchen. 24! 😮 Aber fast keine ist richtig nützlich, oder hast du schon jemals find_last_not_of() benötigt? Die meisten sind mit Iteratoren sowieso unnötig. Dafür muss andere Funktionalität wie sinnvolles Ersetzen wieder komplett neu implementiert werden (nein, std::replace() hilft nicht). Auch so etwas, es gibt 11 std::string::replace() -Überladungen, aber die wichtigste -- Substring durch anderen Substring ersetzen -- ist nicht dabei.

    Die ganzen STL-Algorithmen sind zwar sehr nett vom Design her, ihre Syntax ist jedoch alleine schon deswegen umständlich, weil man in 90% der Fälle begin() und end() auf den gleichen Container separat übergeben muss. Hier wären Ranges eine interessante Alternative.



  • krittikker schrieb:

    Nexus schrieb:

    In C++ hat man die Möglichkeit, freie Funktionen zu benutzen.

    void toLower(std::string& str);
    

    C++ nimmt aber keine string-Referenzen, sondern arbeitet da mit Iteratoren.

    template <typename Iter> void toLower(Iter from, Iter to);
    

    Jetzt will man aber auch eine Funktion, die uppercaset.

    template <typename Iter> void toLower(Iter from, Iter to);
    

    Schon hat man Code-Duplizierung.

    Vielleicht will man dem Benutzer auch erlauben, lower und upper-Case zu tauschen.

    template <typename Iter> void swapCase(Iter from, Iter to);
    

    3 mal der selbe Code!

    Also schreibt der findige Programmierer

    template <typename Iter, typename F> void transform(Iter from, Iter to, F action);
    

    und bietet Funktionen an, die die Aktion erledigen

    char toUpper(char c);
    char toLower(char c);
    char swapCase(char c); // vom Nutzer
    

    Die Argumentation ist relativ albern, jetzt darf jeder diesen Code duplizieren:

    std::transform( std::begin( action ), std::end( action ), std::begin( action ), std::tolower );
    

    Man könnte das std::transform(...bla;Zeugs auch in die String Methoden rein machen, dann dupliziert man weniger als jetzt. 🙄



  • SeppJ schrieb:

    Dein Problem war übrigens, dass a == b || c nicht bedeutet, dass a == b oder a == c sein soll, sondern es wird erst b || c berechnet (je nach Wert von b und c wird das true oder false ergeben) und das Ergebnis dann mit a verglichen. a gleich b oder a gleich c ist in C++ a == b || a == c .

    HMM, das stimmt nicht, oder?
    Laut VS 2010 ist a == b || c identisch zu (a==b)||c, oder meinst du was anderes?


  • Mod

    Namenloser324 schrieb:

    HMM, das stimmt nicht, oder?
    Laut VS 2010 ist a == b || c identisch zu (a==b)||c, oder meinst du was anderes?

    Ja, das war falsch bei mir.



  • Ok, danke(wollte dich nicht ärgern), hatte schon gegrübelt was ich denn falsch verstehe :D(weil du sonst immer recht hast^^)


Anmelden zum Antworten