you need to take 2 (hex) chars at the same time... then calculate the int value and after that make the char conversion like...
char d = (char)intValue;
do this for every 2chars in the hex string
this works if the string chars are only 0-9A-F:
#include <stdio.h>
#include <string.h>
int hex_to_int(char c){
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d){
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
int main(){
const char* st = "48656C6C6F3B";
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++){
if(i % 2 != 0){
printf("%c", hex_to_ascii(buf, st[i]));
}else{
buf = st[i];
}
}
}
Answer from sharpner on Stack Overflowyou need to take 2 (hex) chars at the same time... then calculate the int value and after that make the char conversion like...
char d = (char)intValue;
do this for every 2chars in the hex string
this works if the string chars are only 0-9A-F:
#include <stdio.h>
#include <string.h>
int hex_to_int(char c){
int first = c / 16 - 3;
int second = c % 16;
int result = first*10 + second;
if(result > 9) result--;
return result;
}
int hex_to_ascii(char c, char d){
int high = hex_to_int(c) * 16;
int low = hex_to_int(d);
return high+low;
}
int main(){
const char* st = "48656C6C6F3B";
int length = strlen(st);
int i;
char buf = 0;
for(i = 0; i < length; i++){
if(i % 2 != 0){
printf("%c", hex_to_ascii(buf, st[i]));
}else{
buf = st[i];
}
}
}
Few characters like alphabets i-o couldn't be converted into respective ASCII chars . like in string '6631653064316f30723161' corresponds to fedora . but it gives fedra
Just modify hex_to_int() function a little and it will work for all characters. modified function is
int hex_to_int(char c)
{
if (c >= 97)
c = c - 32;
int first = c / 16 - 3;
int second = c % 16;
int result = first * 10 + second;
if (result > 9) result--;
return result;
}
Now try it will work for all characters.
What am I missing here?
To be honest, the code is so far from plausible, that I am going to ignore that question and the code and just present a solution.
// Convert single Hex digit to integer 0-15
int HexNibbleToInt( char nibble )
{
return nibble > '9' ?
nibble - 'A' + 10 :
nibble - '0' ;
}
// Convert string of ASCII hex digit pairs representing
// character codes to character string.
size_t StrToHex( const char strIn[], char strOut[] )
{
int i = 0 ;
for( i = 0; strIn[i * 2] != 0; i++)
{
strOut[i] = HexNibbleToInt( strIn[i * 2] ) << 4 |
HexNibbleToInt( strIn[i * 2 + 1] ) ;
}
strOut[i] = 0 ;
return i;
}
Note that I have omitted the strLen parameter. If it is a pre-condition that the strIn is a null terminated string with an even number of characters, then then you do not need to calculate the length. Since strlen() has to iterate the string to find the NUL and you have to iterate the string in any case, it serves no purpose. Of course a malformed string that is not capitalised hex digit pairs will have undefined behaviour. That is easy to handle, but if the string has already been validated you might not want to spend CPU cycles doing it twice.
Note also that I have returned the length of the output which saves yet another unnecessary and potentially expensive call to strlen():
size_t output_len = StrToHex( hexbuffer, charbuffer ) ;
HAL_UART_Transmit( &huart3, charbuffer, output_len, 1000);
Moreover as this appears to be targeted at embedded code, I have avoided "expensive" functions such as sprintf() and strtoul(). If you are using them extensively already in the code, then there is probably little marginal cost in using them, but the initial cost of invoking them once may be rather high.
You're not doing anything to parse the hex. sprintf() doesn't do any parsing. You can use strtol() to parse a numeric string in a particular base.
You don't need to use sprintf() to write a single character to an array, just assign the value directly to the array element.
You need to make c a null-terminated string, so add '\0' to it, not '\n'. You don't actually need to append this explicitly, since you initialized the array to all zeroes.
Finally, you need to add a null terminator to strOut.
void Str2Hex(char strIn[],char strOut[], size_t strLen)
{
for(uint16_t i = 0; i < strLen; i += 2)
{
uint8_t c[3] = {0};
c[0] = strIn[i];
c[1] = strIn[i+1];
long ascii = strtoul(c, NULL, 16);
strOut[i/2] = ascii;
}
strOut[strLen/2] = '\0';
}
You need to build a number in base10, considering you have all the digits stored in char*buf like so:
//assumtions: n - number of digits
// digits are ordered MSD first -> buff[0] contains the most significant digit.
for(i=0;i<n;i++)
{
number += buf[n-i-1]*pow(10,i); //number+=digit*10^i
}
printf("%x\n", number);
you can use stdlib's atoi() function to convert a string to an integer:
char str[] = {0x32, 0x35, 0x34, 0x00};
int integer = atoi(str);
printf("%x\n", integer);
you can then printf() that integer as hex/dec or whatever. If this is too simple for your needs, then a more powerful alternative is to use sscanf()
If you are getting these integer strings from a comms buffer then you will likely want to split the buffer up into separate numbers first (perhaps they are separated by spaces for example). A simple way of doing this in C would be to use strtok().
EDIT: this edit is in response to the code that you have added to your question. I cannot comment on your question as I do not have enough reputation! The code you have added is broken. It will only work if a three digit string is provided, eg "001", "255". If a different number of digits are provided, it will read beyond the end of the string and produce garbage output, try "1" or "14", or "12314".
This is not an answer but an observation - using this since it formats code
static char lookup[] = { '0', '1', '2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
int j = 0;
for (i=0; i<ArraySize; ++i)
{
loc[j++] = lookup[(Tmp[i] & 0xf0) >> 4];
loc[j++] = lookup[Tmp[i] & 0xf];
}
loc[j] = 0;
makes the code a lot quicker and simpler.
Even though Ed already provided a shorter solution, i tried to figure out what was wrong because your code "looked" correct.
Let me guess: char1 is signed (e.g. type "char").
It then happens, that:
a byte in your file that is >127 keeps its sign during
&0xf0,and
>> 4is a signed shift which makes the bit-pattern keep the bit set in the most significant bitthen you compare
>9which is not the case because the sign-bit is still setthen you add
+'0'which can now lead to you having a byte with value 0 instead of something between '0'-'9' or 'A'-'F'.which terminates the string while printing
Here's a simplistic function to convert one character to a hexadecimal string.
char hexDigit(unsigned n)
{
if (n < 10) {
return n + '0';
} else {
return (n - 10) + 'A';
}
}
void charToHex(char c, char hex[3])
{
hex[0] = hexDigit(c / 0x10);
hex[1] = hexDigit(c % 0x10);
hex[2] = '\0';
}
Its pretty easy. Scan through character by character ... best to start from the end. If the character is a number between 0 and 9 or a letter between a and f then place it in the correct position by left shifting it by the number of digits you've found so far.
For converting to a string then you do similar but first you mask and right shift the values. You then convert them to the character and place them in the string.