不依赖任何系统API,用c语言实现gbk/utf8/unicode编码转换

汉字'我'
Unicode编码是 0x6211       0110 0010 00 010001
UTF8编码是    0xe68891    1110 0110 10 001000 100 010001
oxc0 11000000
0xE0 11100000    
    |  Unicode符号范围               |  UTF-8编码方式
 n |  (十六进制)                          | (二进制)
---+----------------------- -----------+--------------------------------------------------------------------------
 1 | 0x00  - 0x7F                        |                                                                              0zzzzzzz
 2 | 0x80  - 0x7FF                      |                                                              110yyyyy 10zzzzzz
 3 | 0x800 - 0xFFFF                  |                                               1110xxxx 10yyyyyy 10zzzzzz
--------------------------------------------------------------------------------------------------------------------
 4 | 0x10000     -  0x1FFFFF     |                                 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
 5 | 0x200000   -  0x3FFFFFF   |                 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
 6 | 0x4000000 -  0x7FFFFFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

                                         表 UTF-8的编码规则

一:unicode转utf8

'我'的unicode编码0x6211,二进制为:01100010 00010001
将二进制形式分割成3段为0110 001000
010001 (分别是高4位、中间的6位、最后的低6位)
unicode转utf8只需要这3段分别填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx yyyyyy zzzzzz
得utf8编码是0xe6889,二进制为: 11100110 10001000 100010001

int UnicodeToUtf8(char* pInput, char *pOutput)  
{  
	int len = 0; //记录转换后的Utf8字符串的字节数
	while (*pInput)
	{
		//处理一个unicode字符
		char low = *pInput;//取出unicode字符的低8位
		pInput++;
		char high = *pInput;//取出unicode字符的高8位
		int w=high<<8;
		unsigned  wchar = (high<<8)+low;//高8位和低8位组成一个unicode字符,加法运算级别高

		if (wchar <= 0x7F ) //英文字符
		{   
			pOutput[len] = (char)wchar;  //取wchar的低8位
			len++;
		}  
		else if (wchar >=0x80 && wchar <= 0x7FF)  //可以转换成双字节pOutput字符
		{  
			pOutput[len] = 0xc0 |((wchar >> 6)&0x1f);  //取出unicode编码低6位后的5位,填充到110yyyyy 10zzzzzz 的yyyyy中
			len++;
			pOutput[len] = 0x80 | (wchar & 0x3f);  //取出unicode编码的低6位,填充到110yyyyy 10zzzzzz 的zzzzzz中
			len++;
		}  
		else if (wchar >=0x800 && wchar < 0xFFFF)  //可以转换成3个字节的pOutput字符
		{  
			pOutput[len] = 0xe0 | ((wchar >> 12)&0x0f);  //高四位填入1110xxxx 10yyyyyy 10zzzzzz中的xxxx
			len++;
			pOutput[len] = 0x80 | ((wchar >> 6) & 0x3f);  //中间6位填入1110xxxx 10yyyyyy 10zzzzzz中的yyyyyy
			len++;
			pOutput[len] = 0x80 | (wchar & 0x3f);  //低6位填入1110xxxx 10yyyyyy 10zzzzzz中的zzzzzz
			len++;
		}  

		else //对于其他字节数的unicode字符不进行处理
		{
			return -1;
		}
		pInput ++;//处理下一个unicode字符
	}
	//utf8字符串后面,有个\0
	pOutput [len]= 0;
	return len;  
}  

二:utf8转unicode

utf8二进制形式为1110xxxx 10yyyyyy 10zzzzzz
'我'的utf8编码0xe6889,二进制为:1110 0110 10 001000 10 0010001
分别提取里面的xxxx yyyyyy zzzzzz,然后组合成xxxxyyyy yyzzzzzz,
xxxxyyyy就是unicode的高8位,yyzzzzzz就是unicode的低8位

