/***************************************************************************
* 文 件 名: UTF8_UCS2_GB2312.CPP
*
* 版 本 号: V1.0.0.1
*
* 创建时间: 2008-05-22 11:48:13
*
* 文件描述: 从UTF8格式字符串转换成GB2312编码格式(经由UCS2编码)
* UCS2编码是对双字节编码的统一描述,Unicode就是其中一种
* 假定条件: 用户输入到程序的UTF8字符串是符合UTF8基本规范
* 否则,程序执行的结果不可预料(包括产生异常)
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
typedef char S8; //有符号8位
typedef short S16; //有符号16位
typedef int S32; //有符号32位
typedef unsigned char U8; //无符号8位
typedef unsigned short U16; //无符号16位
typedef unsigned int U32; //无符号32位
/***************************************************************************
* 函数名称: RealVal
* 功能描述: 计算'0' - '9', 'a' - 'z', 'A - Z'分别对应的十进制数值
* 日 期: 2008-05-22 11:57:56
* 作 者: lianxiuzhu
* 参数说明: c - 十六进制字符
* 返 回 值: 对应的十进制数值
***************************************************************************/
U8 RealVal(S8 c)
{
if(c >= '0' && c <= '9')
{
return (c - 48);
}
else if(c >= 'a' && c <= 'f')
{
return (c - 87);
}
else if(c >= 'A' && c <= 'F')
{
return (c - 55);
}
else
{
return 0;
}
}
/***************************************************************************
* 函数名称: UTF8StringToStream
* 功能描述: 从UTF8格式的字符串转换成UTF8字节流数组(%E9%90-->0xE9,0x90)
* 日 期: 2008-05-22 13:34:01
* 参数说明: szUTF8 - UTF8格式的字符串
* binUTF8 - UTF8字节流数组
* 返 回 值: 转换到UTF8字节流数组中字节数
***************************************************************************/
U32 UTF8StringToStream(const S8* szUTF8, U8* binUTF8)
{
U32 uCount = 0;
S8* szTemp = (S8*)szUTF8;
while(*szTemp != '\0')
{
if(*szTemp == '%')
{
binUTF8[uCount] = RealVal(*(szTemp + 1)) * 0x10 + RealVal(*(szTemp + 2));
szTemp = szTemp + 3;
}
else if(*szTemp == '+')
{
binUTF8[uCount] = 0x20;
szTemp = szTemp + 1;
}
else
{
binUTF8[uCount] = *szTemp;
szTemp = szTemp + 1;
}
uCount = uCount + 1;
}
return uCount;
}
/***************************************************************************
* 函数名称: UTF8ToUCS2
* 功能描述: 转换UTF8格式到UCS2格式(UCS2是双字节编码,Unicode是其中一种)
* 日 期: 2008-05-22 13:36:56
* 参数说明: binUTF8 - UTF8字节流数组
* uCount - UTF8字节流数组中的字节数
* binUCS2 - UCS2字节流数组
* 返 回 值: 转换到UCS2字节流数组中的U16单元个数
***************************************************************************/
U32 UTF8ToUCS2(const U8* binUTF8, U32 uCount, U16* binUCS2)
{
U32 uLength = 0;
U8* szTemp = (U8*)binUTF8;
while((U32)(szTemp - binUTF8) < uCount)
{
if(*szTemp <= 0x7F) //0xxxxxxx
{
binUCS2[uLength] = binUCS2[uLength] | (U16)(*szTemp & 0x7F);
szTemp = szTemp + 1;
}
else if(*szTemp <= 0xDF) //110xxxxx 10xxxxxx
{
binUCS2[uLength] = binUCS2[uLength] | (U16)(*(szTemp + 1) & 0x3F);
binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp) & 0x1F) << 6);
szTemp = szTemp + 2;
}
else if(*szTemp <= 0xEF) //1110xxxx 10xxxxxx 10xxxxxx
{
binUCS2[uLength] = binUCS2[uLength] | (U16)(*(szTemp + 2) & 0x3F);
binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp + 1) & 0x3F) << 6);
binUCS2[uLength] = binUCS2[uLength] | ((U16)(*(szTemp) & 0x0F) << 12);
szTemp = szTemp + 3;
}
else
{
return 0;
}
uLength = uLength + 1;
}
return uLength;
}
/*
* 测试用主程序:
* 功能:将一段UTF8格式的字符串,转化成GB2312格式输出
* 检验:如果您能看到屏幕输出“让我们永远铭记这一刻:2008年5月12日 14时28分”,成功!
*/
int main(int argc, char* argv[])
{
S8* szUTF8 = "%E8%AE%A9%E6%88%91%E4%BB%AC%E6%B0%B8%E8%BF%9C%E9%93%AD%E8%AE%B0%E8%BF%99%E4%B8%80%E5%88%BB%EF%BC%9A2008%E5%B9%B45%E6%9C%8812%E6%97%A5+14%E6%97%B628%E5%88%86";
U8 binUTF8[512] = {0};
U32 uCount = UTF8StringToStream(szUTF8, binUTF8);
if(uCount > 0)
{
U16 binUCS2[512] = {0};
uCount = UTF8ToUCS2(binUTF8, uCount, binUCS2);
if(uCount > 0)
{
S8 szGB2312[512] = {0};
setlocale(LC_ALL, ".936");
wcstombs(szGB2312, (wchar_t*)binUCS2, 512);
printf("%s\n", szGB2312);
}
}
return uCount;
}