Как сформировать ASCII(шестнадцатеричное) число, используя 2 символа?

У меня есть чар byte[0] = '1' (H'0x31)а также byte[1] = 'C'(H'0x43)

Я использую еще один буфер для большего количества баффов char hex_buff[0] Я хочу иметь шестнадцатеричное содержание в этом hex_buff[0] = 0x1C (т.е. комбинация байта [0] и байта [1])

Я использовал код ниже, но я понял, что мой код действителен только для шестнадцатеричных значений 0-9

char s_nibble1 = (byte[0]<< 4)& 0xf0;

char s_nibble2 =  byte[1]& 0x0f;

hex_buff[0] = s_nibble1 | s_nibble2;// здесь я хочу иметь 0x1C вместо 0x13

4 ответа

Решение

Возможный способ сделать это, без зависимостей с другими функциями манипулирования персонажами:

char hex2byte(char *hs)
{
    char b = 0;
    char nibbles[2];
    int i;

    for (i = 0; i < 2; i++) {
        if ((hs[i] >= '0') && (hs[i] <= '9')) 
            nibbles[i] = hs[i]-'0';
        else if ((hs[i] >= 'A') && (hs[i] <= 'F')) 
            nibbles[i] = (hs[i]-'A')+10;
        else if ((hs[i] >= 'a') && (hs[i] <= 'f')) 
            nibbles[i] = (hs[i]-'a')+10;
        else 
            return 0;
    }

    b = (nibbles[0] << 4) | nibbles[1];
    return b;
}

Например: hex2byte("a1") возвращает байт 0xa1,

В вашем случае вы должны вызвать функцию как: hex_buff[0] = hex2byte(byte),

Вы пытаетесь получить кусочек, маскируя биты символьного кода, а не вычитая фактическое значение. Это не сработает, потому что диапазон отключен: между [0..9] а также [A-F] в кодировке, поэтому маскирование не удастся.

Вы можете исправить это, добавив небольшую вспомогательную функцию и дважды используя ее в своем коде:

int hexDigit(char c) {
    c = toupper(c); // Allow mixed-case letters
    switch(c) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9': return c-'0';
        case 'A':
        case 'B':
        case 'C':
        case 'D':
        case 'E':
        case 'F': return c-'A'+10;
        default: // Report an error
    }
    return -1;
}

Теперь вы можете закодировать конверсию следующим образом:

int val = (hexDigit(byte[0]) << 4) | hexDigit(byte[1]);

Что мешает вам использовать strtol()?

char bytes[] = "1C";
char buff[1];
buff[0] = strtol(bytes, NULL, 16);  /* Sets buff[0] to 0x1c aka 28. */

Чтобы добавить это согласно комментарию chux: strtol() работает только на 0 -определенные массивы символов. Который не обязательно должен иметь место для вопроса OP.

Похоже, вы пытаетесь преобразовать ASCII-гекс во внутреннее представление.

Есть много способов сделать это, но я чаще всего использую для каждого клева:

int nibval(unsigned short x)
{
    if  (('0' <= x) && ('9' >= x))
    {
        return  x - '0';
    }
    if  (('a' <= x) && ('f' >= x))
    {
        return  x - ('a' - 10);
    }
    if  (('A' <= x) && ('F' >= x))
    {
        return  x - ('A' - 10);
    }

    //  Invalid input
    return  -1;
}

При этом используется параметр типа unsigned int, поэтому он будет работать как с однобайтовыми символами, так и с символами wchar_t.

Другие вопросы по тегам