C uint16_t 到无库的填充十六进制字符串

问题描述 投票:0回答:2

我正在尝试将

uint16_t
值转换为该数字的十六进制表示形式,作为 C 中的字符串,而不使用任何外部库。到目前为止,我已经通过 this 答案实现了可靠的转换。 但是,如果
uint16_t
值小于
0x1000
,我的用例要求结果输出用前导零填充。例如,如果我像这样调用该函数:

char s[5];
itohexa(s, 1230); //(1230->0x04CE)

我会得到:

04CE

但是,这个函数给了我这个:

4CE

字符串中表示的 uint16_t 的实际字节数对于我的用例很重要。我预计该值偶尔会超过

0x0FFF
,因此仅向任何
uint16_t
数字添加前导零字符(到目前为止我一直在这样做作为解决方法),是不够的。

这是我尝试过的:

static char *itohexa_helper(char *dest, uint16_t x, uint8_t pad) {
    if (x >= 16 || pad) {
        dest = itohexa_helper(dest, x/16, pad);
        pad = 1;
    }
    *dest++ = "0123456789ABCDEF"[x & 15];
    return dest;
}

char *itohexa(char *dest, uint16_t x) {
    uint8_t padding = (x < 0x1000);
    *itohexa_helper(dest, x, padding) = '\0';
    return dest;
}

在这种情况下,即使该值的前 4 个最高有效位为零,

padding
pad
是否仍会进行转换? 仅供记录:对上述代码所做的修改仍然会产生与上面链接的answer中提到的原始结果相同的结果。

arrays c string data-conversion
2个回答
0
投票

我可能会尽可能明确地写出来,就像这样(评论中的解释):

#define ZERO_PAD false

char* itohexa (char dest[4+1], uint16_t x)
{
  bool remove_zeroes = true;
  char* ptr = dest;

  for(size_t i=0; i<4; i++)
  {
    // mask out the nibble by shifting 4 times byte number:
    uint8_t nibble = (x >> (3-i)*4) & 0xF; 
    
    // binary to ASCII hex conversion:
    char hex_digit = "0123456789ABCDEF" [nibble];
    
    if(!ZERO_PAD && remove_zeroes && hex_digit == '0')
    {
      ; // do nothing
    }
    else
    {
      remove_zeroes = false;
      *ptr = hex_digit;
      ptr++;
    }
  }

  if(remove_zeroes) // was it all zeroes?
  {
    *ptr = '0';
    ptr++;
  }
  *ptr = '\0';

  return dest;
}

测试用例:

char dest[4+1];
puts(itohexa(dest, 0));
puts(itohexa(dest, 1230));
puts(itohexa(dest, 0));
puts(itohexa(dest, 0xC1));
puts(itohexa(dest, 0xABBA));

输出

ZERO_PAD false

0
4CE
0
C1
ABBA

输出

ZERO_PAD true

0000
04CE
0000
00C1
ABBA

ZERO_PAD
自然可以改为参数,或者你可以制作两个不同的函数等等


0
投票

有时,使用(更复杂的)递归来解决问题比使用迭代更“有趣”。你的代码已经很接近了! 与其说你想要的“填充”,不如说它是前导的“0”。设置、清除填充标志可能会起作用(如果正确完成),但只会给您一个前导零。

这是您重新编写的代码:

static char *itohexa_helper( char *dest, uint16_t x, int n ) { if( --n ) dest = itohexa_helper( dest, x>>4, n ); // recursion *dest++ = "0123456789ABCDEF"[x & 0xF]; // mask and offset return dest; } char *itohexa(char *dest, uint16_t x) { *itohexa_helper( dest, x, 4 ) = '\0'; // 4 digits of output... return dest; } int main( void ) { char buf[16]; // big enough puts( itohexa( buf, 0xBEEF ) ); puts( itohexa( buf, 0xCDE ) ); puts( itohexa( buf, 0xCD ) ); return 0; }

输出:

BEEF 0CDE 00CD

注意没有任何以 10 为基数的常量...

© www.soinside.com 2019 - 2024. All rights reserved.