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

在一个字节中转换两个ASCII十六进制字符(两个ASCII字节),c,ascii,hex,avr-gcc,C,Ascii,Hex,Avr Gcc,我想把两个ASCII字节转换成一个十六进制字节。 例如 0x30 0x43=>0x0C、0x34 0x46=>0x4F ASCII字节是介于0和9之间的数字,或者是介于a和F之间的字母(仅大写),因此介于0x30之间0x39和0x410x46 我知道如何用数字“构造”0x34和0x46:0x4F=0x34*0x10+0x46 所以,事实上,我想把一个ASCII字节转换成十六进制值 为此,我可以构建和数组以将十六进制值分配给ASCII字符: 0x30 => 0x00 0x31 => 0

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

0x30 0x43=>0x0C、0x34 0x46=>0x4F

ASCII字节是介于
0
9
之间的数字,或者是介于
a
F
之间的字母(仅大写),因此介于
0x30
之间<代码>0x39和
0x41
<代码>0x46

我知道如何用数字“构造”
0x34
0x46:0x4F=0x34*0x10+0x46

所以,事实上,我想把一个ASCII字节转换成十六进制值

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

0x30 => 0x00
0x31 => 0x01
...
0x46 => 0x0F
但是,也许它有一个最“合适”的解决方案

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

你有主意了吗? 谢谢

您可以使用,这是的一部分,或者您可以非常轻松地编写您的特定案例:

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

我无法理解您的示例,但如果您想将包含十六进制ascii字符的字符串转换为其字节值(例如,字符串“56”变为字节0x56,则可以使用此选项(假设您的系统使用ascii)

和res(必须至少是参数中
长度的一半)现在包含2个字节0x12,0x34

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

任务:

将包含十六进制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.第一步:转换ascistring,使其仅包含大写字母:

// 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 
}   
//使用:

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

它的作品,但可以大大优化

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;
}
内联uint8\u t两个二进制字节(const std::string&s)
{
uint8_t r=0;
如果(s.长度()==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);
如果(s[0]=“3”)
h-=30;
如果(s[0]=='4',则为else
h-=31;
如果(s[2]=“3”)
l-=30;
如果(s[2]='4')
l-=31;

r=(h以下是一个同时适用于大写和小写十六进制字符串的版本:

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;
  }
}
void十六进制解码(const char*in、size\t len、uint8\t*out)
{
无符号整数i,hn,ln;
char-hc,lc;
memset(out,0,len);
对于(i=0;i<2*len;i+=2){
hc=in[i];

如果('a'1]=(hn将2个十六进制字符转换为一个字节分两步完成:

  • char
    a
    b
    转换为它们的数字(例如
    'F'
    ->
    0xF
    ),这是在两个大的if-else分支中完成的,它们检查char是否在
    '0'
    '9'
    'a'/code>到
    'F'
    'a'/code>到
    'F'
    的范围内


  • 在第二步中,通过将
    a
    (最大值为
    0xF
    0b0000\u FFFF
    4
    移到左侧(
    a
    0b1111\u 0000
    ),然后对
    a
    b
    (a=0x30&&a没有ASCII字节或十六进制字节。你(显然!)我们要做的是将一对字节转换为一个字节,方法是将两个字节解释为ASCII符号,ASCII符号反过来表示十六进制数字,并发出相应的十六进制值。解决这类问题需要精确理解您真正在做什么;精确的通信也有很大帮助:)你必须确保你从根本上理解了数据是什么。正如大卫所说,字节只是字节;没有ASCII字节或十六进制字节。ASCII字节=表示ASCII字符的字节,十六进制字节=表示十六进制的字节。我知道字节只是字节;我只是不知道如何解释它。但其他人已经理解了我所说的蚂蚁。这不是最重要的吗?好吧,这太简单了…我想用4位左旋转来表示0到9之间的数字,但解决方法更简单!谢谢你这是个玩笑?:$man ascii Aucune entrée de manuel pourascii@Loic:不,您一定缺少手册页。这是英文版本:Use
    (在[i]| 32中)-“a”+10
    现在您可以支持大写和小写(最有可能的是,在机器代码中只需再添加一条指令).它不是一个字节吗?如果它应该包含两个字节,那么它不是应该是一个字节吗?@Rudy Velthuis它应该是一个字节,因为它包含一个字节,而不是一个字节2@nos:是的,我看到它是一个uint8_t.Brain fart数组,对不起。请确保包含cytpe.hinline uint8_t asciiToByte(char c){if(c>='0'&&c='A'&&c'
    void printNrOfBytes(int nr, char *p)
    {
       for(int i= 0; i < nr; i++)
        {
            printf( "0x%02X ", (unsigned char)*(p+i) );
        }
        printf( "\n");
    }
    
    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
    
    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;
    }
    
    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;
      }
    }
    
    a: 0000_1111
    b: 1111_0000
    -> 1111_1111
    
    #include <stdio.h>
    #include <stdint.h>
    
    #define u8 uint8_t
    #define u32 uint32_t
    
    u8 to_hex_digit(char a, char b) {
        u8 result = 0;
    
        if (a >= 0x30 && a <= 0x39) {
            result = (a - 0x30) << 4;
        } else if (a >= 0x41 && a <= 0x46) {
            result = (a - 0x41 + 10) << 4;
        } else if (a >= 0x61 && a <= 0x7A) {
            result = (a - 0x61 + 10) << 4;
        } else {
            printf("invalid hex digit: '%c'\n", a);
        }
    
        if (b >= 0x30 && b <= 0x39) {
            result |= b - 0x30;
        } else if (b >= 0x41 && b <= 0x46) {
            result |= b - 0x41 + 10;
        } else if (b >= 0x61 && b <= 0x7A) {
            result |= b - 0x61 + 10;
        } else {
            printf("invalid hex digit: '%c'\n", b);
        }
    
        return result;
    }
    
    u32 main() {
        u8 result = to_hex_digit('F', 'F');
        printf("0x%X (%d)\n", result, result);
    
        return 0;
    }