在一个字节中转换两个ASCII十六进制字符(两个ASCII字节)

时间:2011-08-03 20:42:27

标签: c ascii hex avr-gcc

我想将两个ASCII字节转换为一个十六进制字节。 例如。

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

ASCII字节是09之间的数字,或AF之间的字母(仅大写),因此在0x30之间。 .. 0x390x41 ... 0x46

我知道如何使用数字0x4F0x34来构建“0x46 : 0x4F = 0x34 * 0x10 + 0x46

所以,实际上,我想以十六进制值转换一个ASCII字节。

为此,我可以构建和数组以将十六进制值分配给ASCII字符:

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

但是,也许它有一个最“适当”的解决方案。

该程序将在AVRμC上运行,并使用avr-gcc进行编译,因此scanf() / printf()解决方案不适用。

你有个主意吗? 感谢

6 个答案:

答案 0 :(得分:11)

我无法理解您的示例,但是如果您想将包含十六进制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

另请注意,此代码需要十六进制字母A-F为大写字母,a-f不会执行(并且它不会执行任何错误检查 - 因此您必须将其传递给有效的东西)。

答案 1 :(得分:7)

您可以使用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]);
}

答案 2 :(得分:0)

任务:

将包含十六进制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);

使用:

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

答案 3 :(得分:0)

它有效,但可以进行大量优化!

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;
}

答案 4 :(得分:0)

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;
  }
}

答案 5 :(得分:0)

将2个十六进制字符转换为一个字节需要两个步骤:

  1. char ab转换为其编号(例如'F'-> 0xF),否则将转换成两个大数字分支,检查字符是否在'0''9''A''F''a''f'的范围内。

  2. 在第二步中,通过将a(最大值为0xF0b0000_FFFF))4向左({{ 1}}-> a << 4),然后对0b1111_0000ab)进行按位或运算:

(a << 4) | b
a: 0000_1111
b: 1111_0000
-> 1111_1111