我有以下代码将字母转换为大写:
// make this character upper
if(_istalpha(zChar) && !_istupper(zChar))
pMsg->wParam = (WPARAM)_toupper(zChar);
它已经工作了多年。最近,有人要求我支持阿拉伯语,而我的用户说信件已经损坏。这是因为上面的代码。
阿拉伯语告诉我,大写字母不适用。我知道我可以测试我的程序设置,以查看它们是否使用阿拉伯语,并避免使用此代码。但是还有另一种方法吗?
例如,我知道您_tsetlocale
首先打来的日期。
更新:
找到了有关toupper的主题,其中提到了语言环境设置!会尝试的。
正如您所发现的那样,经典的转换例程(例如CRTtoupper
和Win32)CharUpper
相当愚蠢。它们通常从假定全世界都是ASCII的时间开始欢呼。
您需要的是对语言敏感的转换。这是一种计算上更昂贵的操作,同时也非常难以正确实现。语言很难。因此,您希望将责任尽可能转移到标准库中。由于使用的是MFC,显然您的目标是Windows操作系统,这意味着您很幸运。您可以背负Microsoft本地化工程师的辛勤工作,从而获得与外壳和其他OS组件一致的额外好处。
您需要调用的函数是LCMapStringEx
(或者LCMapString
如果您仍以Vista之前的平台为目标)。该函数签名的复杂性充分证明了正确的语言感知字符串处理这一复杂任务。
LOCALE_NAME_USER_DEFAULT
可以使用进行指定,但是您可以在此处使用任何内容。LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING
。要执行相反的操作,请使用LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING
。这里也要记住许多其他有趣而有用的选项。放在一起:
BOOL ConvertToUppercase(std::wstring& buffer)
{
return LCMapStringEx(LOCALE_NAME_USER_DEFAULT /* or whatever locale you want */,
LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING,
buffer.c_str(),
buffer.length(),
&buffer[0],
buffer.length(),
NULL,
NULL,
0);
}
请注意,我在这里对缓冲区的内容进行就地转换,因此假设大写字符串的长度与原始输入字符串的长度完全相同。这可能是正确的,但可能不是一个普遍安全的假设,因此您将要添加针对此类错误(ERROR_INSUFFICIENT_BUFFER
)的处理,和/或防御性地向缓冲区添加一些额外的填充。
如果您希望像现在一样使用CRT功能,_totupper_l
并且它的朋友是LCMapString
/的包装LCMapStringEx
。请注意_l
后缀,该后缀表示这些是语言环境感知的转换函数。它们允许您传递显式语言环境,该语言环境将在转换中使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句