单片机---ESP8266中utf8转gbk中文标点问题解决

之前写了两篇文章
单片机—ESP8266模块开发
单片机—ESP8266中oled中文显示(完美方案)

背景

今天在测试过程中发现了中文标点存在问题。
在oled中文显示中,我们用到了一个查表法进行utf-8转gbk的方式,经过实验,发现中文能够翻译出来,但是一些全角的标点,例如中文的逗号,句号,感叹号等,翻译的不正确。
这样会就导致在显示中文标点的时候,会死机或者乱码。在这里插入图片描述

问题解决

首先,我们要明确HZK库中的点阵数据是全的,这是一个完整的字库,所以,现在原因就出在这个函数当中

int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen)
{
	int i = 0;
	int j = 0, nLen;
	unsigned short unicode;
	unsigned short gbk;
	for(; i < nBufInLen; i++, j++)
	{
		if((pszBufIn[i] & 0x80) == 0x00)
		{
			nLen = 1;
			pszBufOut[j]= pszBufIn[i];
		}
		/*else if((pszBufIn[i] & 0xE0) == 0xC0)
		{
			nLen = 2;
			unicode = (pszBufIn[i] & 0x1F << 6) | (pszBufIn[i+1]& 0x3F);
		}*/
		else if ((pszBufIn[i] & 0xF0) == 0xE0)
		{
			if (i+ 2 >= nBufInLen) return -1; 
			unicode = (((int)(pszBufIn[i] & 0x0F)) << 12) | (((int)(pszBufIn[i+1] & 0x3F)) << 6) | (pszBufIn[i+2]  & 0x3F); 
			gbk = mb_uni2gb_table[unicode-0x4e00];
			pszBufOut[j]= gbk/256;
			pszBufOut[j+1] = gbk%256;
			j++;
			i+=2;
		}
		else
		{
			return -1;
		}
	}
	*pnBufOutLen = j;
	fprintf(stderr,"pnbufoutlen=%d\n",*pnBufOutLen);
	return 0;
}

其中,utf-8转化为unicode的时候,是没有问题的,但是这个unicode,在这个代码中是存在范围限制的,因为这个全局数组mb_uni2gb_table有个长度,所以unicode必须有这个限制。

((unicode>0x4e00)&&(unicode<0x9fa6))

而我们通过转化一个中文标点,比如“,”,发现它的unicode已经超过这个范围了,也就是这个查表法查询的表,并不完整……
在这里插入图片描述
那我们就需要主动一点,将它翻译不了的范围之外的数字,做一个对照翻译,例如,我们计算逗号的unicode值为0xff0c
逗号的gbk编码是0xa3ac
在这里插入图片描述
那么我们就主动给它返回a3ac,然后在查找HZK的时候,就不会出问题了。
因此修改了版本代码如下。(在表的结尾,补充了中文标点)

//补充中文标点
0xa1ef,
0xa3ba,0xa3ac,0xa1a3,0xa1a2,//冒号逗号顿号
0xa1b6,0xa1b7,//书名号
0xa3bf,0xa3a1,//问号感叹号
0xa1b0,0xa1b1,//双引号
0xa3a8,0xa3a9,//括号
0xa3db,0xa3dd,//中括号
0xa3bb,0xa1e6,//分号和摄氏度
0xa3a4,0xa1ad,//人民币和省略号半个

};

unsigned short chinese_code(unsigned short unicode)
{
	if((unicode>0x4e00)&&(unicode<0x9fa6))
		return (unicode-0x4e00);
	else if(unicode == 0xff1a) //冒号
		return 20903;
	else if(unicode == 0xff0c) //逗号
		return 20904;
	else if(unicode == 0x3002) //句号
		return 20905;
	else if(unicode == 0x3001) //顿号
		return 20906;
	else if(unicode == 0x300a) //《
		return 20907;
	else if(unicode == 0x300b) //》
		return 20908;
	else if(unicode == 0xff1f) //?
		return 20909;
	else if(unicode == 0xff01) //!
		return 20910;
	else if(unicode == 0x201c) //“
		return 20911;
	else if(unicode == 0x201d) //”	
		return 20912;
	else if(unicode == 0xff08) //(	
		return 20913;
	else if(unicode == 0xff09) //)
		return 20914;
	else if(unicode == 0x3010) //【	
		return 20915;
	else if(unicode == 0x3011) //】
		return 20916;
	else if(unicode == 0xff1b) //分号
		return 20917;
	else if(unicode == 0x2103) //摄氏度
		return 20918;
	else if(unicode == 0xffe5) //人民币
		return 20919;
	else if(unicode == 0x2026) //省略号
		return 20920;
	else
		return 20902;
}
int SwitchToGbk(const unsigned char* pszBufIn, int nBufInLen, unsigned char* pszBufOut, int* pnBufOutLen)
{
	int i = 0;
	int j = 0, nLen;
	unsigned short unicode;
	unsigned short gbk;
	unsigned short table_sign;
	
	for(i=0; i < nBufInLen; i++, j++)
	{
		if((pszBufIn[i] & 0x80) == 0x00)		//英文字符
		{
			nLen = 1;
			pszBufOut[j]= pszBufIn[i];
		}
		/*		
		else if((pszBufIn[i] & 0xE0) == 0xC0)// 2λ
		{
			nLen = 2;
			unicode = (pszBufIn[i] & 0x1F << 6) | (pszBufIn[i+1]& 0x3F);
		}*/
		else if ((pszBufIn[i] & 0xF0) == 0xE0) // 中文 
		{
			
 			if (i+ 2 >= nBufInLen) 
				return -1; 
			unicode = (((int)(pszBufIn[i]&0x0F))<<12)|(((int)(pszBufIn[i+1]&0x3F))<<6)|(pszBufIn[i+2]&0x3F); 

			//中文标点补充判断,
			table_sign=chinese_code(unicode);
			gbk = mb_uni2gb_table[table_sign];
			pszBufOut[j]= gbk/256;
			pszBufOut[j+1] = gbk%256;
			j++;
			i+=2;
		}
		else
		{
			return -1;
		}
	}
	*pnBufOutLen = j;
	return 0;
}

这样,就可以完美的支持中文标点符号了
在这里插入图片描述
如果还想添加其他符号,也可以继续扩展那个转化函数。或者说换个思路,可以补充出一个完整的转化表格用来查找,但是感觉没必要,把日常能用的文字标点补充上就可以了,没必要浪费宝贵的flash资源。

新版代码下载

utf-8转gbkc语言完美版,并支持扩展

题外话

今天是圣诞节,有人说,过什么国外的节日,那都是西方国家的,放在几年以前,我也这么想,但是现在随着年龄增大,可能想的更深刻了一些,我们虽然过洋节,但是我并不想知道这个节日的由来,也不知道它要纪念什么或者表达什么,我们只是今天,为了健康吃个苹果,为了庆祝周末,吃顿好吃的,大家一起玩,小孩子也开心,玩点新玩具,放点小烟花。经济拉动了,生活幸福感也提高了,至于洋鬼子的神,对不起,不认识。
在这里插入图片描述
今天老板找我谈话,觉得我对他有意见,我说没有,完全没有,你定的那些制度,我是绝对的赞同。
为什么这么说,其实现实就是这样,所有人(除了老板自己)没有一个没有意见的,但是没有任何人去提,但他们却希望有人去提,然后坐享其成。但是我也不差这点假期,何苦为难自己呢。

人性啊,也很难想象当初的共产党人如何做到那么团结的。在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖哥王老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值