Преобразование двух шестнадцатеричных символов ASCII (два байта ASCII) в один байт - PullRequest
3 голосов
/ 04 августа 2011

Я хочу преобразовать два байта ASCII в один шестнадцатеричный байт.например.

0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F ...

Байтами ASCII являются числа от 0 до 9 или буквы от A до F (только в верхнем регистре), поэтомумежду 0x30 ... 0x39 и 0x41 ... 0x46

Я знаю, как "построить" 0x4F с числами 0x34 и 0x46 : 0x4F = 0x34 * 0x10 + 0x46

Итак, на самом деле, я бы преобразовал один байт ASCII в шестнадцатеричное значение.

Для этого я могу построить и массив, чтобы назначить шестнадцатеричное значение для символа ASCII:

0x30 => 0x00
0x31 => 0x01
...
0x46 => 0x0F

Но, возможно, у него есть наиболее «правильное» решение.

Программа будет работать на AVR µC и скомпилирована с avr-gcc, поэтому решения scanf() / printf() не подходят.

У вас есть идея?Спасибо

Ответы [ 5 ]

11 голосов
/ 04 августа 2011

Я не могу понять ваши примеры, но если вы хотите преобразовать строку, содержащую шестнадцатеричные символы ascii, в ее байтовое значение (например, чтобы строка «56» стала байтом 0x56, вы можете использовать это (что предполагаетсистема использует ASCII)

uint8_t*
hex_decode(const char *in, size_t len,uint8_t *out)
{
        unsigned int i, t, hn, ln;

        for (t = 0,i = 0; i < len; i+=2,++t) {

                hn = in[i] > '9' ? in[i] - 'A' + 10 : in[i] - '0';
                ln = in[i+1] > '9' ? in[i+1] - 'A' + 10 : in[i+1] - '0';

                out[t] = (hn << 4 ) | ln;
        }

        return out;
}

Вы можете использовать его, например,

char x[]="1234";
uint8_t res[2];
hex_decode(x,strlen(x),res);

И res (который должен быть не менее половины длины параметра in) теперь содержит2 байта 0x12,0x34

Обратите внимание также, что для этого кода требуется шестнадцатеричные буквы AF, чтобы быть заглавными, af не будет (и он не выполняет никакой проверки ошибок - поэтому вам придется передать еедействительный материал).

7 голосов
/ 04 августа 2011

Вы можете использовать strtol(), который является частью avr-libc , или вы можете легко написать только свой конкретный случай:

unsigned char charToHexDigit(char c)
{
  if (c >= 'A')
    return c - 'A' + 10;
  else
    return c - '0';
}

unsigned char stringToByte(char c[2])
{
  return charToHexDigit(c[0]) * 16 + charToHexDigit(c[1]);
}
0 голосов
/ 14 июня 2019
Here's a version that works with both upper and lower-case hex strings:

void hex_decode(const char *in, size_t len, uint8_t *out)
{
  unsigned int i, hn, ln;
  char hc, lc;

  memset(out, 0, len);

  for (i = 0; i < 2*len; i += 2) {

    hc = in[i];
    if ('a' <= hc && hc <= 'f') hc = toupper(hc);
    lc = in[i+1];
    if ('a' <= lc && lc <= 'f') lc = toupper(lc);

    hn = hc > '9' ? hc - 'A' + 10 : hc - '0';
    ln = lc > '9' ? lc - 'A' + 10 : lc - '0';

    out[i >> 1] = (hn << 4 ) | ln;
  }
}
0 голосов
/ 15 апреля 2015

Это работает, но может быть значительно оптимизировано!

inline uint8_t  twoAsciiByteToByte(const std::string& s)
{
    uint8_t r = 0;

    if (s.length() == 4)
    {
        uint8_t a = asciiToByte(s[0]);
        uint8_t b = asciiToByte(s[1]);
        uint8_t c = asciiToByte(s[2]);
        uint8_t d = asciiToByte(s[3]);

        int h = (a * 10 + b);
        int l = (c * 10 + d);

        if (s[0] == '3')
            h -= 30;
        else if (s[0] == '4')
            h -= 31;

        if (s[2] == '3')
            l -= 30;
        else if (s[2] == '4')
            l -= 31;

        r = (h << 4) | l;
    }

    return r;
}
0 голосов
/ 02 января 2013

Задача:

Преобразовать строку, содержащую шестнадцатеричные символы ascii, в ее байтовые значения, чтобы ascii "FF" стало 0xFF, а ascii "10" (x31x30x00) стало 0x10

char asciiString[]="aaAA12fF";// input ascii hex string 
char result[4];               // byte equivalent of the asciiString (the size should be at half of asciiString[])

// конечный результат должен быть:

result[0] = 0xAA;
result[1] = 0xAA;       
result[2] = 0x12;
result[3] = 0xFF;

// 1.Шаг шага: преобразуйте asciiString, чтобы он содержал только верхние регистры:

// convert string to upper cases:
stringToUpperCases(asciiString);

use:

void stringToUpperCases(char *p)
{   
    for(int i=0; *(p+i) !='\0'; i++)
    {
        *(p+i) = (unsigned char) toupper( *(p+i) );
    }
}

// 2.Преобразовать строку, содержащую шестнадцатеричные символы ascii, в ее байтовые значения:

// convert string to bytes:

int nrOfBytes = stringToBytes(asciiString,result);

//use:  
unsigned char charToHexDigit(char c)
{
if (c >= 'A')
    return (c - 'A' + 10);
else
    return (c - '0');
}

unsigned char ascii2HexToByte(char *ptr)
{
    return charToHexDigit( *ptr )*16 + charToHexDigit( *(ptr+1) );
}

int stringToBytes(char *string, char *result)
{
    int k=0;
    int strLen = strlen(string);

    for(int i = 0; i < strLen; i = i + 2)
    {
        result[k] = ascii2HexToByte( &string[i] );
        k++;
    }

    return k; // number of bytes in the result array 
}   

// 3.результат печати:

printNrOfBytes(nrOfBytes, result);

// использование:

void printNrOfBytes(int nr, char *p)
{
   for(int i= 0; i < nr; i++)
    {
        printf( "0x%02X ", (unsigned char)*(p+i) );
    }
    printf( "\n");
}

// 4.Результат должен быть:

0xAA 0xAA 0x12 0xFF

// 5.Это тестовая программа:

char asciiString[]="aaAA12fF"; // input ascii hex string 
char result[4];                // result  
// convert string to upper cases:
stringToUpperCases(asciiString);

// convert string to bytes
int nrOfBytes = stringToBytes(asciiString,result);

// print result:
printNrOfBytes(nrOfBytes, result);

// result:
//  0xAA 0xAA 0x12 0xFF
...