5

我正在开发一个基本的手工编码词汇扫描器,并希望支持 UTF-8 输入(它不再是 1970 年了!)。stdin一次从一个文件中读取输入字符,然后将其推入缓冲区,直到看到空格等。我考虑为此编写自己的包装器fgetc(),而不是返回char[]构成 UTF-8 字符并与结果作为一个字符串......这很容易,但会变成一个滑坡。我不想浪费时间重新发明轮子,而是使用现有的、经过测试的库,如ICU。所以现在我有一个非 UTF-8 支持代码,它适用于fgetc(), isspace(),strcmp()等,我正在尝试更新以使用 ICU。这是我第一次尝试 ICU,并且一直在阅读文档并尝试使用 Google 代码搜索查找使用示例,但仍然存在一些混淆点,我希望有人能够澄清。

u_fgetc()函数返回UChar,并u_fgetcx()返回UChar32......文档建议使用u_fgetcx()来读取代码点,所以这就是我开始的内容。我保持与上面相同的方法,但我将UChar32s 推入缓冲区而不是chars。

  • 将字符与已知值进行比较的正确方法是什么?最初我能够if (c == '+')检查是否从输入中获取了加号。GCC 不会抱怨什么时候c是 a UChar32(然后是和之间的比较UChar32char,但这真的合适吗?

  • 我可以用来strcmp()将缓冲的字符与已知值进行比较,例如if ((strcmp(buf, "else") == 0). ICU提供u_strcmp()了,我想我可能需要使用U_STRING_DECLandU_STRING_INIT宏来指定已知的文字,但我不确定。文档显示它们会导致UChar[],尽管我认为我需要UChar32[]......而且我不确定如何正确使用它们。欢迎在这里提供任何指导。

  • 在阅读了一系列数字字符后,我一直在转换它们,strtol()以便可以使用它们。自从我现在转换以来,ICU 是否提供了类似的功能UChar32[]

4

2 回答 2

5

UChar用于持有代码单元,而UChar32用于持有代码点。如果您的输入停留在基本多语言平面(BMP) 上,UChar就足够了,而且实际上大多数 ICU 功能都在UChar[].

强烈推荐阅读ICU 用户指南,它解释了大部分内部知识和最佳实践。

  • 将 Unicode 字符变量与已知值进行比较的正确方法是什么? 字符(或UCharUChar32)只是另一种具有一定宽度和符号的整数类型,并且可以与具有通常警告和限制的其他整数类型进行比较。至于定义字符值,C99(第 6.4.3 章)提供通用字符名称表示法:\u后跟四个十六进制数字,或\U后跟八个十六进制数字,指定 ISO/IEC 10646“短标识符”。0x00a0 以下的区域(0x0024、0x0040'$''@'0x0060(反引号)除外)被保留(但可以通过将简单的字符常量转换为UChar)。还保留了从 0xd800 到 0xdfff 的范围(供 UTF-16 使用)。

  • 如何定义 Unicode 字符串文字? 确实是您正在寻找的东西U_STRING_DECL。(如上所述,U_STRING_INITICU 主要对UChar[].UNICODE_STRING_SIMPLEgetTerminatedBuffer()UChar[]

  • 如何将表示数字的 Unicode 字符串转换为该数字的值? unum_parse()它的弟兄们unum.h会在那里帮助你。

于 2011-06-01T05:33:00.300 回答
2
  1. PLUS SIGN 的 Unicode 值是 U+002B,“+”的正常 (Latin-1) 值也是 0x2B (053, 43)。在代码集基于 ASCII 或 ISO-8859-x 的情况下,您编写的内容足够安全。C99 标准提供了 Unicode(通用字符名称)的形式\u0123\U00102345(具有 4 位和 8 位十六进制数字),但规定您不能指定小于 的值\u00A0,例如\u002B. 所以,我认为你写的是正确的。

    但是,您可以通过使用enum诸如

     enum { PLUS_SIGN = '+' };
    

    在适当的标题中定义并在需要文字加号的任何地方使用。这样,如果您的假设(和我的假设)是错误的,您可以在一个地方进行编辑 - 标题。

    我注意到Strings with ICU 的页面表明在应用程序中使用 UTF-32 是不寻常的。

  2. 在纯 C 中,您可能会使用wcscmp(buf, L"else"),假设wchar_t您系统上的 等价于uint32_t和/或 UChar32。似乎有一些方法可以使用UnicodeStringUNICODE_STRING("...")随后ToUTF32()创建一个 UTF-32 字符串。也可能有更整洁的方法。

  3. 有处理格式化和解析的“格式化”类。您可能会使用从该类派生的NumberFormat类。

于 2011-06-01T05:39:46.050 回答