Question

I could not find a way to convert a string into an array of hexadecimal bytes in C++, I have an example in C # only:

public static byte[] ToBytes(string input)
{
   byte[] bytes = new byte[input.Length / 2];
   for (int i = 0, j = 0; i < input.Length; j++, i += 2)
      bytes[j] = byte.Parse(input.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
   return bytes;
}

I tried this way

byteRead = "02000000ce1eb94f04b62e21dba62b396d885103396ed096fbb6c1680000000000000000223cc23c0df07a75eff6eabf22d6d5805105deff90f1617f27f58045352b31eb9d0160538c9d001900000000";

    // BYTES HEX
    char *hexstring = new char[byteRead.length()+1];
    strcpy(hexstring,byteRead.c_str());       
    uint8_t str_len = strlen(hexstring);       
    for (i = 0; i < (str_len / 2); i++) {
       sscanf(hexstring + 2*i, "%02x", &bytearray[i]);
    }

UPDATED

Here are a solution, this work for me on Arduino Uno:

char hexstring[] = "020000009ecb752aac3e6d2101163b36f3e6bd67d0c95be402918f2f00000000000000001036e4ee6f31bc9a690053320286d84fbfe4e5ee0594b4ab72339366b3ff1734270061536c89001900000000";
    int i;
    int bytearray[80];
    char tmp[3];
    tmp[2] = '\0';
    int j = 0;
    for(i=0;i<strlen(hexstring);i+=2) {
        tmp[0] = hexstring[i];
        tmp[1] = hexstring[i+1];
        bytearray[j] = strtol(tmp,0,16);
        j+=1;
     }
    for(i=0;i<80;i+=1) {
       Serial.println(bytearray[i]);
     }
Was it helpful?

Solution

First of all, you are using an unhealthy mix of C and C++; try to choose one or the other and stick to it (that is, use its idioms). Your code has a memory leak, unnecessary copies, etc...

Second, you just need two things:

  1. A way to convert two consecutive characters (hexadecimal digits) into their numeric counterpart (as a char I guess ?)
  2. A way to store the successive conversions

For the first, whilst indeed you could sscanf, C++ tends to lean toward using istream instead though here it's tricky because of the absence of "stops"; so we can just do it manually:

char fromHexadecimal(char const digit) {
    if ('0' <= digit and digit <= '9') { return digit - '0'; }
    if ('a' <= digit and digit <= 'f') { return 10 + digit - 'a'; }
    if ('A' <= digit and digit <= 'F') { return 10 + digit - 'A'; }
    throw std::runtime_error("Unknown hexadecimal digit");
}

char fromHexadecimal(char digit0, char digit1) {
    return fromHexadecimal(digit0) * 16 + fromHexadecimal(digit1);
}

With that hurdle out of the way, we can just use strings both for input and output; after all a string is just a collection of char:

std::string fromHexadecimal(std::string const& hex) {
    if (hex.size() % 2 != 0) {
        throw std::runtime_error("Requires an even number of hex digits");
    }

    std::string result;
    for (size_t i = 0, max = hex.size() / 2; i != max; ++i) {
        result.push_back(fromHexadecimal(hex.at(2*i), hex.at(2*i+1)));
    }

    return result;
}

OTHER TIPS

Get two characters at a time from the string (see e.g. std::string::substr), and use std::stoi to convert to an integer value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top