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

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

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

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

4

Решение

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

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

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

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

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

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

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

6

Другие решения

Как показал Барт, 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
3

По вопросам рекламы [email protected]