假设我想编写一个函数来比较两个 Unicode 字符。我该怎么做呢?我读了一些文章(比如this http://en.wikipedia.org/wiki/UTF-8)但还是没明白。让我们来€
作为输入。已经在范围内了0x0800
and 0xFFFF
所以它将使用 3 个字节对其进行编码。我该如何解码它?按位运算获取 3 个字节wchar_t
并存储到3char
是? C 示例中的代码可能很棒。
这是我要“解码”的 C 代码,但显然显示解码 unicode 的错误值...
#include <stdio.h>
#include <wchar.h>
void printbin(unsigned n);
int length(wchar_t c);
void print(struct Bytes *b);
// support for UTF8 which encodes up to 4 bytes only
struct Bytes
{
char v1;
char v2;
char v3;
char v4;
};
int main(void)
{
struct Bytes bytes = { 0 };
wchar_t c = '€';
int len = length(c);
//c = 11100010 10000010 10101100
bytes.v1 = (c >> 24) << 4; // get first byte and remove leading "1110"
bytes.v2 = (c >> 16) << 5; // skip over first byte and get 000010 from 10000010
bytes.v3 = (c >> 8) << 5; // skip over first two bytes and 10101100 from 10000010
print(&bytes);
return 0;
}
void print(struct Bytes *b)
{
int v1 = (int) (b->v1);
int v2 = (int)(b->v2);
int v3 = (int)(b->v3);
int v4 = (int)(b->v4);
printf("v1 = %d\n", v1);
printf("v2 = %d\n", v2);
printf("v3 = %d\n", v3);
printf("v4 = %d\n", v4);
}
int length(wchar_t c)
{
if (c >= 0 && c < 0x007F)
return 1;
if (c >= 0x0080 && c <= 0x07FF)
return 2;
if (c >= 0x0800 && c <= 0xFFFF)
return 3;
if (c >= 0x10000 && c <= 0x1FFFFF)
return 4;
if (c >= 0x200000 && c <= 0x3FFFFFF)
return 5;
if (c >= 0x4000000 && c <= 0x7FFFFFFF)
return 6;
return -1;
}
void printbin(unsigned n)
{
if (!n)
return;
printbin(n >> 1);
printf("%c", (n & 1) ? '1' : '0');
}
比较 UTF-8 编码的字符一点也不容易。最好不要尝试。任何一个:
将它们都转换为宽格式(32 位整数)并进行算术比较。看wstring_convert
或您最喜欢的供应商特定功能;或者
将它们转换为 1 个字符串并使用比较 UTF-8 编码字符串的函数。在 C++ 中没有标准方法可以做到这一点,但它是其他语言(如 Ruby、PHP 等)的首选方法。
需要明确的是,困难的是获取编码为 UTF_8 的原始位/字节/字符并进行比较。这是因为您的比较必须考虑编码才能知道是比较 8 位、16 位还是更多。如果您可以以某种方式将原始数据位转换为以空结尾的字符串,那么使用常规字符串函数进行比较就非常容易。该字符串的长度可能超过一个字节/八位字节,但它将表示单个字符/代码点。
Windows 是一个特殊情况。宽字符是短整型(16 位)。从历史上看,这意味着 UCS-2,但它已被重新定义为 UTF-16。这意味着基本多语言平面 (BMP) 中的所有有效字符都可以直接比较,因为它们将占用一个短整型,但其他字符则不能。我不知道有什么简单的方法可以在 Windows 上的 BMP 之外处理 32 位宽字符(表示为简单的 int)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)