![](/img/trans.png)
[英]Printing to stderr on cmd fails to print first character of non-ASCII UTF-8 text
[英]UTF-8 decoder fails on non-ASCII characters
注意:如果您关注了我最近的问题,您会发现它们全都与我在C中的Unicode库有关-作为我在C中的头几个重要项目之一,我遇到了很多问题,所以我对不起,如果我对一件事问太多问题。
我的库的一部分将UTF-8编码的char
指针解码为原始的unsigned
代码点。 但是,某些平面无法正确解码。 让我们看一下(相关的)代码:
typedef struct string {
unsigned long length;
unsigned *data;
} string;
// really simple stuff
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;
}
// UTF-8 conversions
string ctou(char *old) {
unsigned long i, byte = 0, cur = 0;
string new;
new.length = 0;
for (i = 0; old[i]; i++)
if (old[i] < 0x80) upush(&new, old[i]);
else if (old[i] < 0xc0)
if (!byte) {
byte = cur = 0;
continue;
} else {
cur |= (unsigned)(old[i] & 0x3f) << (6 * (--byte));
if (!byte) upush(&new, cur), cur = 0;
}
else if (old[i] < 0xc2) continue;
else if (old[i] < 0xe0) {
cur = (unsigned)(old[i] & 0x1f) << 6;
byte = 1;
}
else if (old[i] < 0xf0) {
cur = (unsigned)(old[i] & 0xf) << 12;
byte = 2;
}
else if (old[i] < 0xf5) {
cur = (unsigned)(old[i] & 0x7) << 18;
byte = 3;
}
else continue;
return new;
}
顺便说一句,所有upush
所做的就是将代码点压入string
的末尾,根据需要重新分配内存。 ctou
进行解码工作,并以字节为单位存储序列中仍需要的byte
,以及以cur
为单位存储进行中的代码点。
该代码对我来说似乎都是正确的。 让我们尝试解码U+10ffff
,它是UTF-8中的f4 8f bf bd
。 这样做:
long i;
string b = ctou("\xf4\x8f\xbf\xbd");
for (i = 0; i < b.length; i++)
printf("%z ", b.data[i]);
应该打印出来:
10ffff
但是它打印出来:
fffffff4 ffffff8f ffffffbf ffffffbd
它基本上是UTF-8的四个字节,前面加上ffffff
。
关于我的代码有什么问题的任何指导?
允许对char类型进行签名,并且先转换为int然后再进行无符号转换(当您直接转换为unsigned时隐式发生)会显示以下错误:
#include <stdio.h>
int main() {
char c = '\xF4';
int i = c;
unsigned n = i;
printf("%X\n", n);
n = c;
printf("%X\n", n);
return 0;
}
印刷品:
FFFFFFF4
FFFFFFF4
请改用unsigned char。
您可能已经忽略了char
是平台上的带符号类型这一事实。 始终使用:
unsigned char
如果要读取字节的实际值) signed char
char
代表抽象字符串,在这里您不需要关心任何值,除了0之外。 顺便说一句,您的代码效率极低。 而不是一遍又一遍地按字符调用realloc
,为什么不先分配sizeof(unsigned)*(strlen(old)+1)
,然后如果太大则减小其大小? 当然,这只是许多低效率中的一种。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.