Is this strange function converting string to binary?
-
24-06-2021 - |
题
I am doing bug fixing on a old c code in our system ( strangely enough, it's not standard c. It is not compiled by gcc ). I come to this code which seems to be converting a string to binary code in unsigned char format. The logic puzzle me ( bold part ). Does this make any sense to you guys?
I need to understand this code because I have to copy this and reuse it on another string whose length is not 13 but 11.
char l_call_dest_no[25];
int l_loop_cnt;
unsigned char l_bcd_byte;
unsigned char l_call_dest_no_in_bcd[13];
...some other code as input...
for (l_loop_cnt = 0; l_loop_cnt < 13; l_loop_cnt++)
{
l_bcd_byte = '\0';
switch (l_call_dest_no[l_loop_cnt * 2])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
l_bcd_byte = (l_call_dest_no[l_loop_cnt * 2] - 48) * 16;
break;
case 'A':
l_bcd_byte = 10 * 16;
break;
case 'B':
l_bcd_byte = 11 * 16;
break;
case 'C':
l_bcd_byte = 12 * 16;
break;
case 'D':
l_bcd_byte = 13 * 16;
break;
case 'E':
l_bcd_byte = 14 * 16;
break;
case 'F':
case ' ':
l_bcd_byte = 15 * 16;
break;
default:
printf("*** invalid call destination number ***\n");
return_status = FAILURE;
break;
}
if (l_loop_cnt < 12)
{
switch (l_call_dest_no[l_loop_cnt * 2 + 1])
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
l_bcd_byte = l_bcd_byte + (l_call_dest_no[l_loop_cnt * 2 + 1] - 48) ;
break;
case 'A':
l_bcd_byte = l_bcd_byte + 10;
break;
case 'B':
l_bcd_byte = l_bcd_byte + 11;
break;
case 'C':
l_bcd_byte = l_bcd_byte + 12;
break;
case 'D':
l_bcd_byte = l_bcd_byte + 13;
break;
case 'E':
l_bcd_byte = l_bcd_byte + 14;
break;
case 'F':
case ' ':
l_bcd_byte = l_bcd_byte + 15;
break;
default:
printf("*** invalid call destination number ***\n");
return_status = FAILURE;
break;
}
}
else
l_bcd_byte = l_bcd_byte + 15;
if (l_bcd_byte == 255)
l_call_dest_no_in_bcd[l_loop_cnt] = '\0';
else
{
l_call_dest_no_in_bcd[l_loop_cnt] = l_bcd_byte;
l_call_dest_no_bcd_length++;
}
}
解决方案
The code converts strings containing hexadecimal (e.g. "002A40FF160AD"
) to an array of bytes containing the values in raw binary (e.g. {0x00, 0x2A, 0x40, 0xFF, 0x16, 0x0A, 0xDF}
). The function has a few gotchas:
- Strangely enough, the string length isn't even, so an additional 'F' is implied to be at the end of the string. (the
else l_bcd_byte = l_bcd_byte + 15;
). - Additional oddity is that
"FF"
is converted to 0x00. - Both
'F'
and' '
(a space) are treated as an'F'
- The function works also as a string to packed-decimal (BCD) converter, because packed decimals look like hexadecimal numbers using only digits 0-9 (e.g. 15 in decimal is
0x15
in packed decimal).The finalF
complicates this functionality, though.
EDIT
The final F makes packed-decimal format actually easier to use: an F at the end of a packed-decimal number means that the number is unsigned.
其他提示
That's a custom BCD transformer. Look-up the BCD format and get a good grasp of how to transform numbers from BCD format to regular numbers.
Afterwards, if you're migrating old code, make sure you move the entire code block in a function. Even if it has a bug. Old code might depend on that bug. After you prove that all the code-paths leading to the old code are covered and bug-free you can start fixing/changing behavior.
I do have one question for you, why is it not standard C code? What's the error that gcc gives you on that code? What does your -std= argument look like? (I would've asked that by replying to your post but apparently I'm not allowed to.)