在C11(ISO/IEC 9899:2011)标准中引入了对UTF8、UTF16以及UTF32字符编码的支持。

其中,UTF8字符直接通过char来定义,字面量前缀使用u8。比如:

char c = u8'你';
const char *s = u8"你好";

而UTF16字符直接通过char16_t来定义,字面量前缀使用u。比如:

#include <uchar.h>

char16_t c = u'你';
const char16_t *s = "你好";

而UTF32字符直接通过char32_t来定义,字面量前缀使用U。比如:

#include <uchar.h>

char32_t c = U'你';
const char32_t *s = U"你好";

在使用char16_t以及char32_t的时候必须包含头文件<uchar.h>。除此之外,C11标准中还添加了诸如wsprintf、wfprintf、vwprintf、wprintf等宽字符函数。不过这些函数的字符串都是const wchar_t*类型的,即宽字符指针类型。而对于Unicode字符的显示是各家平台自己实现的。在OS X以及iOS中,至今(Apple LLVM 6.0)还没完美地支持这一C11特性,但是UTF8、UTF16以及UTF32字面量都已经支持了,尽管系统本身不支持对UTF32编码格式的解析。另外,也没有包含<uchar.h>头文件。不过,我们可以使用Foundation库自带的unichar类型来代替char16_t。另外,printf函数不支持对UTF16编码字符的打印,若要打印UTF16字符或字符串,只能用Foundation里的NSLog函数。

下面举些例子:

#include <stdio.h>
#include <wchar.h> - (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. const char *s = u8"你好,世界!";
printf("此UTF-8字符串为: %s\n", s); unichar ch = u'你';
const unichar *us = u"好,世界!";
NSLog(@"该UTF16是:%C%S", ch, us); wprintf(L"iOS does not support for printing wide-character unicodes!\n");
}

在NSString字符串格式中,%C对应类型为unichar(实际为unsigned short)的UTF16编码字符;%S对应类型为const unichar*,即UTF16编码的字符串。

由于OS X以及iOS所用的LLVM Clang编译器没有引入C11标准的<uchar.h>,因此有些UTF8与UTF16字符串的标准转换函数在这些环境下均无法支持,我们只能通过Foundation库的NSString来解决。不过,如果在Linux下,我们使用GCC4.8或更高版本的话,那么就能使用标准的C11提供的转换函数了。不过在标准C语言中,printf、puts这类打印函数只支持对UTF-8编码格式的字符串的正确打印,因此我们要输出的话需要把UTF-16编码的字符串转为UTF-8。下面介绍在标准C11情况下如果操作UTF-8、UTF16字符串,它们之间的相互转换以及打印输出。

#include <stdio.h>
#include <uchar.h> size_t UTF16StrLen(const char16_t *utf16String)
{
if(utf16String == NULL)
return ; size_t index;
for(index = ; utf16String[index] != u'\0'; index++);
return index;
} size_t UTF16ToUTF8(char *mbBuffer, const char16_t *utf16String)
{
if(mbBuffer == NULL || utf16String == NULL)
return ; mbstate_t state = { }; size_t mbIndex = ;
for(int utf16Index = ; utf16String[utf16Index] != u'\0'; utf16Index++)
{
const size_t length = c16rtomb(&mbBuffer[mbIndex], utf16String[utf16Index], &state);
mbIndex += length;
} mbBuffer[mbIndex] = '\0'; return mbIndex;
} int main(int argc, char *argv[])
{
char16_t ch = u'好';
char chBuffer[];
mbstate_t state = { }; size_t length = c16rtomb(chBuffer, ch, &state);
chBuffer[length] = '\0'; printf("The UTF-8 character length is: %zu, and the character is: %s\n", length, chBuffer); const char *utf8Str = u8"你好, 世界。";
printf("The UTF-8 string is: %s\n", utf8Str); const char16_t *utf16Str = u"你好, 世界。";
printf("The utf16 string length is: %zu\n", UTF16StrLen(utf16Str)); length = UTF16ToUTF8(chBuffer, utf16Str); printf("The UTF-8 string length is: %zu, and the content is: %s\n", length, chBuffer); printf("If the converted UTF-8 string is equal to the original one? %s\n", strcmp(chBuffer, utf8Str) == ? "YES" : "NO");
}

在上述代码中,<uchar.h>必须被包含。因为char16_t、char32_t、mbstate_t等类型都是定义在这个头文件中的。C11标准库仅提供了基本的UTF8字符串转UTF16字符串、UTF16字符转UTF8字符串等函数。但是木有提供获取UTF16字符串长度以及如何将UTF16字符串转UTF8字符串的函数。因此,我在开头就实现这两者功能。当然,上述代码对UTF16的处理基本是将它作为老式的UCS-2编码格式,因为它是双字节固定长度的,而现代的UTF16可能是双字节也可能是四字节变长的。像Apple搞出的Emoji就是四字节长度的UTF16编码。所以,对于四字节的UTF16编码而言,其转换是否能有效工作尚不可知。

