这个奇怪的函数将字符串转换为二进制吗?
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
)。该函数有一些陷阱:
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 中。以上是关于这个奇怪的函数将字符串转换为二进制吗?的主要内容,如果未能解决你的问题,请参考以下文章