/*************************************************************************************************
* 将UTF8编码转换成Unicode(UCS-2LE)编码  低地址存低位字节
* 参数:
*    char* pInput     输入字符串
*    char*pOutput   输出字符串
* 返回值:转换后的Unicode字符串的字节数,如果出错则返回-1
**************************************************************************************************/
//utf8转unicode
int Utf8ToUnicode(char* pInput, char* pOutput)
{
	int outputSize = 0; //记录转换后的Unicode字符串的字节数

	while (*pInput)
	{
		if (*pInput > 0x00 && *pInput <= 0x7F) //处理单字节UTF8字符(英文字母、数字)
		{
			*pOutput = *pInput;
			 pOutput++;
			*pOutput = 0; //小端法表示,在高地址填补0
		}
		else if (((*pInput) & 0xE0) == 0xC0) //处理双字节UTF8字符
		{
			char high = *pInput;
			pInput++;
			char low = *pInput;
			if ((low & 0xC0) != 0x80)  //检查是否为合法的UTF8字符表示
			{
				return -1; //如果不是则报错
			}

			*pOutput = (high << 6) + (low & 0x3F);
			pOutput++;
			*pOutput = (high >> 2) & 0x07;
		}
		else if (((*pInput) & 0xF0) == 0xE0) //处理三字节UTF8字符
		{
			char high = *pInput;
			pInput++;
			char middle = *pInput;
			pInput++;
			char low = *pInput;
			if (((middle & 0xC0) != 0x80) || ((low & 0xC0) != 0x80))
			{
				return -1;
			}
			*pOutput = (middle << 6) + (low & 0x3F);//取出middle的低两位与low的低6位,组合成unicode字符的低8位
			pOutput++;
			*pOutput = (high << 4) + ((middle >> 2) & 0x0F); //取出high的低四位与middle的中间四位,组合成unicode字符的高8位
		}
		else //对于其他字节数的UTF8字符不进行处理
		{
			return -1;
		}
		pInput ++;//处理下一个utf8字符
		pOutput ++;
		outputSize += 2;
	}
	//unicode字符串后面,有两个\0
	*pOutput = 0;
	 pOutput++;
	*pOutput = 0;
	return outputSize;
}
//一个调用示例
int main(int argc, char** argv)
{
	//汉字“我”的UTF8编码是0xe68891,Unicode编码是 0x6211

	//1、unicode转utf8
	char unicodeStr[3]={0x11,0x62,0x00};//我的unicode编码是0x6211,按低地址存低位字节
	char* utf8Str = new char [5];
	memset(utf8Str,0,5);
	int num = UnicodeToUtf8(unicodeStr,utf8Str);

	unsigned char* p = (unsigned char*)utf8Str;   
	for (int i = 0; i < num; i++)
	{
		printf("%0x", *p);
		p++;
	}//输出e68891
	printf("\n");
	delete utf8Str;

	//2、utf8转unicode
	//char utf8Str[4] = {0xe6, 0x88, 0x91, 0x00}; 
	//char* unicodeStr = new char[8];
	//memset(unicodeStr,0,8);
	//int num = Utf8ToUnicode(utf8Str, unicodeStr);
	//if (num == -1)
	//{
	//	printf("Error!\n");
	//}
	//else
	//{
	//       unsigned char* p = (unsigned char*)unicodeStr;
	//	for (int i = 0; i < num; i++)
	//	{
	//		printf("%0x", *p);
	//		p++;
	//	}//输出1162
	//	printf("\n");
	//}
	//delete unicodeStr;

	return 0;
} 

三、gbk与unicode互转


参照博客:

