tolower() не работает для Ü,Ö в с ++

Когда я попробовал tolower() с неанглийскими символами в C++, он не работал нормально. Я искал эту проблему, и я столкнулся с кое-чем о локали, но я не уверен в лучшем решении этого.

Мой пример кода ниже:

printf("%c ",tolower('Ü'));

2 ответа

К сожалению, стандартная библиотека C++ не имеет достаточной поддержки для изменения регистра всех возможных неанглийских символов (в той части, в которой эти символы вообще имеют варианты регистра). Это ограничение вызвано тем, что стандарт C++ предполагает, что один символ и его варианты регистра занимают ровно один char объект (или wchar_t объект для широких символов) и для неанглийских символов, которые не гарантируются как истинные (также в зависимости от того, как символы кодируются).

Если ваша среда использует однобайтовую кодировку для соответствующих символов, это может дать вам то, что вы хотите:

std::cout << std::tolower('Ü', locale());

С широкими символами вам, вероятно, повезет больше:

std::wcout << std::tolower(L'Ü', locale());

но даже это не даст правильный результат для toupper(L'ß'), которая будет двухсимвольной последовательностью L"SS").

Если вам нужна поддержка всех символов, взгляните на библиотеку ICU, в частности на часть, посвященную отображению регистров

Как показал Барт, C++ просто не любит многобайтовые кодировки. К счастью, вы можете использовать Boost.Local, чтобы решить эту проблему без особых хлопот. Вот простой пример:

#include <iostream>
#include <locale>
#include <boost/locale.hpp>

int main() {
    boost::locale::generator gen;
    std::locale loc = gen("en_US.UTF-8");
    std::string line;
    while (std::getline(std::cin, line))
        std::cout << boost::locale::to_lower(line, loc) << '\n';
}

Для компиляции нам нужна ссылка на библиотеку Boost.Locale:

g++ -lboost_locale lower.cpp -o lower

И когда мы выполняем это, мы получаем следующее:

$ ./main <<< 'ICH HÄTTE GERNE EINEN SÜßEN HASEN'
ich hätte gerne einen süßen hasen
Другие вопросы по тегам