1

我有一些现有的 Visual C++ 代码,我需要将宽字符串转换为大写或小写。

我知道这有一些陷阱(例如土耳其语的“I”),但如果您了解该语言,其中大部分都可以解决。幸运的是,在这部分代码中,我知道 LCID 值(区域设置 ID),我猜这与了解语言相同。

由于 LCID 是 Windows 类型,是否有 Windows 函数可以将宽字符串转换为大写或小写?

C 运行时函数 _towupper_l() 听起来很理想,但它需要一个 _locale_t 参数而不是 LCID,所以我猜它是不合适的,除非有一种完全可靠的方法将 LCID 转换为 _locale_t。

4

1 回答 1

0

您正在搜索的函数被调用LCMapString,它是 Windows NLS API 的一部分。LCMAP_UPPERCASE标志将字符映射为大写,而将LCMAP_LOWERCASE字符映射为小写。

对于面向 Windows Vista 及更高版本的应用程序,有一个Ex变体适用于语言环境名称而不是标识符,微软现在说你应该更喜欢使用标识符。

事实上,在 VS 2010(可能还有其他版本)提供的 CRT 实现中,诸如此类的函数_towupper_l最终LCMapString会在它们从指定的_locale_t.

如果您像我一样,对 i8n API 的熟悉程度低于应有的程度,那么您可能已经了解CharUpperCharLowerCharUpperBuffCharLowerBuff系列函数。这些是 Windows 早期用于更改字符/字符串大小写的旧备用,但正如他们的文档警告的那样:

请注意CharXxx,即使当前语言是土耳其语或阿塞拜疆语,也始终将大写 I 映射到小写 I(“i”)。如果您需要在这方面对语言敏感的函数,请调用LCMapString.

Michael Kaplan 关于国际化问题的精彩博客上的几篇文章填补了它忽略提及的内容:“语言外壳”是什么意思?,如何最好地改变大小写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.
}
于 2013-02-07T18:57:18.627 回答