http://blog.csdn.net/tge7618291/article/details/7599902
http://www.ithao123.cn/content-1832906.html



  • 12
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
### 回答1: GBK和UTF-8是两种不同的字符编码方式,GBK是中国的编码方式,而UTF-8是一种国际通用的编码方式。在实际开发过程中,由于不同平台和程序使用的编码方式不同,会出现需要进行GBK和UTF-8之间的互转的情况。 在C语言中,实现GBK和UTF-8的互转,可以使用iconv函数。iconv函数是一个系统函数,用于进行字符编码转换。在进行转换的时候,需要提供源编码和目标编码,同时也需要传入需要进行转换的字符串和字符串的长度。 具体的实现过程如下: 1. 获取需要转换的字符串和字符串的长度。 2. 定义iconv_t类型的变量,用于存储转换方式。 3. 调用iconv_open函数,打开转换方式,获取iconv_t类型的变量。 4. 定义一个用于存储转换后字符串的char数组和数组长度。 5. 调用iconv函数,将源编码的字符串转换为目标编码的字符串。 6. 关闭iconv_t类型的变量。 7. 返回转换后的字符串。 下面是一个简单的示例代码: ``` #include <iconv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char gbk_str[100] = "这是一个GBK编码的字符串"; char utf8_str[100] = {0}; char *inbuf = gbk_str; char *outbuf = utf8_str; size_t inlen = strlen(gbk_str); size_t outlen = strlen(utf8_str); iconv_t ic = iconv_open("utf-8","gbk"); if(ic == (iconv_t)-1) { perror("iconv_open"); exit(1); } int ret = iconv(ic, &inbuf, &inlen, &outbuf, &outlen); if(ret == -1) { perror("iconv"); exit(1); } printf("gbk_str: %s\nutf8_str: %s\n", gbk_str, utf8_str); iconv_close(ic); return 0; } ``` 这段代码将一个GBK编码的字符串转换为UTF-8编码的字符串,最终输出转换后的字符串。可以看到,使用iconv函数可以非常方便地进行编码转换。 ### 回答2: GBK和UTF-8是两种常见的字符编码方式,它们的字节长度和编码规则不同。如何进行互转呢?我们可以通过C语言实现。 首先,需要了解GBK和UTF-8编码的规则。GBK是双字节编码,每个字符占用2个字节,而UTF-8是变长编码,每个字符的字节长度不同,最长可达4个字节。 其次,需要用C语言写出转换函数。以将GBK转为UTF-8为例,可按如下步骤进行: 1. 定义两个指针,一个指向源字符串GBK,一个指向目标字符串UTF-8。 2. 使用循环遍历GBK字符串中的每个字符。 3. 如果字符的高位为0,表示该字符为ASCII字符,将该字符直接复制到UTF-8字符串中。 4. 如果字符的高位为1,表示该字符为汉字或其他非ASCII字符,需要将该字符转为UTF-8编码。 5. 将该字符的二进制形式转为Unicode编码,再根据以下规则将Unicode编码转为UTF-8编码: - 对于1字节的UTF-8编码Unicode编码的范围为U+0000~U+007F; - 对于2字节的UTF-8编码Unicode编码的范围为U+0080~U+07FF; - 对于3字节的UTF-8编码Unicode编码的范围为U+0800~U+FFFF; - 对于4字节的UTF-8编码Unicode编码的范围为U+10000~U+10FFFF。 6. 将得到的UTF-8编码复制到目标字符串UTF-8中,并移动目标字符串指针。 7. 循环结束后,在目标字符串UTF-8的末尾添加一个\0字符,表示字符串的结束。 最后,我们需要注意转换时可能会出现一些错误,如GBK字符串中包含非法字符等。因此,在实现时需要对这些情况进行判断和处理。 总的来说,通过以上步骤,我们就能够将GBK字符串转为UTF-8编码的字符串了。同样的,我们也可以实现将UTF-8字符串转为GBK编码的函数。 ### 回答3: GBK与UTF-8是两种编码格式,GBK适用于汉字编码,UTF-8适用于多语言编码。想要在C语言中进行互转需要先了解一些基本操作。 UTF-8编码格式使用变长字节,一个字符可以由1-4个字节组成,其中第一个字节有特殊标记来表示后面有几个字节是该字符的一部分。而GBK编码格式每个汉字占两个字节。 在C语言中可以使用stdlib.h库函数中的mbstowcs()和wcstombs()来进行编码转换。mbstowcs()函数可以将一个字符串转换为宽字符数组,wcstombs()函数可以将宽字符数组转换为字符串。 将GBK编码格式的字符串转换为UTF-8格式需要进行如下操作: 1. 使用mbstowcs()函数将GBK字符串转换为宽字符数组。 2. 遍历宽字符数组,使用wcstombs()函数将每个宽字符(即一个汉字或一个英文字母)转换为UTF-8格式的字节。 3. 将所有转换后的字节组合成一个字符串即为UTF-8格式的字符串。 将UTF-8编码格式的字符串转换GBK格式也需要进行类似的操作: 1. 使用mbstowcs()函数将UTF-8字符串转换为宽字符数组。 2. 遍历宽字符数组,使用wcstombs()函数将每个宽字符(即一个汉字或一个英文字母)转换GBK格式的字节。 3. 将所有转换后的字节组合成一个字符串即为GBK格式的字符串。 需要注意的是,在进行编码转换时可能会出现一些字符无法转换的问题,处理方式可以选择忽略该字符或将该字符替换为一个特定字符。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值