如何“解码”UTF-8 字符?

2024-02-25

假设我想编写一个函数来比较两个 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 编码的字符一点也不容易。最好不要尝试。任何一个:

  1. 将它们都转换为宽格式(32 位整数)并进行算术比较。看wstring_convert或您最喜欢的供应商特定功能;或者

  2. 将它们转换为 1 个字符串并使用比较 UTF-8 编码字符串的函数。在 C++ 中没有标准方法可以做到这一点,但它是其他语言(如 Ruby、PHP 等)的首选方法。


需要明确的是,困难的是获取编码为 UTF_8 的原始位/字节/字符并进行比较。这是因为您的比较必须考虑编码才能知道是比较 8 位、16 位还是更多。如果您可以以某种方式将原始数据位转换为以空结尾的字符串,那么使用常规字符串函数进行比较就非常容易。该字符串的长度可能超过一个字节/八位字节,但它将表示单个字符/代码点。


Windows 是一个特殊情况。宽字符是短整型(16 位)。从历史上看,这意味着 UCS-2,但它已被重新定义为 UTF-16。这意味着基本多语言平面 (BMP) 中的所有有效字符都可以直接比较,因为它们将占用一个短整型,但其他字符则不能。我不知道有什么简单的方法可以在 Windows 上的 BMP 之外处理 32 位宽字符(表示为简单的 int)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何“解码”UTF-8 字符? 的相关文章

