7

I am working on a C++ project that need to get data from unicode text. I have a problem that I can't lower some unicode character. I use wchar_t to store unicode character which read from a unicode file. After that, I use _wcslwr to lower a wchar_t string. There are many case still not lower such as:

Đ Â Ă Ê Ô Ơ Ư Ấ Ắ Ế Ố Ớ Ứ Ầ Ằ Ề Ồ Ờ Ừ Ậ Ặ Ệ Ộ Ợ Ự

which lower case is:

đ â ă ê ô ơ ư ấ ắ ế ố ớ ứ ầ ằ ề ồ ờ ừ ậ ặ ệ ộ ợ ự 

I have try tolower and it is still not working.

UmNyobe
  • 22,539
  • 9
  • 61
  • 90
Nguyên Phan
  • 133
  • 1
  • 8
  • 1
    welcome to stack overflow!! – UmNyobe Dec 23 '15 at 10:22
  • 3
    The standard library is incapable of doing this correctly, you need a decent library. Also dealing with the trickier corner cases, like the lower-case of `ß` is `ss`, from one char to two. The ICU library is pretty popular in C++ land. – Hans Passant Dec 23 '15 at 10:29
  • 1
    if the number of characters that you need to convert to lower is small, you can define yout own mapping arrayinstead of using libraries. – ManKeer Dec 23 '15 at 10:39

1 Answers1

5

If you call only tolower, it will call std::tolower from header clocale which will call the tolower for ansi character only.

The correct signature should be:

template< class charT >
charT tolower( charT ch, const locale& loc );

Here below is 2 versions which works well:

#include <iostream>
#include <cwctype>
#include <clocale>
#include <algorithm>
#include <locale>

int main() {
    std::setlocale(LC_ALL, "");
    std::wstring data = L"Đ Â Ă Ê Ô Ơ Ư Ấ Ắ Ế Ố Ớ Ứ Ầ Ằ Ề Ồ Ờ Ừ Ậ Ặ Ệ Ộ Ợ Ự";
    std::wcout << data << std::endl;

    // C std::towlower
    for(auto c: data)
    {
        std::wcout << static_cast<wchar_t>(std::towlower(c));
    }
    std::wcout << std::endl;

    // C++ std::tolower(charT, std::locale)
    std::locale loc("");
    for(auto c: data)
    {
        // This is recommended
        std::wcout << std::tolower(c, loc);
    }
    std::wcout << std::endl;
    return 0;
}

Reference:

Danh
  • 5,916
  • 7
  • 30
  • 45