tags:

views:

137

answers:

4

Hi,
how to convert a string (wstring) from lowercase to uppercase characters and vice versa? I searched the net and found there is a STL-function std::transform.
But until now I hav'nt figured out how to give the right locale-object for example "Germany_german" to the function. Who can help please? my code looks like:

wstring strin = L"ABCÄÖÜabcäöü";
wstring str = strin;
locale loc( "Germany_german" ); // ??? how to apply this ???
std::transform( str.begin(), str.end(), str.begin(), (int(*)(int)tolower );
//result: "abcäöüabcäöü"

The characters ÄÖÜ and äöü (it's like Ae, Oe, Ue) will not be converted correctly.

P.S.: I don't prefer a big switch sweat and also I know BOOST is capable of everything, i would prefer a STL solution.

thanks in advance
Oops

+1  A: 

Did you try "de_DE.UTF-8" for locale construction?

Laurynas Biveinis
+1  A: 

If you're on Unix, see /usr/share/locale/ for available locales. It looks like you want "de_DE.UTF-8".

But setlocale(LC_ALL, ""); should set the program to work in the system's locale, whatever it is.

Your program works for me (I fixed a close-paren) if I simply set the default locale like that, without specifying Germany.

Potatoswatter
He is on windows... German_Germany is windows style locale names
Artyom
Ah. All the more reason to use `setlocale(LC_ALL, "");`, which is standard C++, and not specify a particular locale.
Potatoswatter
C++ has its own locale API: `std::locale` which is different from C locales. For example, there may be many instances of `std::locale` and its access is generally thread safe.
Artyom
Thank you very much! setlocale(LC_ALL, "") I think this works very best for my needs. Oops
Oops
@Oops No, it does not... See my comment
Artyom
A: 

The problem is that tolower()/toupper() are fundamentally broken for many locales. How do you propose toupper() should work with words containing an 'ß'? What would be the all-upper-case of "Maße"?[1] There are similar examples in French and other languages.

So the first thing to ask yourself is why you need this and what you want to achieve.

If you're willing to ignore all these problems, here is the first treatment on the topic google found me. (If you're going to google for more of this, James Kanze has over the years posted many many useful insights into this problem in quite a few of the C++ newsgroups.)

[1] A hint for the few non-Germans hanging out here :): In German, the "ß", literally a ligature of "sz", is not available as a capital letter. It can be replaced by "ss", but not always. For example, "Masse" is a completely different word than "Maße".

sbi
Why 'fundamentally broken'? its not something that can be 'fixed'. Its how the language 'is'
Adrian
@Adrian: As I wrote, there isn't an upper-case/lower-case equivalent for all letters in all locales. And where there is one, it's not always a 1:1 mapping of characters. (The `'ß'`, for example, maps to `"SS"` - well, at least mostly, with "Maße" being a prominent exception.) And even if you take this into account, the mapping is often context sensitive. (Not all `"SS"`map to `'ß'`) If you just want to convert a DOS filename (ASCII <128), you're fine. If you want it to work reliably in all circumstances, I don't think any one person could come up with a working algorithm.
sbi
Strictly speaking, there is a Capital ß: http://en.wikipedia.org/wiki/Capital_%C3%9FIt's only used in some obscure corner cases in typesetting, however.
Joachim Sauer
@Joachim: That article says: "There have been repeated attempts to introduce an upper case ß." and "If you use all-caps, the current spelling rules require to replace the ß with SS."
sbi
@sbi: I know. So while "Capital ß" is *available*, it's not *used*. Tiny difference, I know ;-)
Joachim Sauer
@Joachim: I see your point.
sbi
+4  A: 

You need to apply it in different way:

for(unsigned i=0;i<str.size();i++)
   str[i]=std::toupper(str[i],loc);

Or set global locale

std::locale::global(std::locale("Germany_german"));

and then

std::transform( str.begin(), str.end(), str.begin(), std::toupper );

See: http://www.cplusplus.com/reference/std/locale/tolower/

Note 1 C toupper is different from std::toupper which receives std::locale as parameter it uses char only as parameter while std::toupper works on both char and wchar_t.

Note 2 std::locale is quite broken for German because it works on character basis and can't convert "ß" to "SS" but it would work for most of other characters...

Note 3: If you need correct case conversion including handling characters like "ß", you need use good localization library like ICU, or Boost.Locale

Artyom