Требуется преобразовать строку с кириллицей типа std::u16string к нижнему регистру.
Что пробовал:
1) boost::algorithm::to_lower
2) std::use_facet<std::ctype<char16_t>>(std::locale("")).tolower(&test[0],&test[0] + test.size());
3) std::transform(test.begin(), test.end(), test.begin(), ::tolower);
Пробовал устанавливать перед этим локаль:
1) std::locale("");
2) std::locale("ru");
3) std::locale("RU");
4) std::locale("ru_RU"); - вызывается исключение
Во всех случаях результат преобразования строки u"Тест" равен: "5ab, а должен быть: тест
При этом текст на латинице преобразуется правильно. Строка с кириллицей типа std::wstring также преобразуется правильно.
Пример кода для воспроизведения:
std::locale("");
std::u16string test = u"Тест";
std::transform(test.begin(), test.end(), test.begin(), ::tolower);
Условия воспроизведения:
ОС: Windows 7 64Bit Eng
Компилятор: Visual Studio 2017 Community
Кодировка файла с исходником: UTF-8 с BOM
Поддержки Unicode в C++ нет(*), поэтому используйте сторонние средства. Одним из наиболее известных средств является ICU. Если собрать Boost с использованием ICU, то можно использовать Boost.Locale, которая может быть удобнее.
(*) Есть некоторые «ошмётки» Unicode в C++, но они не стоят внимания.
Преобразование строки в нижний регистр, а также "По поводу tolower и русских букв - опропобал на лине. Действительно, не работает. Чтобы нормально преобразовывать, нужно создать строку wchar_t и далее с нею работать функцией towlower из wchar.h" – skegg 1 дек '11 в 14:56
Пришел к такому рабочему решению:
#include <string>
#include <algorithm>
#include <cwctype>
int main()
{
setlocale(LC_ALL, "");
std::u16string test = u"Тест";
std::transform(test.begin(), test.end(), test.begin(), std::towlower);
return 0;
}
То есть использовать функцию towlower. Обязательно необходимо установить локаль. Проверял под Ubuntu 14 (32-64), Mac OS Sierra, Windows Server 2008. В целом нет уверенности что это правильный подход, ведь в описании сказано, что функция towlower предназначена для обработки символов типа wchar_t, а у меня тип char16_t и под Linux wchar_t имеет размер 4 байта. Так или иначе работает. Если есть более правильное решение прошу делиться в ответах.
Есть функция tolower, которая переводит символы в нижний регистр. Можно применить ее ко всем символам строки:
#include <algorithm>
#include <iostream>
#include <string>
#include <ctype.h>
int main() {
std::string s = "IaFFSjndsUFfE";
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::cout << s << std::endl;
}
специально для минусаторов
#include <algorithm>
#include <iostream>
#include <string>
#include <ctype.h>
int main() {
std::string s ="тест";
std::transform(s.begin(), s.end(), s.begin(), tolower);
std::cout << s << std::endl;
}
рабочее решение
std::transform(test.begin(), test.end(), test.begin(), ::towlower);
Проверял под Ubuntu 14 (32-64), Mac OS Sierra, Windows Server 2008. Везде работает.
специально для минусаторов
#include <algorithm>
#include <iostream>
#include <string>
#include <ctype.h>
int main() {
std::string s = "БОЛЬШИЕ РУСКИЕ БУКВЫ";
std::transform(s.begin(), s.end(), s.begin(), ::towlower);
std::cout << s << std::endl;
}
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости