C库将unicode代码点转换为UTF8?

cha*_*nux 10 c unicode utf-8

我必须经历一些文本并根据字符模式编写UTF8输出.我认为如果我可以使用代码点并将其转换为UTF8将会很容易.我一直在阅读有关unicode和UTF8的内容,但无法找到一个好的解决方案.任何帮助将不胜感激.

R..*_*R.. 36

将Unicode代码点转换为UTF-8是如此微不足道,以至于调用库可能需要的代码多于自己执行的代码:

if (c<0x80) *b++=c;
else if (c<0x800) *b++=192+c/64, *b++=128+c%64;
else if (c-0xd800u<0x800) goto error;
else if (c<0x10000) *b++=224+c/4096, *b++=128+c/64%64, *b++=128+c%64;
else if (c<0x110000) *b++=240+c/262144, *b++=128+c/4096%64, *b++=128+c/64%64, *b++=128+c%64;
else goto error;
Run Code Online (Sandbox Code Playgroud)

另外,自己动手意味着你可以将api调整到你需要的工作类型(一次一个字符?还是长字符串?)如果你知道输入是有效的Unicode标量值,你可以删除错误情况.

另一个方向更难以纠正.我建议使用有限自动机方法,而不是典型的位算术循环,有时会将无效序列解码为真实字符的别名(这非常危险并且可能导致安全问题).

编辑:即使你最终选择了图书馆,我认为你应该先尝试自己编写,或者至少认真学习UTF-8规范,然后才能进一步学习.很多糟糕的设计都可以将UTF-8当作一个黑盒子来处理,因为它不是一个黑盒子而是被创建为具有非常强大的属性,并且太多UTF-8的程序员都没有看到这个他们自己也经常使用它.

  • @Philipp:是否正在编写更多代码来封装库以满足您的接口需求并更好地解决它的错误?如果您想要浏览解码UTF-8的现有库代码,您会发现绝大多数都是错误的,至少是微妙的方式,并且至少30%有严重的安全关键错误.(这些估计来自我之前做过的谷歌代码搜索.)此外,`iconv`的GNU实现对于一次一次转换的转换速度太慢,尽管它可以正常工作(尽管有意不合格) )用于批量转换. (6认同)
  • 拒绝非字符可能对您的应用程序有用,但它不是UTF-8规范的一部分,通常是不正确的.UTF是代码单元序列(字节或更大的单词)和"Unicode标量值"之间的一对一映射.Unicode标量值正好是整数0-0xD7FF和0xE000-0x10FFFF.这都是在Unicode标准中定义的,您应该在尝试实现自己的东西之前阅读它. (2认同)
  • @R.. : 请解释一下什么是`b`,什么是`c`!什么变量代表代码点?。初始化为哪个值`b`? (2认同)

use*_*374 5

iconv可以用于我的身材.

#include <iconv.h>

iconv_t cd;
char out[7];
wchar_t in = CODE_POINT_VALUE;
size_t inlen = sizeof(in), outlen = sizeof(out);

cd = iconv_open("utf-8", "wchar_t");
iconv(cd, (char **)&in, &inl, &out, &outlen);
iconv_close(cd);
Run Code Online (Sandbox Code Playgroud)

但是我担心wchar_t可能不代表Unicode代码点,而是代表任意值.编辑:我想你可以通过简单地使用Unicode源来实现:

uint16_t in = UNICODE_POINT_VALUE;
cd = iconv_open("utf-8", "ucs-2");
Run Code Online (Sandbox Code Playgroud)

  • 如果代码点不在BMP中怎么办?ucs-2无法代表它.根据平台,一个wchar_t可能还不够.这就是为什么我认为OP关于知道代码点的假设是错误的.因为那时,问了用于表示它的编码问题(UTF-32?UTF-16?显然不是UTF-8) (2认同)
  • 16 位“wchar_t”肯定可以在 UTF-16 编码字符串中使用。它的意思是,BMP 之外的任何代码点值都将使用编码字符串中并排的 2 个“wchar_t”代理字符进行编码,仅此而已。Windows API 正是针对此类数据进行操作,并且工作得很好。 (2认同)