将十进制转换为十六进制时,一次只考虑4位

问题描述 投票:-2回答:3

我有一个C函数将十进制转换为十六进制字符串hexConversion

int hexConversion(int num){
    char hex_buffer[9];
    unsigned int mask = 4026531840;
    for(int i = 0; i < 9; i++){
        int temp = mask & num;
        if(temp < 10){
            hex_buffer[i] = temp + '0';
        }
        else if(temp == 10){
            hex_buffer[i] = 'A';
        }
        else if(temp == 11){
            hex_buffer[i] = 'B';
        }
        else if(temp == 12){
            hex_buffer[i] = 'C';
        }
        else if(temp == 13){
            hex_buffer[i] = 'D';
        }
        else if(temp == 14){
            hex_buffer[i] = 'E';
        }
        else if(temp == 15){
            hex_buffer[i] = 'F';
        }
        mask >>= 4;
    }

    hex_buffer[8] = '\0';

    for(int i = 0; i < sizeof(hex_buffer); i++){
        printf("%c", hex_buffer[i]);
    }
}

用驱动代码:

int main(){
    hexConversion(2);
    hexConversion(255);
    hexConversion(-1);
    hexConversion(INT_MAX);
    hexConversion(INT_MIN);
    hexConversion(0xDEADBEEF);
}

我的输出是:00000002 0000000F 0000000F 0000000F 00000000 0000000F

每个输出的最后一个值都是正确的,但最后一个值之前的所有值都没有进行评估。我相信这是因为我的temp = mask & num没有产生不是0-15的值。我的问题是,我如何一次只考虑4位,以便我所有的temp值都在这个范围内?

c function binary hex output
3个回答
2
投票

在不考虑问题的情况下查看代码的第一句话就是为什么你管理好案例0..9但是你将案例A和B ......和F分开而不是像对数字那样做?

所以

int hexConversion(int num){
  char hex_buffer[9];
  unsigned int mask = 4026531840;
  for(int i = 0; i < 9; i++){
    int temp = mask & num;
    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else if (temp < 16) {
      hex_buffer[i] = temp - 10 + 'A';
    }
    else {
      hex_buffer[i] = '?';
    }
    mask >>= 4;
  }

  hex_buffer[8] = '\0';

  for(int i = 0; i < sizeof(hex_buffer); i++){
    printf("%c", hex_buffer[i]);
  }
}

我添加了测试if (temp < 16)通常无用,如果代码是正确的,但结果是:

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra h.c
h.c: In function ‘hexConversion’:
h.c:23:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(int i = 0; i < sizeof(hex_buffer); i++){
                      ^
pi@raspberrypi:/tmp $ ./a.out
00000002000000?F0??????F???????F000000000??????F

因此,在您的解决方案中,您不会在某些索引上写入,因为代码中存在错误

一种方法是:

void hexConversion(int num){
  char hex_buffer[9];

  for(size_t i = 0; i < sizeof(hex_buffer) -1; i++){
    int temp = (num >> (28-4*i)) & 0xf;
    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else {
      hex_buffer[i] = temp - 10 + 'A';
    }
  }
  hex_buffer[8] = 0;
  puts(hex_buffer);
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra h.c
pi@raspberrypi:/tmp $ ./a.out
00000002
000000FF
FFFFFFFF
7FFFFFFF
80000000
DEADBEEF

请注意,您的代码假设在32b上为int,与大小无关(但假设char在8位上):

void hexConversion(int num){
  char hex_buffer[sizeof(int)*2 + 1];

  for(size_t i = 0; i < sizeof(int)*2; i++){
    int temp = (num >> (sizeof(int)*8-4-4*i)) & 0xf;

    if(temp < 10){
      hex_buffer[i] = temp + '0';
    }
    else {
      hex_buffer[i] = temp - 10 + 'A';
    }
  }
  hex_buffer[sizeof(int)*2] = 0;
  puts(hex_buffer);
}

2
投票

这取决于你的系统,但如果你想从你的值中提取nybbles,你最终可以在你的值上应用0xF(掩码>>(4 * n))例如,如果我得到一个类似于0x4602 = 0100 0110 0000 0010的二进制数据,我需要只提取这个的第一部分我可以使用带有&mask的0xF000 = 1111 0000 0000 0000超过这个0x4602得到这个值的第一部分这将给我们 0xF000 = 1111 0000 0000 0000 &0x4602 = 0100 0110 0000 0010 result would be 0x4000 = 0100 0000 0000 0000

为了得到这个值的第n部分你可以漂移(0xF000)>> 4 n次


1
投票

你需要从0-7运行循环,并在将掩码应用到较低的半字节后移动数字。

for(int i = 0; i < 8; i++){
    int temp = (mask & num) >> (28 -4*i);
© www.soinside.com 2019 - 2024. All rights reserved.