I have done a similar thing before and I think this might help you.
The following works for me:
int main(){
int co[8];
char ch[8];
printf("please enter the string:");
scanf("%s", ch);
for (int i=0; i<=7; i++) {
if ((ch[i]>='A') && (ch[i]<='F')) {
co[i] = (unsigned int) ch[i]-'A'+10;
} else if ((ch[i]>='0') && (ch[i]<='9')) {
co[i] = (unsigned int) ch[i]-'0'+0;
}
}
Here, I have only taken a string of 8 characters.
If you want you can add similar logic for 'a' to 'f' to give their equivalent hex values. Though, I haven't done that because I didn't need it.
Or if you want to have your own implementation, I wrote this quick function as an example:
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
uint32_t hex2int(char *hex) {
uint32_t val = 0;
while (*hex) {
// get current character then increment
uint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
So, after a while of searching, and finding out that strtol is quite slow, I've coded my own function. It only works for uppercase on letters, but adding lowercase functionality ain't a problem.
I know this is really old but I think the solutions looked too complicated. Try this in VB:
Public Function HexToInt(sHEX as String) as long
Dim iLen as Integer
Dim i as Integer
Dim SumValue as Long
Dim iVal as long
Dim AscVal as long
iLen = Len(sHEX)
For i = 1 to Len(sHEX)
AscVal = Asc(UCase(Mid$(sHEX, i, 1)))
If AscVal >= 48 And AscVal <= 57 Then
iVal = AscVal - 48
ElseIf AscVal >= 65 And AscVal <= 70 Then
iVal = AscVal - 55
End If
SumValue = SumValue + iVal * 16 ^ (iLen- i)
Next i
HexToInt = SumValue
End Function
Use strtol if you have libc available like the top answer suggests. However if you like custom stuff or are on a microcontroller without libc or so, you may want a slightly optimized version without complex branching.
#include <inttypes.h>
/**
* xtou64
* Take a hex string and convert it to a 64bit number (max 16 hex digits).
* The string must only contain digits and valid hex characters.
*/
uint64_t xtou64(const char *str)
{
uint64_t res = 0;
char c;
while ((c = *str++)) {
char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8);
res = (res << 4) | (uint64_t) v;
}
return res;
}
The bit shifting magic boils down to: Just use the last 4 bits, but if it is an non digit, then also add 9.
// makes a number from two ascii hexa characters
int ahex2int(char a, char b){
a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
b = (b <= '9') ? b - '0' : (b & 0x7) + 9;
return (a << 4) + b;
}
You have to be sure your input is correct, no validation included (one could say it is C). Good thing it is quite compact, it works with both 'A' to 'F' and 'a' to 'f'.
The approach relies on the position of alphabet characters in the ASCII table, let's peek e.g. to Wikipedia (https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png). Long story short, the numbers are below the characters, so the numeric characters (0 to 9) are easily converted by subtracting the code for zero. The alphabetic characters (A to F) are read by zeroing other than last three bits (effectively making it work with either upper- or lowercase), subtracting one (because after the bit masking, the alphabet starts on position one) and adding ten (because A to F represent 10th to 15th value in hexadecimal code). Finally, we need to combine the two digits that form the lower and upper nibble of the encoded number.
Here we go with same approach (with minor variations):
#include <stdio.h>
// takes a null-terminated string of hexa characters and tries to
// convert it to numbers
long ahex2num(unsigned char *in){
unsigned char *pin = in; // lets use pointer to loop through the string
long out = 0; // here we accumulate the result
while(*pin != 0){
out <<= 4; // we have one more input character, so
// we shift the accumulated interim-result one order up
out += (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble
pin++; // go ahead
}
return out;
}
// main function will test our conversion fn
int main(void) {
unsigned char str[] = "1800785"; // no 0x prefix, please
long num;
num = ahex2num(str); // call the function
printf("Input: %s\n",str); // print input string
printf("Output: %x\n",num); // print the converted number back as hexa
printf("Check: %ld = %ld \n",num,0x1800785); // check the numeric values matches
return 0;
}
I like @radhoo solution, very efficient on small systems. One can modify the solution for converting the hex to int32_t (hence, signed value).
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
int32_t hex2int(char *hex) {
uint32_t val = *hex > 56 ? 0xFFFFFFFF : 0;
while (*hex) {
// get current character then increment
uint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
Note the return value is int32_t while val is still uint32_t to not overflow.
Here is a solution building upon "sairam singh"s solution. Where that answer is a one to one solution, this one combines two ASCII nibbles into one byte.
// Assumes input is null terminated string.
//
// IN OUT
// -------------------- --------------------
// Offset Hex ASCII Offset Hex
// 0 0x31 1 0 0x13
// 1 0x33 3
// 2 0x61 A 1 0xA0
// 3 0x30 0
// 4 0x00 NULL 2 NULL
int convert_ascii_hex_to_hex2(char *szBufOut, char *szBufIn) {
int i = 0; // input buffer index
int j = 0; // output buffer index
char a_byte;
// Two hex digits are combined into one byte
while (0 != szBufIn[i]) {
// zero result
szBufOut[j] = 0;
// First hex digit
if ((szBufIn[i]>='A') && (szBufIn[i]<='F')) {
a_byte = (unsigned int) szBufIn[i]-'A'+10;
} else if ((szBufIn[i]>='a') && (szBufIn[i]<='f')) {
a_byte = (unsigned int) szBufIn[i]-'a'+10;
} else if ((szBufIn[i]>='0') && (szBufIn[i]<='9')) {
a_byte = (unsigned int) szBufIn[i]-'0';
} else {
return -1; // error with first digit
}
szBufOut[j] = a_byte << 4;
// second hex digit
i++;
if ((szBufIn[i]>='A') && (szBufIn[i]<='F')) {
a_byte = (unsigned int) szBufIn[i]-'A'+10;
} else if ((szBufIn[i]>='a') && (szBufIn[i]<='f')) {
a_byte = (unsigned int) szBufIn[i]-'a'+10;
} else if ((szBufIn[i]>='0') && (szBufIn[i]<='9')) {
a_byte = (unsigned int) szBufIn[i]-'0';
} else {
return -2; // error with second digit
}
szBufOut[j] |= a_byte;
i++;
j++;
}
szBufOut[j] = 0;
return 0; // normal exit
}