How to turn a string hex code into its ASCII translation

So I need to convert this hex data 526f736574746120436f646521 into its ASCII translation and store it as a string in Arduino. The hex conversion should come out as Rosetta Code! The hex is also being stored as a string. Could anyone help me in completing this task? Thanks

so the hexadecimal would not be separated, it would be in one long string. also this would have to happen many many times in the code. the entire code will constantly repeat with different hexadecimal each time. so if there someone is has a function that could translate the hexadecimal value of 526f736574746120436f646521 that would be greate.

const char input[] = "526f736574746120436f646521";
char output[(sizeof(input) + 1) / 2];

void setup() {
  Serial.begin(250000);
  const char* ptr = input;
  for (byte i = 0; i < sizeof(output) - 1; i++) {
    output[i] = aNibble(*ptr++);
    output[i] <<= 4;
    output[i] |= aNibble(*ptr++);
  }
  Serial.write('"');
  Serial.print(output);
  Serial.println("\"");
}
void loop() {}

byte aNibble(char in) {
  if (in >= '0' && in <= '9') {
    return in - '0';
  } else if (in >= 'a' && in <= 'f') {
    return in - 'a' + 10;
  } else if (in >= 'A' && in <= 'F') {
    return in - 'A' + 10;
  }
  return 0;
}
"Rosetta Code!"

Please don't send technical questions as PMs.

Cybertonic:
Thanks so for the code Whandall! it works perfectly.
I have a question about it though, how would I use it multiple times in the code, each translating different hex data?

const char input[] = "526f736574746120436f646521";
const char riddle[] = "436F70792026207061737465206D616B6573206C617A7920616E64206C6561647320746F20627261696E206174726F7068792E";
char output[65];

void setup() {
  Serial.begin(250000);
  Serial.write('"');
  Serial.print(unHex(input, output, sizeof(output)));
  Serial.write('"');
  Serial.println();
  Serial.write('"');
  Serial.print(unHex(riddle, output, sizeof(output)));
  Serial.write('"');
  Serial.println();
}
void loop() {}

char * unHex(const char* input, char* target, size_t len) {
  if (target != nullptr && len) {
    size_t inLen = strlen(input);
    if (inLen & 1) {
      Serial.println(F("unhex: malformed input"));
    }
    size_t chars = inLen / 2;
    if (chars >= len) {
      Serial.println(F("unhex: target buffer too small"));
      chars = len - 1;
    }
    for (size_t i = 0; i < chars; i++) {
      target[i] = aNibble(*input++);
      target[i] <<= 4;
      target[i] |= aNibble(*input++);
    }
    target[chars] = 0;
  } else {
    Serial.println(F("unhex: no target buffer"));
  }
  return target;
}

byte aNibble(char in) {
  if (in >= '0' && in <= '9') {
    return in - '0';
  } else if (in >= 'a' && in <= 'f') {
    return in - 'a' + 10;
  } else if (in >= 'A' && in <= 'F') {
    return in - 'A' + 10;
  }
  return 0;
}

Whandall could you please explain your code? it works great, but I am having trouble understanding it.

No, I will not spoonfeed you basic C code, I already did your homework.

And, as I already stated

436F70792026207061737465206D616B6573206C617A7920616E64206C6561647320746F20627261696E206174726F7068792E

Which gets transformed into

"Copy & paste makes lazy and leads to brain atrophy."

@OP

1. Say, this is your hex number: 0x1c34 or any combination of 0 - 9, A - F or 0 - 9, a - f.

2. There are two bytes data in Step-1, and these are: 0x1c and 0x34 or 0x1C and 0x34. Here, 0x refers to hexadecimal base.

3. You want that every digit of the data of Step-2 should be transformed into its ASCII code. This is to say that 1 would be converted to 0x31 (hex), c would be transformed to 0x43 (hex) as per following ASCII table.


Figure-1: ASCII Table for the characters of English Language Alphabet

4. Let us see how we can obtain 0x31 for 1 from Fig-1 using C Codes.
(1) let us observe that: 0x31 = 0x30 + 0x01

(2) Form Step-4(1), it is deduced that that he ASCII code could be found by adding the hex digit with 0x30. That is -- the ASCII code of 1 is: ==> 0x01 + 0x30 = 0x31.

(3) For C, the ASCII code is: 0x43 ==> 0x0C + 0x37.

5. Based on the analysis of Step-4, we can form the following structure:

obtains 1st byte (0x1c) of the given number and save into variable byte x;.
Extract 1st digit (0x01 from left) of 0x1c and save into variable byte y;.
if(y <= 0x09)
{
   y = y + 0x30;  //y holds the ASCII code of any digit from 0 - 9 = 0x30 - 0x39 (note: 0x30 = '0')
}
else
{
   y = y + 0x37;  //y holds ASCII code of any digit from A - F (a - f) = 0x41 - 0x46 (note: 0x41 = 'A')
}

6. Finally, we can write as:

byte myData [] = {0x52, 0x6f, 0x73, 0x65, 0x74, 0x74, 0x61, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x21}; 
char myASCII[26] = "";    //to hold the ASCII codes of the digits of the given number

