Как преобразовать строку std::u32string в нижний регистр?
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
Сохранив оригинал строки.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Если оригинал нужно сохранить, то придётся предварительно откопировать строку.
Для преобразования в нижний регистр можно воспользоваться функцией tolower из пространства имён std, применив её к каждому символу строки. В С++ (в отличии от С), есть перегруженный вариант этой функции, принимающий в качестве дополнительного параметра локаль (locale). Он-то нам и нужен. Само собой, локаль должна быть Russian, если хочешь, чтобы понижение регистра работало и для русских символов.
Небольшая заметка, касающаяся конкретно MinGW. В 32-битной версии нет стандартной русской локали. Мне пришлось руками написать фасет (facet) ctype, и проставить его в стандартную сишную локаль, чтобы алгоритм заработал для русских символов. Судя по форумам, знающие люди пишут, что в 64-битной версии компилятора этот недочёт устранён. Я ещё это не проверял, но так как у тебя именно такой компилятор, то можешь попробовать и рассказать нам получилось ли.
Для преобразования в нижний регистр можно воспользоваться функцией tolower из пространства имён std, применив её к каждому символу строки. В С++ (в отличии от С), есть перегруженный вариант этой функции, принимающий в качестве дополнительного параметра локаль (locale). Он-то нам и нужен. Само собой, локаль должна быть Russian, если хочешь, чтобы понижение регистра работало и для русских символов.
Небольшая заметка, касающаяся конкретно MinGW. В 32-битной версии нет стандартной русской локали. Мне пришлось руками написать фасет (facet) ctype, и проставить его в стандартную сишную локаль, чтобы алгоритм заработал для русских символов. Судя по форумам, знающие люди пишут, что в 64-битной версии компилятора этот недочёт устранён. Я ещё это не проверял, но так как у тебя именно такой компилятор, то можешь попробовать и рассказать нам получилось ли.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Как раз только их преобразование и обязательно.Romeo писал(а):если хочешь, чтобы понижение регистра работало и для русских символов.
Говорит, чтоRomeo писал(а):принимающий в качестве дополнительного параметра локаль (locale). Он-то нам и нужен. Само собой, локаль должна быть Russian
.'Russian' was not declared in this scope|
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Покажи, как локаль создал. Такое ощущение, что Russian ты пытаешься использовать, как идентификатор.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ну да. А как надо?Romeo писал(а):Покажи, как локаль создал. Такое ощущение, что Russian ты пытаешься использовать, как идентификатор.
Что это такое и как его писать?Romeo писал(а):Мне пришлось руками написать фасет (facet) ctype, и проставить его в стандартную сишную локаль
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Судя по форумам, на MinGW 64 должно работать вот так:Сионист писал(а):Ну да. А как надо?
Код: Выделить всё
std::wstring ws(L"some Русский текст");
std::locale loc("Russian");
std::transform(ws.begin(), ws.end(), ws.begin(), std::bind2nd(std: :p tr_fun(&std::tolower<wchar_t>), loc));
Но мне на практике проверить не удалось, так как MinGW 32, которым я пользуюсь, не поддерживает русскую кодировку (кидает исключение в конструкторе std::locale, если передать что-то, кроме пустой строки). Мне пришлось пойти окольными путями.
Как написать фасет расскажу, если попробуешь со стандартной локалью, и у тебя ничего не получится. А вообще, этот вопрос гуглится с полпинка. Начинать нужно с конструктора locale, который принимает оригинальную локаль и facet.Сионист писал(а):Что это такое и как его писать?
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аварийное завершение с зелёным прогрессбаром.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Ты c "ru_RU.UTF-8" тоже пробовал запускать?
А если в try взять и сделать catch(...), тогда что?
Подозреваю, что летит эксепшн из конструктора std::locale. И, если так, то тогда врут на форуме, что на MinGW 64 всё исправлено. Тогда нужно свой фасет делать. Можешь мой взять (см. следующие 2 сообщения, по лимиту символов не влазит в это).
Проставляется этот фасет в локаль вот таким образом:
Будь осторожней, если собираешься возвращаться локаль из функции или делать её статической. Дело в том, что она не владеет фасетами, а лишь содержит поинтеры на них (так стандартом положено). Так что если локаль будешь делать статической, чтобы использовать во всём проекте одну, то фасет тоже статическим делай.
А если в try взять и сделать catch(...), тогда что?
Подозреваю, что летит эксепшн из конструктора std::locale. И, если так, то тогда врут на форуме, что на MinGW 64 всё исправлено. Тогда нужно свой фасет делать. Можешь мой взять (см. следующие 2 сообщения, по лимиту символов не влазит в это).
Проставляется этот фасет в локаль вот таким образом:
Код: Выделить всё
russian_ctype rct;
std::locale loc(std::locale(), &rct);
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Код: Выделить всё
class russian_ctype : public std::ctype<wchar_t>
{
using _base = std::ctype<wchar_t>;
public:
russian_ctype() = default;
protected:
virtual wchar_t do_toupper(wchar_t __c) const override
{
using toupper_vec_base = std::vector<std: :p air<wchar_t, wchar_t>>;
static class toupper_vec : public toupper_vec_base
{
public:
toupper_vec() : toupper_vec_base()
{
reserve(33);
push_back(std::make_pair(L'а', L'А'));
push_back(std::make_pair(L'б', L'Б'));
push_back(std::make_pair(L'в', L'В'));
push_back(std::make_pair(L'г', L'Г'));
push_back(std::make_pair(L'д', L'Д'));
push_back(std::make_pair(L'е', L'Е'));
push_back(std::make_pair(L'ё', L'Ё'));
push_back(std::make_pair(L'ж', L'Ж'));
push_back(std::make_pair(L'з', L'З'));
push_back(std::make_pair(L'и', L'И'));
push_back(std::make_pair(L'й', L'Й'));
push_back(std::make_pair(L'к', L'К'));
push_back(std::make_pair(L'л', L'Л'));
push_back(std::make_pair(L'м', L'М'));
push_back(std::make_pair(L'н', L'Н'));
push_back(std::make_pair(L'о', L'О'));
push_back(std::make_pair(L'п', L'П'));
push_back(std::make_pair(L'р', L'Р'));
push_back(std::make_pair(L'с', L'С'));
push_back(std::make_pair(L'т', L'Т'));
push_back(std::make_pair(L'у', L'У'));
push_back(std::make_pair(L'ф', L'Ф'));
push_back(std::make_pair(L'х', L'Х'));
push_back(std::make_pair(L'ц', L'Ц'));
push_back(std::make_pair(L'ч', L'Ч'));
push_back(std::make_pair(L'ш', L'Ш'));
push_back(std::make_pair(L'щ', L'Щ'));
push_back(std::make_pair(L'ъ', L'Ъ'));
push_back(std::make_pair(L'ы', L'Ы'));
push_back(std::make_pair(L'ь', L'Ь'));
push_back(std::make_pair(L'э', L'Э'));
push_back(std::make_pair(L'ю', L'Ю'));
push_back(std::make_pair(L'я', L'Я'));
// Сортировка необходима из-за нестандартного положения буквы 'ё' в таблице символов
std::sort(begin(), end(), [](const_reference ref1, const_reference ref2) -> bool
{
return (ref1.first < ref2.first);
});
}
} vec;
auto it = std::lower_bound(vec.begin(), vec.end(), __c,
[](toupper_vec::const_reference ref, wchar_t __c) -> bool
{
return (ref.first < __c);
});
if (it != vec.end() && it->first == __c)
{
return it->second;
}
return _base::do_toupper(__c);
}
virtual const wchar_t* do_toupper(wchar_t* __lo, const wchar_t* __hi) const override
{
for (wchar_t* curr = __lo; curr != __hi; ++curr)
{
*curr = do_toupper(*curr);
}
return __lo;
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Код: Выделить всё
virtual wchar_t do_tolower(wchar_t __c) const override
{
using tolower_vec_base = std::vector<std: :p air<wchar_t, wchar_t>>;
static class tolower_vec : public tolower_vec_base
{
public:
tolower_vec() : tolower_vec_base()
{
reserve(33);
push_back(std::make_pair(L'А', L'а'));
push_back(std::make_pair(L'Б', L'б'));
push_back(std::make_pair(L'В', L'в'));
push_back(std::make_pair(L'Г', L'г'));
push_back(std::make_pair(L'Д', L'д'));
push_back(std::make_pair(L'Е', L'е'));
push_back(std::make_pair(L'Ё', L'ё'));
push_back(std::make_pair(L'Ж', L'ж'));
push_back(std::make_pair(L'З', L'з'));
push_back(std::make_pair(L'И', L'и'));
push_back(std::make_pair(L'Й', L'й'));
push_back(std::make_pair(L'К', L'к'));
push_back(std::make_pair(L'Л', L'л'));
push_back(std::make_pair(L'М', L'м'));
push_back(std::make_pair(L'Н', L'н'));
push_back(std::make_pair(L'О', L'о'));
push_back(std::make_pair(L'П', L'п'));
push_back(std::make_pair(L'Р', L'р'));
push_back(std::make_pair(L'С', L'с'));
push_back(std::make_pair(L'Т', L'т'));
push_back(std::make_pair(L'У', L'у'));
push_back(std::make_pair(L'Ф', L'ф'));
push_back(std::make_pair(L'Х', L'х'));
push_back(std::make_pair(L'Ц', L'ц'));
push_back(std::make_pair(L'Ч', L'ч'));
push_back(std::make_pair(L'Ш', L'ш'));
push_back(std::make_pair(L'Щ', L'щ'));
push_back(std::make_pair(L'Ъ', L'ъ'));
push_back(std::make_pair(L'Ы', L'ы'));
push_back(std::make_pair(L'Ь', L'ь'));
push_back(std::make_pair(L'Э', L'э'));
push_back(std::make_pair(L'Ю', L'ю'));
push_back(std::make_pair(L'Я', L'я'));
// Сортировка необходима из-за нестандартного положения буквы 'ё' в таблице символов
std::sort(begin(), end(), [](const_reference ref1, const_reference ref2) -> bool
{
return (ref1.first < ref2.first);
});
}
} vec;
auto it = std::lower_bound(vec.begin(), vec.end(), __c,
[](tolower_vec::const_reference ref, wchar_t __c) -> bool
{
return (ref.first < __c);
});
if (it != vec.end() && it->first == __c)
{
return it->second;
}
return _base::do_tolower(__c);
}
virtual const wchar_t* do_tolower(wchar_t* __lo, const wchar_t* __hi) const override
{
for (wchar_t* curr = __lo; curr != __hi; ++curr)
{
*curr = do_tolower(*curr);
}
return __lo;
}
};
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.