If Bedingung, variable und vorgegebene Parameter
-
Dein Problem war übrigens, dass
a == b || cnicht bedeutet, dassa == bodera == csein soll, sondern es wird erstb || cberechnet (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.edit: Argh
, umgekehrt: a == b || cist(a == b) || c. Trotzdem ist aus meinem Beitrag mitzunehmen, dass der Ausdruck nicht das macht, was der TE dachte.
-
Swordfish schrieb:
std::transform( std::begin( action ), std::end( action ), std::begin( action ), std::tolower );
gibts da in c++11 was einfacheres?
-
Ich finde das echt schwach vom GCC. Wenn ich den Code kompiliere (-Wall -Wextra) ist die einzige Warnung, die ich bekomme
warning: suggest parentheses around ‘&&’ within ‘||’ [-Wparentheses](wobei ich den Sinn dieser Warnung eh nicht verstehe)
Clang gibt in etwa die gleiche Warnung.Warum warnt niemand bei
if ("string literal")gibt es einen Fall, in dem das sinnvoll ist?
-
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.
Ich kenn da nur eine Lösung von Boost.
-
Das ist doch einfach genug?
Notfalls ginge auch:for (auto &c : action) c = std::tolower(c);Aber ich persönlich finde das erste einfacher...
-
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::stringist 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 Nutzertransform 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::stringhat 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 11std::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()undend()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 NutzerDie 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 || cnicht bedeutet, dassa == bodera == csein soll, sondern es wird erstb || cberechnet (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?
-
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^^)