Учитывая только 4 бита за раз при преобразовании десятичного числа в шестнадцатеричное - PullRequest
0 голосов
/ 05 марта 2019

У меня есть функция 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 были в этом диапазоне?

Ответы [ 3 ]

2 голосов
/ 05 марта 2019

Первое замечание, касающееся вашего кода без учета проблемы, заключается в том, почему вы хорошо справляетесь с делом 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

Обратите внимание, что ваш код предполагает, что int на 32b не зависит от размера (но предположим, что 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 голосов
/ 05 марта 2019

Это зависит от вашей системы, но если вы хотите извлечь nybbles из вашего значения, вы можете в конечном итоге применить 0xF (маски >> (4 * n)) к вашим значениям. Например, если я получил двоичные данные, выглядящие так: 0x4602 = 0100 0110 0000 0010 и мне нужно извлечь только 1-ю часть этого, я мог бы использовать 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 голос
/ 05 марта 2019

Вам нужно запустить цикл от 0-7, а также переместить число после применения маски, чтобы понизить клев.

for(int i = 0; i < 8; i++){
    int temp = (mask & num) >> (28 -4*i);
...