std::locale wirt exception
-
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
ProgrammiererUser 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::stringist eintypedefaufstd::basic_string<char>, was wiederum für das interne Array denChar_T = charverwendet, was wiederum beim überladenen Index-Operator eben diesen Typ liefert. Also wo bitte übergebe ich keinenunsinged 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.
-
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
charund einemunsigned 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:
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
charund einemunsigned char?Ich erinnere mich gerade an cooky451:
char und unsigned char ist nicht dasselbe!
-
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 "" (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.
Eine andere locale wird z.B. benötigt, wenn mann eine Textdatei sortieren will, die Sonderzeichen enthält. Wenn man z.B. die Länge der Vokale ausdrücklich darstellen will (-> Latein) benutzt man ā und ă, die zwar beide aus dem lateinischen Zeichensatz stammen, aber bei Verwendung der deutschen Standard-locale nicht alphabetisch als a einsortiert werden. Am besten ist es in diesem Fall, eine eigene locale als Kopie der deutschen locale zu erzeugen und darin die eigene Sortierfacette einzubauen. Siehe Stroustrup, Der C++ Programmierer, Anhang
locales.