随机推荐

  • Tizen WEB 应用程序在 2.2 版本中无法运行

    我是 Tizen 的新手 并通过在 64 位 Windows 7 计算机中将 SDK 版本设置为 2 2 来开始开发 我创建了一个新的 WEB 应用程序 在尝试运行它 在模拟器和真实设备上 时 安装后没有任何反应 我尝试了几次启动该应用程序
  • Windows 上 PyCharm 中 numpy 的安装

    当我尝试在 Pycharm Windows 中安装 numpy 时 我不断收到错误 这是我得到的错误 C Python27 lib distutils dist py 267 UserWarning 未知的分发选项 define macro
  • cmd.exe 的 CSS 字体系列

    我在CSS中找不到任何与CMD exe中使用的字体系列类似的字体系列 请你帮助我好吗 您可以使用 font family monospace 指定您希望使用等宽字体 控制台使用等宽字体以确保所有字符具有相同的宽度 请注意 某些浏览器无法正确
  • 如何访问在条件匹配组 Javascript 正则表达式中导致匹配的表达式?

    我有一个条件匹配分组正则表达式 例如 sun bmoon 当我访问字符串中的匹配项时 我希望能够看到导致匹配的表达式 let regex sun bmoon let match regex exec moon return bmoon 这可
  • 通俗地说,Java 中的“静态”是什么意思? [复制]

    这个问题在这里已经有答案了 我被告知了它的几个定义 查看了维基百科 但作为 Java 的初学者 我仍然不确定它的含义 有人精通 Java 吗 static 意味着标记为此类的变量或方法在类级别可用 换句话说 您不需要创建该类的实例来访问它
  • 如何使用 RefersToRange?

    谁能告诉我如何在vba中使用RefersToRange 以及什么时候需要它 请先提供简单的例子 提前致谢 在Excel中 有一个概念 命名范围 这是一个带有名称的单元格范围 这由Name https msdn microsoft com e
  • 刷新 firebase id 令牌服务器端

    我正在开发一个使用 Next js 13 和带有 id 令牌的 firebase auth 的应用程序 我想利用服务器端组件的 Next JS 内置功能来更快地获取用户数据 因此我需要在初始请求时验证服务器上的 id 令牌 当没有用户登录受
  • 使用pdfminer从pdf中提取文本给出多个副本

    我正在尝试使用 PDFMiner 从 PDF 文件中提取文本 代码位于在Python中使用PDFMiner从PDF文件中提取文本 https stackoverflow com questions 26494211 extracting t
  • 以编程方式选择 jqGrid 中的所有行?

    以编程方式选择设置为多选的 jqGrid 中的所有行的最佳方法是什么 该代码可以一次循环遍历所有行并选择每一行 但不会选中网格标题中的复选框 我正在考虑只触发标题行复选框的单击事件 但这会对底层 jqGrid 实现做出假设 一定会有更好的办
  • 使用动态规划将球分配到“给定容量的箱子”中

    我想知道如何使用DP解决这样的问题 给定 n 个球和 m 个箱子 每个箱子有 max 容量 c1 c2 cm 将这 n 个球分配到这 m 个箱子中的方式总数是多少 我面临的问题是 如何找到递归关系 当容量都是单个常数 c 时我可以 将有多个
  • 如何在 django 中安排将来某个时间发送电子邮件?

    我想安排在执行特定操作时向用户发送电子邮件 但是 如果用户采取其他操作 我想取消该电子邮件并且不发送它 我该如何在 django 或 python 中做到这一点 豆茎 如果可以安装的话豆茎 http kr github com beanst
  • C 的 GCD 函数

    Q 1 问题5 可整除 我尝试了蛮力法 但是需要时间 所以我参考了几个网站 找到了这段代码 include
  • ChartJS 甜甜圈图表渐变填充

    因此 我尝试为 ChartJS 圆环图进行渐变填充 但这仅适用于水平方向 而不适用于圆形 这是我正在使用的代码 var ctx document getElementById chart area getContext 2d var gra
  • 仅显示 shell_exec('df') 中磁盘使用数据的特定列

    我正在尝试编写一个 PHP 脚本来执行用于报告的 shell 函数 我从磁盘使用报告开始 我想要以下格式 drive path total size free space 没有其他的 我的脚本是 output shell exec df h
  • 我可以在 TCPDF 中使用“旧式”(非衬里)数字吗?

    Unicode 不区分衬里数字 与大写字母具有相同的比例 在表格中很有用 但在运行文本中很突出 和非衬里数字 它们看起来更像小写字母 具有上升部分和下降部分 因为它认为它们是彼此的变体 不过 许多字体都具有两组数字 并提供了一种在它们之间进
  • Mozilla firefox 无法使用 window.onbeforeunload

    我在用着window onbeforeunload在窗口关闭时向用户显示消息 该功能在 Chrome 和 IE 上运行良好 但在 Firefox 上不起作用 我使用的是 Firefox 版本26 0我已经尝试了很多 但没有任何意义 有人说这
  • 如何通过解耦的后端和前端进行社交身份验证(Passport / Express / React)

    我正在尝试使用 PassportJS Express 后端和 React JS 前端来进行社交身份验证 但是 我不确定如何去做 我做了一些阅读并实现了社交身份验证 当使用 Google Auth 登录时 它会返回由 Express 应用程序
  • 是否建议在 bash 脚本中捕获 SIGPIPE?

    我在使用系统调用命令从 C 执行 bash 脚本时遇到问题 该脚本捕获了一个SIGPIPE发出信号并退出并返回代码141 这个问题只在我的代码的最后一个版本中开始出现 我的问题如下 为什么这个 SIGPIPE 现在出现而以前没有出现 忽略
  • 带脚本的文本编辑器...适用于 Linux

    一段时间以来 我一直在我的 Windows 机器上使用 UltraEdit 事实证明 使用熟悉的语言 JavaScript 编写脚本的能力非常有用 唯一的问题是我无法在工作时在我的 Linux 机器上使用它 是否有在 Linux 上运行并具
  • 如何“解码”UTF-8 字符?

    假设我想编写一个函数来比较两个 Unicode 字符 我该怎么做呢 我读了一些文章 比如this http en wikipedia org wiki UTF 8 但还是没明白 让我们来 作为输入 已经在范围内了0x0800 and 0xF