由于UTF8编码格式的字符串对ASCII是兼容的,因此我们可以直接使用C90提供的strlen等标准库对它们进行操作。

C11中的Unicode的更多相关文章

  1. C#中文和UNICODE编码转换

    C#中文和UNICODE编码转换 //中文轉為UNICODE string str = "中文"; string outStr = ""; if (!strin ...

  2. C#中Encoding.Unicode与Encoding.UTF8的区别

    今天在园子首页看到一篇博文-简单聊下Unicode和UTF-8,从中知道了UTF-8是Unicode的一种实现方式: Unicode只是给这世界上每个字符规定了一个统一的二进制编号,并没有规定程序该如 ...

  3. 如何利用java把文件中的Unicode字符转换为汉字

    有些文件中存在Unicode字符和非Unicode字符,如何利用java快速的把文件中的Unicode字符转换为汉字而不影响文件中的其他字符呢, 我们知道虽然java 在控制台会把Unicode字符直 ...

  4. String 字符串中含有 Unicode 编码时,转为UTF-8

    1.单纯的Unicode 转码 String a = "\u53ef\u4ee5\u6ce8\u518c"; a = new String(a.getBytes("UTF ...

  5. Wpf中显示Unicode字符

    1. 引言 今天在写一个小工具,里面有些字符用Unicode字符表示更合适.但是一时之间却不知道怎么写了.经过一番查找,终于找到了办法.记到这里,一是加深印象,二则以备查询. 2. C#中使用Unic ...

  6. Python中的Unicode编码和UTF-8编码

    下午看廖雪峰的Python2.7教程,看到 字符串和编码 一节,有一点感受,结合崔庆才的Python博客 ,把这种感受记录下来: ASCII码:是用一个字节(8bit, 0-255)中的127个字母表 ...

  7. python2中的unicode()函数在python3中会报错:

    python2中的unicode()函数在python3中会报错:NameError: name 'unicode' is not defined There is no such name in P ...

  8. 从ord()中对Unicode编码的理解

    刚开始学习编程的时候,老对字符串编码的理解模模糊糊.也一直看这方便的资料,今天在看Dive in python时,突然有了新的理解(不知道是否正确). Python有个built-in函数ord(), ...

  9. json中含有Unicode的处理办法 C#

    public static class StringExtension { #region unicode 字符转义 /// <summary> /// 转换输入字符串中的任何转义字符.如 ...

随机推荐

  1. 【Leetcode】【简单】【283. 移动零】【JavaScript】

    题目描述 283. 移动零 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12]输出: [1,3,12,0,0] 说 ...

  2. 基于栈的指令集与基于寄存器的指令集详细比对及JVM执行栈指令集实例剖析

    基于栈的指令集与基于寄存器的指令集详细比对: 这次来学习一些新的概念:关于Java字节码的解释执行的一种方式,当然啦是一些纯理论的东东,但很重要,在之后会有详细的实验来对理论进行巩固滴,下面来了解一下 ...

  3. BZOJ 4873 寿司餐厅 网络流

    最大权闭合子图 1.每个区间收益(i,j)对应一个点 权值为正连S 负连T 2.每个区间收益向其子区间收益(i+1,j)与(i,j-1)对应的两个点连边 容量为INF 3.每个寿司类型对应一个点 连一 ...

  4. Linux 误卸载自带python后的解决办法

    1:卸载python(以免有些同学没有卸载干净) rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps #强制删除已安装程序及其关联 wher ...

  5. Nginx中ngx_http_fastcgi_module

    转发请求到 FastCGI 服务器器,不不⽀支持 php 模块⽅方式指令:15.1 fastcgi_pass设置 fastcgi 服务器器的地址.地址可以指定为域名或 IP 地址,以及端⼝口Synta ...

  6. Pycharm----破解码的获取

    网站:http://idea.lanyus.com/ 复制后,粘贴到pycharm中的激活即可

  7. docker压缩导入导出

    导出镜像 docker save <myimage>:<tag> | gzip > <myimage>_<tag>.tar.gz 导入镜像 gun ...

  8. 工作 巧遇 sql 查询 一组数据中 最新的一条

    SELECT * FROM rsl a, (SELECT CODE, max(time_key) time_key FROM rsl GROUP BY CODE ) b WHERE a. CODE = ...

  9. CF633C Spy Syndrome 2 trie树

    这个模型以前绝对见过,模拟赛的时候开始敲了一个AC自动机,纯属脑抽~ code: #include <bits/stdc++.h> #define N 5000006 #define NN ...

  10. learning armbian steps(5) ----- armbian 构建arm rootfs

    基于learning armbian step(4) 的总结,我们来实践一下,接下来的会把整个构建的log都贴出来: vmuser@vmuser-virtual-machine:~/qemu-arm$ ...