c语言把utf-8编码转换器,[C语言]unicode与utf-8编码转换(一)

Unicode与UTF-8编码转换(一)

Unicode是一个符号集合,规定了符号的二进制代码,而UTF-8是Unicode的一种实现,具体Unicode和UTF-8的联系如下所示:

Unicode符号范围                    UTF-8编码规则

1 | 0000 0000 - 0000 007F |                                              0xxxxxxx

2 | 0000 0080 - 0000 07FF |                                     110xxxxx 10xxxxxx

3 | 0000 0800 - 0000 FFFF |                            1110xxxx 10xxxxxx 10xxxxxx

4 | 0001 0000 - 0010 FFFF |                   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

5 | 0020 0000 - 03FF FFFF |          111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

6 | 0400 0000 - 7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

由图可清晰的知道Unicode和UTF-8间的联系。其中UTF-8编码规则中的x就是让你编码的地方。接下来逐一举例说明各段的编码:

1,范围0x00-0x7F:给定的用例Unicode码为0x41,对应的二进制位:0100 0001,而UTF-8编码规则为:0xxxxxxx。故有:

0xxx  xxxx

+    100 0001

0100 0001

所以Unicode编码0x41转换为UTF-8后为:0x41。

所以对于区间段0x00-0x7F之间的Unicode和UTF-8编码是一致的。即与ASCII码一致(ASCII共规定了128个字符的编码)

2,范围0x80-0x7FF:给定的用例Unicode码为0x123,对应的二进制为:0001 0010 0011,而UTF-8编码规则为:110xxxxx 10xxxxxx。故有:

110x xxxx 10xx  xxxx

+       0 0100     10 0011

1100 0100 1010 0011

所以Unicode编码0x123转换为UTF-8后为:0xC4A3

3,范围0x800-0xFFFF:给定的用例Unicode码为0x4E25,对应的二进制为:0100 1110 0010 0101,而UTF-8编码规则为:1110xxxx 10xxxxxx 10xxxxxx,故有:

1110 xxxx 10xx  xxxx 10xx xxxx

+          0100     11 1000    10 0101

1110 0100 1011 1000 1010 0101

所以Unicode编码为0x4E25转换为UTF-8后为:0xE4B8A5

4,范围0x10000-0x10FFFF:给定的Unicode码为0x23456,对应的二进制为:0010 0011 0100 0101 0110,而UTF-8编码规则为:111100xx 10xxxxxx 10xxxxxx 10xxxxxx。故有:

1111 00xx 10xx xxxx  10xx xxxx 10xx xxxx

+           00     10  0011     01 0001    01 0110

1111 0000 1010 0011 1001 0001 1001 0110

所以Unicode编码为0x23456转换UTF-8后为:0xF0A39196

5,范围0x200000-0x3FFFFFF:给定的Unicode码为0x234567,对应的二进制为:0010 0011 0100 0101 0110 0111,UTF-8编码规则为:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。故有:

1111 10xx 10xx  xxxx 10xx xxxx  10xx xxxx 10xx xxxx

+                       00 1000    11 0100     01 0101    10 0111

1111 1000 1000 1000 1011 0100 1001 0101 1010 0111

所以Unicode编码为0x234567转换UTF-8后为:0xF888B495A7

6,范围0x4000000-0x7FFFFFFF:给定的Unicode码为0x34561234,对应的二进制为:0011 0100 0101 0110 0001 0010 0011 0100,UTF-8编码规则为:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx。故有:

1111 110x 10xx  xxxx 10xx  xxxx 10xx xxxx  10xx xxxx  10xx xxxx

+                0    11  0100    01  0101    10 0001     00 1000     11 0100

1111 1100 1011 0100 1001 0101 1010 0001 1000 1000 1011 0100

所以Unicode编码为0x34561234转换UTF-8后为:0xFCB495A188B4

1,通过以上案例分析可得如下单字符Unicode编码转UTF-8程序为:

