二十四进制编码串转换为32位无符号整数(C语言实现)

时间:2022-06-16 10:17:57
二十四进制编码串转换为32位无符号整数(C语言实现)二十四进制编码串转换为32位无符号整数(C语言实现)
typedef int BOOL;
#define TRUE 1;
#define FALSE 0;

#define UINT_MAX 0xffffffff /* maximum unsigned int value */

enum Scale24AsciiVal
{
sav_aADis
= 32, // 小写字母与大写字母ASCII码差值
sav_chIntDis = 48, // 字符‘0’ASCII码值
};

static const char scale24[24] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'F', 'H', 'K', 'M', 'P', 'S', 'T', 'U', 'W', 'X', 'Y'};

// 判断是否为合法的二十四进制编码字符
BOOL IsScale24(const char ch, unsigned int* nVal);

/*
二十四进制编码串转换为32位无符号整数, 其中:
参数:
str 二十四进制编码串
length 二十四进制编码串长度, 若 < 0 则为 str 以 '\0' 结尾
code 转换返回码, 若 code == NULL 则忽略返回码
返回值:
(值) 转换后的返回值, 转换是否成功从 code 得到。
*/
unsigned
int C24ToU32(const char* str, int length, int* code)
{
unsigned
int result = 0;
const char* pStr = str;
unsigned
int nVal = 0; // 位值
int codeIdx = 1; // 非法字符在编码串中的序号

if (code != NULL) *code = 0;

if( (pStr==NULL) || ((pStr=="") && (length==0)) )
{
if (code != NULL)
*code = -1; // 转换失败, 可能参数错误或字符串为空串
}
else
{
if(length < 0) // str 以 '\0' 结尾
{
while(*pStr != '\0')
{
if(IsScale24(*pStr, &nVal))
{
if ( ((UINT_MAX-nVal)/24) < result ) // 转换失败(溢出)
{
if (code != NULL)
*code = codeIdx;
break;
}
else
result
= result*24 + nVal; // 进位并加位值
}
else
{
if (code != NULL)
*code = codeIdx; // 转换失败, 第 code 个字符(包含第一个字符)为非二十四进制编码
break;
}
codeIdx
++;
pStr
++;
}
}
else
{
while(codeIdx <= length)
{
if(IsScale24(*pStr, &nVal))
{
if ( ((UINT_MAX-nVal)/24) < result ) // 转换失败(溢出)
{
if (code != NULL)
*code = codeIdx;
break;
}
else
result
= result*24 + nVal; // 进位并加位值
}
else
{
if (code != NULL)
*code = codeIdx; // 转换失败, 第 code 个字符(包含第一个字符)为非二十四进制编码
break;
}

codeIdx
++;
pStr
++;
}
}
}
return result;
}

/*
判断是否为合法的二十四进制编码字符, 其中:
参数:
ch 待判定字符
nVal ch若合法,则nVal为ch所对应的二十四进制字符位值('A'->10,'B'->11,'C'->12...)
返回值:
(值) ch合法->true,非法->false。
*/
BOOL IsScale24(
const char ch, unsigned int* nVal)
{
BOOL result
= FALSE;

unsigned
int nbegin = 10; // 二分查找ch,初始起始位置
unsigned int nEnd = 23; // 二分查找ch,初始结束位置
unsigned int nMid = 16; // 二分查找ch,初始折半位置
unsigned int nOffset = 0;
char chScale= 0;

if((ch >= '0') && (ch <='9')) // '0'...'9'
{
*nVal = (unsigned int)(ch-sav_chIntDis);
result
= TRUE;
}
else if (ch >= 'A' && ch <= 'y')
{
if (ch > 'Z') // ch为小写字母
nOffset = sav_aADis;

// 'A(a)'...'Y(y)' 二分查找ch
while ( nbegin <= nEnd ){
chScale
= scale24[nMid] + nOffset;
if ( chScale == ch )
{
*nVal = nMid;
result
= TRUE;
break;
}
else if ( chScale > ch )
nEnd
= nMid - 1;
else
nbegin
= nMid + 1;

nMid
= (nbegin + nEnd) / 2;
}
}
return result;
}
View Code

点评:

   1. if((pStr==NULL) || ((pStr=="") && (length==0))) 判断错误的 bug, 应该为:
      if ((pStr == NULL) || (length == 0) || ((length < 0) && (*pStr == '\0')))
   2. if (((UINT_MAX-nVal)/24) < result) 判断溢出有漏洞的 bug;
   3. IsScale24(const char ch, unsigned int* nVal) 查找效率不够好, 可以把小写字
      母也放在数组中, 全部进行二分查找, 这样可以减少判断;
   4. 评分: 75分