Преобразование строки типа std::u16string к нижнему регистру

118
04 июля 2019, 08:00

Требуется преобразовать строку с кириллицей типа 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

Answer 1

Поддержки Unicode в C++ нет(*), поэтому используйте сторонние средства. Одним из наиболее известных средств является ICU. Если собрать Boost с использованием ICU, то можно использовать Boost.Locale, которая может быть удобнее.

(*) Есть некоторые «ошмётки» Unicode в C++, но они не стоят внимания.

Answer 2

Преобразование строки в нижний регистр, а также "По поводу tolower и русских букв - опропобал на лине. Действительно, не работает. Чтобы нормально преобразовывать, нужно создать строку wchar_t и далее с нею работать функцией towlower из wchar.h" – skegg 1 дек '11 в 14:56

Answer 3

Пришел к такому рабочему решению:

#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 байта. Так или иначе работает. Если есть более правильное решение прошу делиться в ответах.

Answer 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;
}
READ ALSO
error: does not name a type

error: does not name a type

ListBig* self; выдаёт ошибку - error: 'ListBig' does not name a type ListBig* self;

163
Как легко удалить из строки начальные символы такие как пробел, табуляция или символ новой строки и т.п. а также в конце?

Как легко удалить из строки начальные символы такие как пробел, табуляция или символ новой строки и т.п. а также в конце?

Как легко удалить из строки начальные символы такие как пробел, табуляция или символ новой строки и тп

153
Просмотр памяти Linux [закрыт]

Просмотр памяти Linux [закрыт]

Если для Linux инструмент (или возможность в какой-либо ide) для просмотра оперативной памяти процесса, наподобие инструмента просмотра памяти...

135
Как по нажатию кнопки Read вывести список в ListView?

Как по нажатию кнопки Read вывести список в ListView?

Эта код добавляет удаляет обновляет данные из БД все прекрасно работает но при нажатии на кнопки READ она все выводит в консоль, да так и продуманно...

161