1)由于本系统采用大头方式(Big endian),所以先打出来的是高位的值。

2)实现思路:移动指定的位数是该字节处于易于操作的位置或使操作完的值达到指定位置,使用与运算取得指定位上的值,使用或运算实现相加效果。

int

unicode_to_utf( unsigned long unicode, unsigned char *utf )

{

assert( utf );

int size = 0;

if ( unicode <= 0x7F )

{

*( utf + size++ ) = unicode & 0x7F;

}

else if ( unicode >= 0x80 && unicode <= 0x7FF )

{

*( utf + size++ ) = ( ( unicode >> 6 ) & 0x1F ) | 0xC0;

*( utf + size++ ) = ( unicode & 0x3F ) | 0x80;

}

else if ( unicode >= 0x800 && unicode <= 0xFFFF )

{

*( utf + size++ ) = ( ( unicode >> 12 ) & 0x0F ) | 0xE0;

*( utf + size++ ) = ( ( unicode >> 6  ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( unicode & 0x3F  ) | 0x80;

}

else if ( unicode >= 0x10000 && unicode <= 0x10FFFF )

{

*( utf + size++ ) = ( (unicode >> 18 ) & 0x7  ) | 0xF0;

*( utf + size++ ) = ( (unicode >> 12 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 6  ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( unicode & 0x3F ) | 0x80;

}

else if ( unicode >= 0x200000 && unicode <= 0x3FFFFFF )

{

*( utf + size++ ) = ( (unicode >> 24 ) & 0x3  ) | 0xF8;

*( utf + size++ ) = ( (unicode >> 18 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 12 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 6  ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( unicode & 0x3F ) | 0x80;

}

else if ( unicode >= 0x4000000 && unicode <= 0x7FFFFFFF )

{

*( utf + size++ ) = ( (unicode >> 30 ) & 0x1  ) | 0xFC;

*( utf + size++ ) = ( (unicode >> 24 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 18 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 12 ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( (unicode >> 6  ) & 0x3F ) | 0x80;

*( utf + size++ ) = ( unicode & 0x3F ) | 0x80;

}

else

{

printf( "Error : unknow scope\n" );

return -1;

}

*( utf + size ) = '\0';

return size;

}

测试用例如下:

int

main( int argc, char *argv[] )

{

unsigned long unicode1 = 0x55;

unsigned char utf[7] = { 0 };

int size = unicode_to_utf( unicode1, utf );

utf_print( utf, size );

unsigned long unicode2 = 0x123;

size = unicode_to_utf( unicode2, utf );

utf_print( utf, size );

memset( utf, 0x00, sizeof( utf ) );

unsigned long unicode3 = 0x4E25;

size = unicode_to_utf( unicode3, utf );

utf_print( utf, size );

memset( utf, 0x00, sizeof( utf ) );

unsigned long unicode4 = 0x23456;

size = unicode_to_utf( unicode4, utf );

utf_print( utf, size );

memset( utf, 0x00, sizeof( utf ) );

unsigned long unicode5 = 0x234567;

size = unicode_to_utf( unicode5, utf );

utf_print( utf, size );

memset( utf, 0x00, sizeof( utf ) );

unsigned long unicode6 = 0x34561234;

size = unicode_to_utf( unicode6, utf );

utf_print( utf, size );

/* error */

memset( utf, 0x00, sizeof( utf ) );

unsigned long unicode7 = 0x8FFFFFFF;

size = unicode_to_utf( unicode7, utf );

utf_print( utf, size );

return 0;

}

打印函数如下:

void

utf_print( unsigned char *utf, int size )

{

if ( size == -1 )

{

printf( "unknow scope\n" );

return;

}

int index = 0;

for ( ; index 

{

printf( "%X",  *( utf + index) );

}

printf( "\n" );

}

2,单字符UTF-8编码转Unicode编码:

int

utf_to_unicode( unsigned long utf, unsigned char *unicode )

{

int size = 0;

if ( utf <= 0x7F )

{

*( unicode + size++ ) = utf & 0x7F;

}

else if ( utf >= 0xC080 && utf <= 0xCFBF )

{

*( unicode + size++ ) = ( ( utf >> 10 ) & 0x07 );

*( unicode + size++ ) = ( utf & 0x3F ) | ( ( ( utf >> 8 ) & 0x03 ) <

}

else if ( utf >= 0xE08080 && utf <= 0xEFBFBF )

{

*( unicode + size++ ) = ( ( utf >> 10 ) & 0x0F ) | (( utf >> 16 ) & 0x0F ) <

*( unicode + size++ ) = ( utf & 0x3F ) | ((( utf >> 8 ) & 0x03 ) <

}

else if ( utf >= 0xF0808080 && utf <= 0xF7BFBFBF )

{

*( unicode + size++ ) = ( (utf >> 20 ) & 0x03 ) | ((( utf >> 24 ) & 0x07 ) <

*( unicode + size++ ) = (( utf >> 10 ) & 0x0F ) | ( ( ( utf >> 16 ) & 0x0F ) <

*( unicode + size++ ) = ( utf & 0x3F ) | ( ( utf >> 8 ) & 0x03 ) <

}

else if ( utf >= 0xF880808080 && utf <= 0xFBBFBFBFBF )

{

*( unicode + size++ ) = ( utf >> 32 ) & 0x03;

*( unicode + size++ ) = ( ( utf >> 20 ) & 0x03 ) | ( ( ( utf >> 24 ) & 0x3F ) <

*( unicode + size++ ) = ( ( utf >> 10 ) & 0x0F ) | ( ( ( utf >> 16 ) & 0x0F ) <

*( unicode + size++ ) = ( utf & 0x3F ) | ( ( (utf >> 8) & 0x03 ) <

}

else if ( utf >= 0xFC8080808080 && utf <= 0xFDBFBFBFBFBF )

{

*( unicode + size++ ) = ( ( utf >> 32 ) & 0x3F ) | ( ( ( utf >> 40 ) & 0x01 ) <

*( unicode + size++ ) = ( ( utf >> 20 ) & 0x03 ) | ( ( ( utf >> 24 ) & 0x3F ) <

*( unicode + size++ ) = ( ( utf >> 10 ) & 0x0F ) | ( ( ( utf >> 16 ) & 0x0F ) <

*( unicode + size++ ) = ( utf & 0x3F ) | ( ( ( utf >> 8 ) & 0x03 ) <

}

else

{

printf( "Error : unknow scope\n" );

return -1;

}

*( unicode + size ) = '\0';

return size;

}

测试用例:

int

main( int argc, char *argv[] )

{

unsigned char unicode[9];

int size = 0;

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf1 = 0x55;

size = utf_to_unicode( utf1, unicode );

unicode_print( unicode, size );

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf2 = 0xC480;

size = utf_to_unicode( utf2, unicode );

unicode_print( unicode, size );

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf3 = 0xE4B8A5;

size = utf_to_unicode( utf3, unicode );

unicode_print( unicode, size);

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf4 = 0xF0A39196;

size = utf_to_unicode( utf4, unicode );

unicode_print( unicode, size);

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf5 = 0xF888B495A7;

size = utf_to_unicode( utf5, unicode );

unicode_print( unicode, size);

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf6 = 0xFCB495A188B4;

size = utf_to_unicode( utf6, unicode );

unicode_print( unicode, size);

memset( unicode, 0x00, sizeof( unicode ) );

unsigned long utf7 = 0xFEBFBFBFBFBF;

size = utf_to_unicode( utf7, unicode );

unicode_print( unicode, size);

return 0;

}

打印函数如下:

void

unicode_print( unsigned char *unicode, int size )

{

if ( size == -1 )

{

printf("Error : unknow scope\n");

return;

}

int index = 0;

for ( ; index 

{

printf( "%02X", *( unicode + index ) );

}

printf("\n");

}

本文参考文献:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值