【问题标题】:Converting wide char string to lowercase in C++在 C++ 中将宽字符字符串转换为小写
【发布时间】:2010-12-09 12:47:22
【问题描述】:

如何在 C++ 中将 wchar_t 字符串从大写转换为小写?

字符串包含日文、中文、德文和希腊字符的混合体。

我考虑过使用 towlower...

http://msdn.microsoft.com/en-us/library/8h19t214%28VS.80%29.aspx

.. 但文档说:

towlower 的大小写转换是特定于语言环境的。仅更改与当前语言环境相关的字符以防大小写。

编辑:也许我应该描述一下我在做什么。我收到来自用户的 Unicode 搜索查询。它最初采用 UTF-8 编码,但我将其转换为宽字符(我的措辞可能有误)。我的调试器(VS2008)在“变量快速表”中正确显示了日文、德文等字符。我需要遍历 Unicode 中的另一组数据并找到搜索字符串的匹配项。虽然当搜索区分大小写时这对我来说没有问题,但不区分大小写则更成问题。我(可能是幼稚的)解决问题的方法是将所有输入数据和输出数据转换为小写,然后进行比较。

【问题讨论】:

  • 另一种方法是使用忽略大小写的比较算法。案例不是您唯一的问题。如果不对字符串进行规范化,例如可以将变音符号视为一个字符(éÕ)或几个单独字符('e~O)的一部分。在比较之前进行适当的标准化(NFC/NFD/NFKC/NFKD)对您的情况至关重要。
  • Abel,请将其作为正确答案发布,以便对其进行投票。在这种情况下,这几乎是唯一正确的答案......

标签: c++ lowercase widestring


【解决方案1】:

如果您的字符串包含所有这些字符,则代码集必须基于 Unicode。如果实现得当,Unicode(Chapter 4 'Character Properties')会定义字符属性,包括字符是否为大写和小写映射等。

鉴于前言,<wctype.h> 中的 towlower() 函数是正确使用的工具。如果它不能完成这项工作,那么您就有一个 QoI(实施质量)问题需要与您的供应商讨论。如果您发现供应商没有响应,请查看替代库。在这种情况下,您可以考虑ICU(Unicode 的国际组件)。

【讨论】:

  • Unicode 大小写映射,在您链接到的文档中指定,仍然部分依赖于区域设置。引用:“SpecialCasing.txt - 包含映射到多个字符的其他大小写映射,例如“ß”到“SS”。还包含依赖于上下文的映射,带有将它们与普通映射区分开来的标志,以及 一些与语言环境相关的映射。”。所以tolower 不能避免特定于语言环境。
  • @Pavel 这个过程称为“Unicode 字符串规范化”,它确保 ßss 被同等对待(取决于选择的规范化形式)并且 Unicode 包含语言中立的算法这一点,同时不忽略对语言环境或应用程序特定处理的希望。
  • @Abel:规范化不是一个完整的解决方案。例如,在某些拉丁语言中,变音符号会在大写字母上消失,而在其他语言中则不会。除非您知道文本是用哪种语言编写的,否则无法判断。当然,还有臭名昭著的土耳其无点“i”问题 - 您希望 İ 小写为 iI 小写为 @ 987654334@ 用于土耳其语,但您希望 I 小写为 i 以用于任何其他拉丁字母语言。
  • @Pavel:这是一个很好的阐述,我完全同意。不,规范化并不完美,它更像是一种简单的蛮力方法,但它在很多情况下都有帮助。可能是讨论中包含指向 Unicode 排序算法的链接的好时机,该算法完整地讨论了这一点(比小写/大写更进一步):unicode.org/reports/tr10 和 Unicode 大小写映射:unicode.org/reports/tr21/tr21-5.html
  • @JonathanLeffler:ICU 很有趣,但可能有点矫枉过正。我可能会去处理 UnicodeData.txt [编译为二进制并过滤掉不相关的部分]。
【解决方案2】:

你手头有一个讨厌的问题。日语语言环境无助于转换德语,反之亦然。有些语言也没有大写的概念(我想toupper 和朋友在这里是无用的)。那么,你能把你的字符串分解成来自同一种语言的单独的词块吗?如果可以的话,您可以转换这些片段并将它们串起来。

【讨论】:

  • 日语和来自东亚的其他表意语言是主要没有大写字母的语言示例。
  • 不仅如此,个别语言对于特定字母的大写/小写方式可能有不同的意见。在不了解语言的情况下,根本没有单一算法可以在任何随机 Unicode 字符串上正确执行此操作。
  • 虽然我同意该评估,但 Unicode 包括独立于区域设置的大写/小写属性,其用法在 3.13 “默认大小写操作” 中描述,将在没有针对特定语言进行定制的情况下使用,标准是这样说的。
  • 确实如此。问题是它适用于所有案例的 99%,但你会得到 1% 的错误。这可能是也可能不是问题。一般来说,当你将它用于代码中的标识符之类的东西时,它就足够了,甚至可能是文件名。
  • @Pavel:这意味着你不能一直做对,但你可以一直做。我知道在土耳其语中将 'I' 小写为 'i' 是错误的,但如果您只是对字符串进行规范化以进行比较而不是打印出结果,它可能工作得很好。
【解决方案3】:

This SO answer 展示了如何使用构面来处理多个语言环境。如果这是在 Windows 上,您可以考虑使用 win32 API 函数,如果您可以使用 C++.NET(托管 C++),则可以使用符合 Unicode 的 char.ToLowerstring.ToLower 函数。

【讨论】:

    【解决方案4】:

    <wchar.h> (MSDN) 中查看_wcslwr_l

    您应该能够在每个语言环境的输入上运行该函数。

    【讨论】:

    • "您应该能够在每个语言环境的输入上运行该函数。" - 如果集合中的两个语言环境映射相同的字符不同怎么办?
    • 正如在其他 cmets 中提到的,您必须了解字符串每个部分的语言以避免这些情况。真的没有办法解决这个问题。我只是建议使用不同的函数来更轻松地管理在当前语言环境下运行操作的问题。
    猜你喜欢
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-13
    相关资源
    最近更新 更多