【问题标题】:Hex to Ascii conversion C十六进制到ASCII转换C
【发布时间】:2017-07-21 08:30:28
【问题描述】:

我的挑战是将十六进制值转换为 ascii,输入是指向 uint8 的指针,因此我需要逐字节转换,并且还有一个大小输入(字节数),输入都是十六进制值,请帮我找出我的代码有什么问题。

输出始终为 0

uint8 ReferenceNumber[8] = {0x30,0x40,0x60,0x50,0x80,0x60,0x75,0x95};
HexToAscii(&ReferenceNumber[0], output, 8); 

static void HexToAscii(uint8* input, uint8 *output, uint8 size)//No of bytes
{
    uint8 i, temp;

    for(i=1; i<=size; i++)
    {
        temp = (*(input)) >> (4*(i-1));
        temp &= 0x0F;
        temp +='0';
        if (temp >= (10+'0'))
        {
            temp += ('A'-10-'0');
        }
        *(output+size-i) = temp;
    }
}

【问题讨论】:

  • 输入是什么,实际结果和预期结果是什么?通过调试你的代码你发现了什么?
  • 你想把十六进制转换成字符吗?
  • 你期望什么输出?
  • 提示:“0123456789ABCDEF”
  • *(输出+size-i) = temp;你为什么要交换末端?

标签: c hex ascii


【解决方案1】:

声明

temp = (*(input)) >> (4*(i-1));

可以改写为

uint8 x = *(input);
temp = x >> (4 * (i - 1));

temp = input[0] >> (4 * (i - 1));

现在您可以看到您实际上将相同的值向右移动了 0、4、8、12、... 位。当向右移动值时,您从左侧填充 0,因此在循环 2 次迭代后,您的 temp 变量始终为 0。

E1 >> E2 的结果是E1 右移E2 位位置。如果 E1 有一个无符号类型或如果 E1 有一个有符号类型和一个非负值,则结果的值是 E1 / 2^E2。如果 E1 具有带符号类型和负值,则结果值是实现定义的。 - ISO/IEC 9899:TC3, Section 6.5.7: Bitwise shift operators

您需要增加您的input 指针。但是在您的代码中,您需要为每个字节重复两次代码 - 对于 uint8 的低 4 位和高 4 位。

我就是这样做的(用内联函数替换宏,正如 Olaf 在 comment 中指出的那样):

/*! \brief Convert nibble (lower 4 bits) to HEX value to avoid using standard libraries.
 */
static inline __attribute__((always_inline, const)) char
NibbleToHex(uint8_t nibble)  {
    return ((nibble <= 9) ? ('0' + nibble) : ('A' + nibble - 10));
}

static void HexToAscii(const uint8_t *input, char *output, uint8_t size) {
    while (size--) {
        *(output++) = NibbleToHex((*input) >> 4u);
        *(output++) = NibbleToHex((*input) & 0x0Fu);
        input++; /*< Move to the next byte. */
    }
}

uint8_t ReferenceNumber[8] = {0x30, 0x40, 0x60, 0x50, 0x80, 0x60, 0x75, 0x95};
HexToAscii(ReferenceNumber, output, sizeof(ReferenceNumber) / sizeof(ReferenceNumber[0])); 

注意output 必须始终是输入数据大小的两倍(假设size 变量等于输入数据的长度)。

【讨论】:

  • 太棒了,没看到!,我仍然想知道为什么我问这个问题时得到-1,输入[0]与输入不同?..这可能是我的理解出错的地方!
  • 我不知道你为什么得到-1。在您的情况下,input 是内存中某处uint8 类型变量的指针。您可以通过使用*input 取消引用指针来获得位于该地址上的实际值,该指针等于input[0]。因为您知道该指针指向多个连续值(数组),所以您可以访问以下地址。 *input == input[0], *(input + 1) == input[1], *(input + 123) == input[123],... 我使用指针的手动增量而不是索引来消除对额外计数器变量的需要。
  • 是的,我知道 *input 与 input[0] 相同,但我认为 input 和 &input[0] 应该相同,我在第一条评论中错过了 &
  • 我明白了。你是对的 - 在这种情况下,在大多数情况下,input&amp;input[0] 是相同的,我更喜欢input,因为它打字更少/更清晰。但是,在将其与 sizeof 运算符一起使用时要小心,正如 in this answer 和更详尽的 this answer 中所解释的那样。但是,我刚刚在 C 和 C++ 89/11/14 中进行了测试,第一个链接答案中提到的两种情况都给出了相同的正确结果。
  • 我认为大部分时间都使用input 表单,这在 SEI CERT 页面上的示例中也可以看到(可以查看)EXP09-C. Use sizeof to determine the size of a type or variable。说到sizeof,请注意ARR01-C. Do not apply the sizeof operator to a pointer when taking the size of an array
猜你喜欢
  • 2014-06-22
  • 1970-01-01
  • 2015-05-22
  • 2011-08-02
  • 2011-11-27
  • 2012-11-14
  • 2011-12-09
  • 2016-04-22
  • 2017-08-28
相关资源
最近更新 更多