转载请标注出处:(版权所有)
本文将从五点详细介绍bcd码和ascii 之间的关系,如下所示:
一、简介
二、用途
三、特点
四、代码原理
五、代码
1、ascii 转压缩bcd码 2、 压缩bcd 转ascii 码
六、总结语
正文
一、简介
(1) bcd 码(仅0-9)
bcd 二-十进制代码(Binary Coded Decimal):主要采用 4 位 表示一个十进制(通常一个字节只取低四位),常见的有8421码,如:0100 为4 范围为: 0-9 。 321则是:0011 0010 0001
(2) ascii 码
标准的ascii码值范围为 0-127 最高位为0,128-255为拓展的ascii码 例如由IBM自拓展的图形。
(3)压缩的bcd 码(包含 A-F)
由于bcd 码取低四个字节,导致高四个字节空闲没有,因此可以将十进制的两个字节压缩成1个字节 如 “32” 则为0x32
二、用途
(1)金额等仅数字的压缩
(2)表示发送内容的长度压缩
三、特点
1.有损压缩: bcd 仅取后四个字节进行压缩,因此还原也仅低四位
2. 任意字符压缩: 本文代码是对任意字符进行压缩仅取后四位。(压缩bcd 仅用于0-9 A-F之间)
四、代码原理
0:0000 '0' 0011 0000
1:0001 '1' 0011 0001 'A' 0100 0001'a' 0110 0001
2:0010 '2' 0011 0010 'B' 0100 0010'b' 0110 0010
3:0011 ~~~~ ‘C' 0100 0011'c' 0110 0011
4:0100 ~~~~ ~~~~ ~~~~
5:0101 ~~~~ ~~~~ ~~~~
6:0110 ~~~~ ~~~~ ~~~~
7: 0111 ~~~~ ~~~~ ~~~~
8:1000 ~~~~ ~~~~ ~~~~
9: 1001 ~~~~ ~~~~~~~~
其中 0-9 A-F a-f第四个字节是一样的。所以可以根据后四个字节进行压缩和还原
五、代码
1.ascii 转bcd 码
/*
nType 0 左靠右边补0 1 有靠左边补0
*/
int AscToBcd(const unsigned char *pszAscStr,int nLen, int nType, unsigned char *pszBcdStr)
{
unsigned char *psTempbuf = (unsigned char *)pszAscStr;
int nBcdCount = 0;
int nIcount = 0;
int nAsciiLen = 0;
int nIsDouble = 0;//是否为双
if(pszAscStr == NULL || pszBcdStr == NULL)
return APP_FAIL;
nAsciiLen = strlen((char *)pszAscStr);
if(nAsciiLen < nLen)
nLen = nAsciiLen;
else
nAsciiLen = nLen; //否则长度为原来的
//判断单双 8421 所有除了第一位外所有相加都为偶数
if(nLen&0x01 == 1)
{
nIsDouble = 0;//奇数
nAsciiLen = nLen -1;
//判断靠的方向
if(nType == 1) //向右边
{
nIcount = 1;
nAsciiLen ++;//补齐回去
}
}
else
{
nIsDouble = 1;
}
for (nBcdCount = nIcount; nIcount < nAsciiLen; nIcount ++,nBcdCount++)
{
if (
(psTempbuf[nIcount] >= 'A' && psTempbuf[nIcount] <= 'F' )||
(psTempbuf[nIcount] >= 'a' && psTempbuf[nIcount] <= 'f' )
)
{
pszBcdStr[nBcdCount] = (int)(psTempbuf[nIcount++] & 0x0f) +9;
}
else
{
pszBcdStr[nBcdCount] = (int)(psTempbuf[nIcount++] & 0x0f);
}
if (
(psTempbuf[nIcount] >= 'A' && psTempbuf[nIcount] <= 'F' )||
(psTempbuf[nIcount] >= 'a' && psTempbuf[nIcount] <= 'f' )
)
{
pszBcdStr[nBcdCount] = (((int)pszBcdStr[nBcdCount]) << 4) | ((int)(psTempbuf[nIcount] & 0x0f) +9);
}
else
{
pszBcdStr[nBcdCount] = (((int)pszBcdStr[nBcdCount]) << 4) | ((int)(psTempbuf[nIcount] & 0x0f));
}
}
if (nIsDouble == 0)
{
if(nType == 1) //向右边
{
if (
(pszAscStr[0] >= 'A' && pszAscStr[0] <= 'F' )||
(pszAscStr[0] >= 'a' && pszAscStr[0] <= 'f' )
)
{
pszBcdStr[0] = (int)(psTempbuf[0] & 0x0f) +9;
}
else
{
pszBcdStr[0] = (int)(psTempbuf[0] & 0x0f) ;
}
}
else //左靠
{
if (
(pszAscStr[nIcount] >= 'A' && pszAscStr[nIcount] <= 'F' )||
(pszAscStr[nIcount] >= 'a' && pszAscStr[nIcount] <= 'f' )
)
{
pszBcdStr[nBcdCount] = (int)(psTempbuf[nIcount] & 0x0f) +9;
}
else
{
pszBcdStr[nBcdCount] = (int)(psTempbuf[nIcount] & 0x0f) ;
}
pszBcdStr[nBcdCount] = pszBcdStr[nBcdCount] << 4;//左移动
}
}
return APP_SUCCESS;
}
2.bcd 转ascii
int BcdToAsc(const unsigned char *pszBcdStr,int nLen, int nType, unsigned char *pszAscStr)
{
unsigned char *psTempbuf = (unsigned char *)pszBcdStr;
int nHight = 0;//高四位
int nLow = 0;//第四位
int nIcount = 0;
int nAsciiLen = 0;
int nIsDouble = 0;//是否为双
if(pszAscStr == NULL || pszBcdStr == NULL)
return APP_FAIL;
//判断单双 8421 所有除了第一位外所有相加都为偶数
if(nLen&0x01 == 1) //3
{
nIsDouble = 0;//奇数
//判断靠的方向
if(nType == 1) //向右边
{
nIcount = 1;
}
else
{
nLen --;//左边对齐
}
}
else
{
nIsDouble = 1;
}
for (nAsciiLen = nIcount; nAsciiLen < nLen; nIcount ++)
{
nHight = (int)(pszBcdStr[nIcount])>>4;
nLow = (int)(pszBcdStr[nIcount])&0x0f;
if ( nHight > 9 && nHight < 16 )
{
pszAscStr[nAsciiLen ++] = nHight + 'A' -10;
}
else
{
pszAscStr[nAsciiLen ++] = nHight + '0' -0;
}
if ( nLow > 9 && nLow < 16 )
{
pszAscStr[nAsciiLen ++] = nLow + 'A' -10;
}
else
{
pszAscStr[nAsciiLen ++] = nLow + '0' -0;
}
}
if (nIsDouble == 0)
{
if(nType == 1) //向右边
{
nLow = (int)(pszBcdStr[0])&0x0f;
if ( nLow > 9 && nLow < 16 )
{
pszAscStr[0 ] = nLow + 'A' -10;
}
else
{
pszAscStr[0] = nLow + '0' -0;
}
}
else //左靠
{
nHight = (int)(pszBcdStr[nIcount])>>4;
if ( nHight > 9 && nHight < 16 )
{
pszAscStr[nAsciiLen ] = nHight + 'A' -10;
}
else
{
pszAscStr[nAsciiLen ] = nHight + '0' -0;
}
}
}
return APP_SUCCESS;
}