【问题标题】:Dealing with chars outside ASCII range处理 ASCII 范围之外的字符
【发布时间】:2011-05-02 08:26:46
【问题描述】:

我有一个 isAlpha 的查找表。

for (int i = 0; i <= UCHAR_MAX; ++i)
p.isalphaLUT[i] = isalpha(i);

其中 isalphaLUT 是一个字符数组...问题是 isalphaLUT[i] 其中 i 是 ASCII 范围之外的字符(当我尝试获取等效的 ASCII 值时,它会打印 4294967168)。我尝试将 127 以上的所有 ASCII 范围设置为 0,但这不起作用。有问题的字符是这个ö。

【问题讨论】:

  • ASCII 范围是 [0, 127],而不是 [0, 255]。
  • 我关心 ASCII [0,255]。目前 ö 应该在 0 到 255 的 ASCII 范围内。但是当我尝试打印等效值时,我得到了一些无意义的数字,并且当 i 是 ö 的 isalphaLUT[i] 应该返回 false 时返回 true 跨度>
  • ASCII 是 0..127,不是 0..255,jamesdlin 是对的。

标签: c++ arrays char


【解决方案1】:

测试字符是否为字母的正确方法是测试它是否属于以下字母类别之一:Lu、Ll、Lt、Lm 或 Lo。您可以使用 IBM 的 ICU 库来执行此操作,它是一个非常流行的用于处理 Unicode 的库。

http://icu-project.org/apiref/icu4c/uchar_8h.html

您也可以直接使用 ICU 中的u_isalpha 函数,或使用u_charType 来确定角色的类别。请注意,术语“字母”优于“字母”,因为 Unicode 中有许多非字母“字母”(例如汉字)。

但是,您必须先对字符进行解码。如果您使用的是 char 数组,那么您的编码可以是 ASCII、LATIN-1、Windows 1252、UTF-8 或无数其他编码中的任何一种。如果您直接访问char,则它可能是有符号或无符号的,具体取决于您的平台,这就是为什么您会得到一个明显错误的数字,例如 4294967168——当字节 0x80 被解释为有符号 @ 时会发生这种情况987654327@,然后转换为unsigned int

对于此类任务,使用查找表是一个非常糟糕的选择,因为该表必须非常大——大约 700k。相反,我建议使用 ICU 或创建字符范围表并在表中执行二进制搜索。这可能非常有效。

我正在开发一种工具来准确地创建这些类型的表格。该工具目前尚未准备好投入生产,但如果您喜欢冒险,您可以使用它,并且 README 中有如何使用它的示例。

https://github.com/depp/uniset

【讨论】:

    【解决方案2】:

    在使用它来索引数组之前检查字符的值是否在您的范围内怎么样?将“所有 ASCII 范围”设置为 255 以上(顺便说一句,这没有意义,我听说的所有 ASCII 定义都是单字节编码)会导致查找表相当大。

    另外,ö 确实是一个字母字符。您为什么不想像处理它一样处理它?

    【讨论】:

      【解决方案3】:

      假设您使用的是默认语言环境,isalpha() 函数将为字母 A-Z 和 a-z 返回 true - 其他任何内容都会使其返回 false。为了进一步了解这一点,您需要了解字符编码(例如 ASCII 的实际含义)和语言环境。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-06
        • 1970-01-01
        • 1970-01-01
        • 2013-06-19
        • 1970-01-01
        相关资源
        最近更新 更多