gpt4 book ai didi

c - UTF-16 解码器未按预期工作

转载 作者:太空狗 更新时间:2023-10-29 15:03:02 26 4
gpt4 key购买 nike

我有一部分 Unicode 库可以将 UTF-16 解码为原始 Unicode 代码点。但是,它没有按预期工作。

这是代码的相关部分(省略了 UTF-8 和字符串操作内容):

typedef struct string {
unsigned long length;
unsigned *data;
} string;

string *upush(string *s, unsigned c) {
if (!s->length) s->data = (unsigned *) malloc((s->length = 1) * sizeof(unsigned));
else s->data = (unsigned *) realloc(s->data, ++s->length * sizeof(unsigned));
s->data[s->length - 1] = c;
return s;
}

typedef struct string16 {
unsigned long length;
unsigned short *data;
} string16;

string u16tou(string16 old) {
unsigned long i, cur = 0, need = 0;
string new;
new.length = 0;
for (i = 0; i < old.length; i++)
if (old.data[i] < 0xd800 || old.data[i] > 0xdfff) upush(&new, old.data[i]);
else
if (old.data[i] > 0xdbff && !need) {
cur = 0; continue;
} else if (old.data[i] < 0xdc00) {
need = 1;
cur = (old.data[i] & 0x3ff) << 10;
printf("cur 1: %lx\n", cur);
} else if (old.data[i] > 0xdbff) {
cur |= old.data[i] & 0x3ff;
upush(&new, cur);
printf("cur 2: %lx\n", cur);
cur = need = 0;
}
return new;
}

它是如何工作的?

string 是一个包含 32 位值的结构,string16 用于 16 位值,如 UTF-16。 upush 所做的就是将完整的 Unicode 代码点添加到 string,并根据需要重新分配内存。

u16tou 是我关注的部分。它循环遍历 string16,正常传递非代理值,并将代理对转换为完整代码点。放错位置的代理将被忽略。

一对中的第一个代理项将其最低的 10 位向左移动 10 位,从而形成最终代码点的高 10 位。另一个代理项将其最低的 10 位添加到最后一个,然后附加到字符串。

问题是什么?

让我们试试最高的代码点,好吗?

U+10FFFD,最后一个有效的 Unicode 代码点,在 UTF-16 中被编码为 0xDBFF 0xDFFD。让我们尝试对其进行解码。

string16 b;
b.length = 2;
b.data = (unsigned short *) malloc(2 * sizeof(unsigned short));
b.data[0] = 0xdbff;
b.data[1] = 0xdffd;
string a = u16tou(b);
puts(utoc(a));

使用 utoc(未显示;我知道它正在工作(见下文))函数将其转换回 UTF-8 char * 以进行打印,我可以在我的终端中看到我得到的是 U+0FFFFD,而不是 U+10FFFD

在计算器中

gcalctool 中手动进行所有转换会导致相同的错误答案。所以我的语法本身没有错,但算法错了。虽然该算法对我来说似乎是正确的,但它以错误的答案结束。

我做错了什么?

最佳答案

解码代理对时需要加上0x10000;报价rfc 2781 ,您缺少的步骤是第 5 步:

    1) If W1 < 0xD800 or W1 > 0xDFFF, the character value U is the value       of W1. Terminate.    2) Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence       is in error and no valid character can be obtained using W1.       Terminate.    3) If there is no W2 (that is, the sequence ends with W1), or if W2       is not between 0xDC00 and 0xDFFF, the sequence is in error.       Terminate.    4) Construct a 20-bit unsigned integer U', taking the 10 low-order       bits of W1 as its 10 high-order bits and the 10 low-order bits of       W2 as its 10 low-order bits.    5) Add 0x10000 to U' to obtain the character value U. Terminate.

ie. one fix would be to add an extra line after your first read:

cur = (old.data[i] & 0x3ff) << 10;
cur += 0x10000;

关于c - UTF-16 解码器未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3787297/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com