Преобразовать регистр широких символов, учитывая LCID (Visual C++)

У меня есть некоторый существующий код Visual C++, где мне нужно добавить преобразование строк широких символов в верхний или нижний регистр.

Я знаю, что в этом есть подводные камни (например, турецкое "Я"), но большинство из них можно устранить, если вы знаете язык. К счастью, в этой области кода я знаю значение LCID (ID локали), которое, как я полагаю, совпадает со знанием языка.

Поскольку LCID относится к типу Windows, существует ли функция Windows, которая преобразует широкие строки в верхний или нижний регистр?

Runtime-функция C _towupper_l() звучит так, как будто она идеальна, но вместо LCID принимает параметр _locale_t, поэтому я думаю, что она не подходит, если нет абсолютно надежного способа преобразования LCID в _locale_t.

1 ответ

Функция, которую вы ищете, называется LCMapString и это часть API-интерфейсов Windows NLS. LCMAP_UPPERCASE флаг отображает символы в верхний регистр, а LCMAP_LOWERCASE отображает символы в нижний регистр

Для приложений, ориентированных на Windows Vista и более поздние версии, существует Ex вариант, который работает с именами локалей, а не идентификаторами, которые, по словам Microsoft, вы должны использовать.

Фактически, в реализации CRT, предоставляемой с VS 2010 (и, возможно, и с другими версиями), такие функции, как _towupper_l в конечном итоге звонит LCMapString после того, как они извлекают идентификатор локали (LCID) из указанного _locale_t,

Если вы похожи на меня и менее знакомы с API i8n, чем должны быть, вы, вероятно, уже знаете о CharUpper, CharLower, CharUpperBuff, а также CharLowerBuff семейство функций. Это были старые резервы с ранних дней Windows для изменения регистра символов / строк, но, как предупреждает их документация:

Обратите внимание, что CharXxx всегда отображает верхний регистр I в нижний регистр I ("i"), даже если текущий язык турецкий или азербайджанский. Если вам нужна функция, чувствительная в этом отношении к лингвистическому LCMapString,

То, что он игнорирует, упоминается в нескольких постах в замечательном блоге Майкла Каплана по вопросам интернационализации: что означает "лингвистический корпус"? Как лучше всего переделать дело. Резюме заключается в том, что вы достигаете тех же результатов, что и CharXxx семейство функций путем вызова LCMapString и не указав LCMAP_LINGUISTIC_CASING флаг, в то время как вы можете быть лингвистически чувствительными, гарантируя, что вы действительно указываете LCMAP_LINGUISTIC_CASING флаг.

Образец кода:

std::wstring test("Does my code pass the Turkey test?");
if (!LCMapStringW(lcid,            /* your LCID, defined elsewhere */
                  LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING,
                  test.c_str(),    /* input string */
                  test.length(),   /* length of input string */
                  &test[0],        /* output buffer (can reuse input) */
                  test.length()))  /* length of output buffer (same as input) */
{
   // Uh-oh! Something went wrong in the call to LCMapString, so you need to
   // handle the error somehow here.
   // A good start is calling GetLastError to determine the error code.
}
Другие вопросы по тегам