Convert two ASCII Hexadecimal Characters (Two ASCII bytes) in one byte

后端 未结 6 2259
余生分开走
余生分开走 2020-12-18 13:08

I want to convert two ASCII bytes to one hexadecimal byte. eg.

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

The ASCII bytes are a number bet

相关标签:
6条回答
  • 2020-12-18 13:17

    i can't make sense of your examples, but if you want to convert a string containing hexadecimal ascii characters to its byte value (e.g. so the string "56" becomes the byte 0x56, you can use this (which assumes your system is using 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;
    }
    

    You'd use it like e.g.

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

    And res (which must be at least half the length of the in parameter) now contains the 2 bytes 0x12,0x34

    Note also that this code needs the hexadecimal letters A-F to be capital, a-f won't do (and it doesn't do any error checking - so you'll have to pass it valid stuff).

    0 讨论(0)
  • 2020-12-18 13:18

    The task:

    Convert a string containing hexadecimal ascii characters to its byte values so ascii "FF" becomes 0xFF and ascii "10" (x31x30x00) becomes 0x10

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

    // the final result should be:

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

    //1. Firt step: convert asciiString so it contains upper cases only:

    // 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. Convert a string containing hexadecimal ascii characters to its byte values:

    // 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. print result:

    printNrOfBytes(nrOfBytes, result);
    

    // use:

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

    //4. The result should be:

    0xAA 0xAA 0x12 0xFF

    //5. This is the test program:

    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
    
    0 讨论(0)
  • 2020-12-18 13:29

    It's works, but could be much optimized !

    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 讨论(0)
  • 2020-12-18 13:32

    You can use strtol(), which is part of avr-libc, or you can write just your specific case pretty easily:

    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 讨论(0)
  • 2020-12-18 13:38

    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 讨论(0)
  • 2020-12-18 13:41

    Converting 2 hex chars to a byte is done in two steps:

    1. Convert char a and b to their number (e.g. 'F' -> 0xF), which is done in two big if else branches, that check if the char is in the range '0' to '9', 'A' to 'F' or 'a' to 'f'.

    2. In the 2nd step the two numbers are joined by shifting a (largest value is 0xF (0b0000_FFFF)) 4 to the left (a << 4 -> 0b1111_0000) and then apply the bitwise or operation on a and b ((a << 4) | b):

    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;
    }
    
    0 讨论(0)
提交回复
热议问题