byte x1 = sizeof(myData);   //x1 = 13
for(int i = 0, j=0; i<x1, j<2*x1; i++, j++)
{
   byte x = myData[i];     //x = 52
   x = x>>4;                  //x=05
   if(x <= 9)
   {
       x = x + 0x30;  //x holds ASCII codes of any digit from 0 - 9 as the case be
       myASCII [j] = x;    //myASCII[0] holds ASCII codes of digits 0 - 9 as the case be
   }
   else
   {
       x = x + 0x37;  // x = ASCII code of digits: A - F
       myASCII [j] = x;    //myASCII[0] holds ASCII codes of digits: A - F as the case be
   }
}

Some people just want to make things look hard (or get paid by the LOC)

   myASCII [j] = "0123456789abcdef"[x];

(someone else can sort out the train-wreck of a for loop)

TheMemberFormerlyKnownAsAWOL:

myASCII [j] = "0123456789abcdef" [x];

The above does not work well with the following definition:

myASCII [j] = "0123456789abcdef" [x];

Screen shot:

with myASCII [j] = "0123456789abcdef"[x];

f as appered as 0x66 (ASCII code of alphabet f) and not as 0x46 (ASCII code of digit F/f)
SMascii.png
Codes:

byte myData [] = {0x52, 0x6f, 0x73, 0x65, 0x74, 0x74, 0x61, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x21};
char myASCII[26] = "";    //to hold the ASCII codes of the digits of the given number
byte x;

void setup()
{
  Serial.begin(9600);
  byte x1 = sizeof(myData);   //x1 = 13
  for (int i = 0, j = 0; i < x1, j < 2 * x1; i++, j++)
  {
    x = myData[i];     //x = 52
    x = x >> 4;                //x=05
    myASCII [j] = "0123456789abcdef"[x];//= myCode(x);
    //------------------------------------
    j++;
    x = myData[i];     //x = 52
    x = x & 0x0F;                //x=05
    myASCII [j] = "0123456789abcdef"[x];//= myCode(x);
    //-------------------------
  }
  for (int i = 0; i < 26; i++)
  {
    Serial.print(myASCII[i], HEX);
    Serial.print(' ');
  }
}

void loop()
{

}

Screen shot:

with myASCII [j] = "0123456789ABCDEF"[x];

F has appeared as 0x46 (ASCII code of digit F).
smascii2.png

smascii2.png

SMascii.png

GolamMostafa:
The above does not work well with the following definition:

myASCII [j] = "0123456789abcdef" [x];

myASCII [j] = (youCanChooseUppercase ? "0123456789ABCDEF" : "0123456789abcdef") [x];
Or select "toupper"

so the hexadecimal would not be separated, it would be in one long string. also this would have to happen many many times in the code. the entire code will constantly repeat with different hexadecimal each time. so if there someone is has a function that could translate the hexadecimal value of 526f736574746120436f646521 that would be greate.

Cybertonic:
so the hexadecimal would not be separated, it would be in one long string. also this would have to happen many many times in the code. the entire code will constantly repeat with different hexadecimal each time. so if there someone is has a function that could translate the hexadecimal value of 526f736574746120436f646521 that would be greate.

Didn't Whandall already supply that to you?

No whandall uses constants, not allowing for constantly different variables.

Cybertonic:
No whandall uses constants, not allowing for constantly different variables.

That's not true.

Where is your minimal failing sketch?

const char input[] = "526f736574746120436f646521";
const char p1[] = "636F6E7374206D65616E73206F6E6C79207468617420";
const char p2[] = "74686520646174612077696C6C206E6F74206265206368616E676564";

char riddle[129];
char output[65];

void setup() {
  Serial.begin(250000);
  Serial.write('"');
  Serial.print(unHex(input, output, sizeof(output)));
  Serial.write('"');
  Serial.println();
  strcpy(riddle, p1);
  strcat(riddle, p2);
  Serial.write('"');
  Serial.print(unHex(riddle, output, sizeof(output)));
  Serial.write('"');
  Serial.println();
}
void loop() {}

char * unHex(const char* input, char* target, size_t len) {
  if (target != nullptr && len) {
    size_t inLen = strlen(input);
    if (inLen & 1) {
      Serial.println(F("unhex: malformed input"));
    }
    size_t chars = inLen / 2;
    if (chars >= len) {
      Serial.println(F("unhex: target buffer too small"));
      chars = len - 1;
    }
    for (size_t i = 0; i < chars; i++) {
      target[i] = aNibble(*input++);
      target[i] <<= 4;
      target[i] |= aNibble(*input++);
    }
    target[chars] = 0;
  } else {
    Serial.println(F("unhex: no target buffer"));
  }
  return target;
}

byte aNibble(char in) {
  if (in >= '0' && in <= '9') {
    return in - '0';
  } else if (in >= 'a' && in <= 'f') {
    return in - 'a' + 10;
  } else if (in >= 'A' && in <= 'F') {
    return in - 'A' + 10;
  }
  return 0;
}
"Rosetta Code!"
"const means only that the data will not be changed"

the data will be constantly changing, it will be inputted over serial, and the entire script will be in a loop

Cybertonic:
the data will be constantly changing, it will be inputted over serial, and the entire script will be in a loop

Not in any code I have seen from you.
There is a Robin2 tutorial for serial input, with only CR/LF as end-marker it's what your looking for.

I would rather not post my code, for it is barely anything. I would get a string from the serial connection and then turn it into hex code, twice. this system is an encryption/decryption message system. this entire system . would get inputs repetitively, thus the loop.