我正在研究一种基本的手工编码词法扫描仪,并希望支持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()
来读取代码点,这就是我的意思从...开始。我保持与上面相同的方法,但我将UChar32
推入缓冲区而不是char
s。
将字符与已知值进行比较的正确方法是什么?最初我能够if (c == '+')
检查加号是否是从输入中获取的。当c
为UChar32
时,GCC不会抱怨(这是UChar32
和char
之间的比较),但这是否合适?
我能够使用strcmp()
将缓冲的字符与已知值进行比较,例如if ((strcmp(buf, "else") == 0)
。 ICU提供了u_strcmp()
,我想我可能需要使用U_STRING_DECL
和U_STRING_INIT
宏来指定已知文字,但我不确定。文档显示它们导致UChar[]
,但我认为我需要UChar32[]
...而且我不确定如何正确使用它们。欢迎任何指导。
在阅读了一系列数字字符后,我一直用strtol()
转换它们,所以我可以使用它们。 ICU是否提供类似功能,因为我现在转换UChar32[]
?
答案 0 :(得分:5)
UChar
用于保存代码单元,而UChar32
用于保存代码点。如果您的输入保留在Basic Multilingual Plane(BMP)上,则UChar
就足够了,而且大多数ICU功能都会在UChar[]
上运行。
强烈推荐的阅读是ICU User Guide,它解释了大多数内部和最佳实践。
将Unicode字符变量与已知值进行比较的正确方法是什么?
字符(或UChar
或UChar32
)只是具有一定宽度和符号的另一个整数类型,并且可以与其他整数类型进行比较,具有通常的警告和限制。至于定义字符值,C99(第6.4.3章)提供通用字符名称表示法:\u
后跟四个十六进制数字,或{{1}后跟八个十六进制数字,指定ISO / IEC 10646“短标识符”。低于0x00a0的区域(除了0x0024 \U
,0x0040 '$'
和0x0060(反引号)之外的区域是保留的(但可以通过将简单字符常量转换为'@'
来表示)。还保留是从0xd800到0xdfff的范围(供UTF-16使用)。
如何定义Unicode字符串文字? UChar
和U_STRING_DECL
确实是您正在寻找的。 (如上所述,ICU主要在U_STRING_INIT
上运行。)如果您使用C ++而不是C,UNICODE_STRING_SIMPLE
(可选地后跟UChar[]
再次产生getTerminatedBuffer()
)提供了更方便的定义Unicode字符串文字的方法。
如何将表示数字的Unicode字符串转换为该数字的值? unum_parse()
及其UChar[]
中的兄弟会帮助您。
答案 1 :(得分:2)
PLUS SIGN的Unicode值为U + 002B,“+”的正常(Latin-1)值也为0x2B(053,43)。您编写的内容足够安全,代码集基于ASCII或ISO-8859-x。 C99标准提供了\u0123
和\U00102345
形式的Unicode(通用字符名称)(带有4和8个十六进制数字),但规定您不能指定小于\u00A0
的值,例如为\u002B
。所以,我认为你写的是正确的。
但是,您可以使用enum
(例如
enum { PLUS_SIGN = '+' };
在适当的标题中定义,并在需要文字加号时使用。这样,如果你的假设(和我的假设)是错误的,你就有一个地方可以编辑 - 标题。
我注意到Strings与ICU的页面表明在应用程序中使用UTF-32是不寻常的。
在纯C中,您可能会使用wcscmp(buf, L"else")
,假设系统上的wchar_t
等同于uint32_t
和/或UChar32。似乎有办法使用UnicodeString
和UNICODE_STRING("...")
后跟ToUTF32()
来创建UTF-32字符串。可能还有更简洁的方法。
有'格式化'类可以处理格式化和解析。您可能会使用从NumberFormat
类派生的类。