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 final F 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.)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top