这个奇怪的函数将字符串转换为二进制吗?

Posted

技术标签:

【中文标题】这个奇怪的函数将字符串转换为二进制吗?【英文标题】:Is this strange function converting string to binary? 【发布时间】:2012-08-03 07:19:09 【问题描述】:

我正在对我们系统中的旧 c 代码进行错误修复(奇怪的是,它不是标准 c。它不是由 gcc 编译的)。我来到这段代码,它似乎将字符串转换为无符号字符格式的二进制代码。逻辑让我感到困惑(粗体部分)。这对你们有意义吗?

我需要理解这段代码,因为我必须复制它并在另一个长度不是 13 而是 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++;
                
               

【问题讨论】:

@Joachim Pileborg 这不是问题。 您似乎遇到了 BCD 编码器/解码器:en.m.wikipedia.org/wiki/Binary-coded_decimal 我相信你不应该复制这个。您应该修复它,因为您可以将其简化为几行代码。 我最初以为我最终会参加 The Daily WTF 现在我知道它在做什么......谢谢! 【参考方案1】:

代码将包含十六进制的字符串(例如"002A40FF160AD")转换为包含原始二进制值的字节数组(例如0x00, 0x2A, 0x40, 0xFF, 0x16, 0x0A, 0xDF)。该函数有一些陷阱:

奇怪的是,字符串的长度不是偶数,所以字符串末尾暗示了一个额外的“F”。 (else l_bcd_byte = l_bcd_byte + 15;)。 另一个奇怪的地方是 "FF" 被转换为 0x00。 'F'' '(空格)都被视为'F' 该函数也可用作字符串到压缩十进制 (BCD) 转换器,因为压缩十进制看起来像仅使用数字 0-9 的十六进制数字(例如,十进制中的 15 是压缩十进制中的 0x15)。 不过,最后的 F 使这个功能复杂化了。

编辑

最后的 F 使压缩十进制格式实际上更容易使用:压缩十进制数字末尾的 F 表示该数字是无符号的。

【讨论】:

在您的帮助下,我明白了更多。一次需要 2 个字符,并将它们的值组合成一个无符号字符。例如,如果字符串是'00195232943',它将采用'00'、'19'、'52'、'32'、'94'、'3'并附加一个'\0'来表示结束。在十六进制编辑器下,它将显示“00195232943F”。在普通编辑器中,它将显示“00195232943”。从而使文本能够以二进制模式传输。很讨厌。【参考方案2】:

这是一个定制的 BCD 转换器。查找 BCD 格式并掌握如何将数字从 BCD 格式转换为常规数字。

之后,如果您要迁移旧代码,请确保在函数中移动整个代码块。即使它有一个错误。旧代码可能取决于该错误。在您证明通向旧代码的所有代码路径都被覆盖并且没有错误后,您就可以开始修复/更改行为了。

我确实有一个问题要问你,为什么它不是标准的 C 代码? gcc 在该代码上给您的错误是什么?你的 -std= 参数是什么样的? (我会通过回复你的帖子来问这个问题,但显然我不允许这样做。)

【讨论】:

嗯。我不知道它是否不是标准 c,但它有一些我在 gcc 编译的 c 程序中没有看到的行为。例如,它不会接受 // 作为评论。 是的, // cmets 是在 C99 标准中引入的。 gcc(1) 默认使用 gnu89,它是 C90 标准 + GNU 扩展。因此,如果您想要 // cmets,最好将 -std=C99 添加到您的 CFLAGS 中。

以上是关于这个奇怪的函数将字符串转换为二进制吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中如何将字符串转换为二进制数

python怎么将字符串转化为八位二进制

lua可以对单个字符和数字之间进行转换吗

Swift将十六进制字符串或字符转换为整数

将数字数组转换为二进制数

如何将十六进制字符串转换为R中的文本?