C语言将字符转十六进制

在格式转换中,对于字符的处理,需要知道几种编码格式。下面这两篇博客对unicode,utf-8有比较详细的描述。

https://blog.csdn.net/zhusongziye/article/details/84261211?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/qq_24326765/article/details/82183167

这篇博客讲的是,首先从内存中读入一个字符,然后将字符通过格式转换,转成另一种格式的字符串(16进制)。

这里会用到几个关键技术:

Unicode 与 UTF-8 互转

1. UTF-8 的编码规则是:

① 对于单字节的符号,字节的第一位设为 0,后面的7位为这个符号的 Unicode 码,因此对于英文字母,UTF-8 编码和 ASCII 码是相同的。 

② 对于n字节的符号(n>1),第一个字节的前 n 位都设为 1,第 n+1 位设为 0,后面字节的前两位一律设为 10,剩下的没有提及的二进制位,全部为这个符号的 Unicode 码 。

举个例子:比如说一个字符的 Unicode 编码是 130,显然按照 UTF-8 的规则一个字节是表示不了它(因为如果是一个字节的话前面的一位必须是 0),所以需要两个字节(n = 2)。

根据规则,第一个字节的前 2 位都设为 1,第 3(2+1) 位设为 0,则第一个字节为:110X XXXX,后面字节的前两位一律设为 10,后面只剩下一个字节,所以后面的字节为:10XX XXXX。

所以它的格式为 110XXXXX 10XXXXXX 。

那么对于一个具体的 Unicode 编号,具体怎么进行 UTF-8 的编码呢?

首先找到该 Unicode 编号所在的编号范围,进而可以找到与之对应的二进制格式,然后将该 Unicode 编号转化为二进制数(去掉高位的 0),最后将该二进制数从右向左依次填入二进制格式的 X 中,如果还有 X 未填,则设为 0 。

比如:“马”的 Unicode 编号是:0x9A6C,整数编号是 39532,对应第三个范围(2048 - 65535),其格式为:1110XXXX 10XXXXXX 10XXXXXX,39532 对应的二进制是 1001 1010 0110 1100,将二进制填入进入就为: 

11101001 10101001 10101100 。

 

2. 将UTF-8转换成Unicode

继续拿上面的数值举例,现在有一个UTF-8编码为1110XXXX 10XXXXXX 10XXXXXX的字符,如何转换成Unicode?

UTF-8: 11101001 10101001 10101100

(1) 将*current_char指向低位地址的11101001,*(current_char+1)则指向的是中间字节10101001, *(current_char+2)则指向的是高位的10101100

(2) 转换第一个字节:

*current_char & 0x0F << 4 得到-> 10010000,*(current+1) &0x3C >>2 得到->00001010,接着

(*current_char & 0x0F << 4) | (*(current+1) &0x3C >>2) -> 10011010

(3) 转换第二个字节:

*(current+1) &0x03 << 6 得到->01000000,*(current+2) &0x3F>>2 得到->00101100,接着

(*(current+1) &0x03 << 6) | (*(current+2) &0x3F>>2) ->01101100

(4) 拼接两个字节:

char *unicode;

sprintf(unicode, "\\u%02X02X", (*current_char & 0x0F << 4) | (*(current+1) &0x3C >>2),

                                                  (*(current+1) &0x03 << 6) | (*(current+2) &0x3F>>2)))

下面是简化的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int dec2hex(char *in);

int main(void)
{
	//输入一个字符串
	int i, str_len;
	char *str = (char *)malloc(sizeof(char) * 12);
	str = "hello";
	char *current_char;				//当前字符

	printf("size of str = %d.\n", str_len = strlen(str));
	
	//将每一个字符放入指针
	for (i = 0; i < str_len; i++) {
		current_char = &str[i];
		printf("before convert, current_char[%d] = %c. 0d = %d. \n", i, *current_char, (int)*current_char);
		dec2hex(current_char);
	}

	//输出一个utf8
	free(str);

	return 0;
}

int dec2hex(char *in)
{
	char *utf8 = (char*)malloc(sizeof(char)*8);
	sprintf(utf8, "\\u%02X", (0x0F & *in) << 4);
	printf("after convert, current_char = %s.\n", utf8);
	return 0;
}

与运算

0,1 和 1 做与运算都得到自身,因此0x0F & char,就是取char的低四位

移位

经过与运算取到char的低四位后,<<4,左移4位,即把char的低四位顶到了高四位,原来的低四位补零

如0110 1100 & 0x0F => 0000 1100 << 4 => 1100 0000

 


结果:

size of str = 5.

before convert, current_char[0] = h. 0d = 104.

after convert, current_char = \u80.

before convert, current_char[1] = e. 0d = 101.

after convert, current_char = \u50.

before convert, current_char[2] = l. 0d = 108.

after convert, current_char = \uC0.

before convert, current_char[3] = l. 0d = 108.

after convert, current_char = \uC0.

before convert, current_char[4] = o. 0d = 111.

after convert, current_char = \uF0.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值