Convert chars from pointer to integer num - c

if the user enter a string,than is save every part of it with strtok, and one of the part was numbers, how i can convert this numbers to integer?
my goal is to get this string : "matrix 3 3 ", and to verify that the user didnt enter double or float, just integer num. I tried to do casting but it is didnt work
thx!

There are different possible ways, but concerning
my goal is [...] to verify that the user didnt enter double or float, just integer num.
you probably aim for full input validation. In that case, you must use strtol().
#include <stdlib.h>
#include <limits.h>
int main(void)
{
const char *str = "42"; // in your code, some result from strtok
char *endptr;
long num = strtol(str, &endptr, 10);
if (endptr == str || *endptr)
{
// not parsed successfully
return 1; // error and out ... do whatever is suitable
}
if (num > INT_MAX || num < INT_MIN)
{
// value was outside int range
return 1;
}
int x = (int)num;
return 0;
}
If you actually want a long, for checking the range, set errno to 0 before calling strtol() and check for errno == ERANGE afterwards. (include errno.h for this)
For the sake of completeness, in response to your comment, of course you can do it all manually, but it's tedious and error prone and less efficient, so I'd never recommend that. See here an example for parsing unsigned integers from strings, with error checking:
#include <stdio.h>
#include <string.h>
// write result to *result, return 0 on error, 1 on success:
int parseuint(unsigned int *result, const char *str)
{
if (!str || !*str) return 0;
size_t len = strlen(str);
unsigned char bcd[len];
for (size_t i = 0; i < len; ++i)
{
if (str[i] < '0' || str[i] > '9') return 0;
bcd[i] = str[i] - '0';
}
size_t scanstart = 0;
*result = 0;
unsigned int mask = 1;
while (scanstart < len)
{
if (!mask) return 0;
if (bcd[len-1] & 1) *result |= mask;
mask <<=1;
for (size_t i = len-1; i > scanstart; --i)
{
bcd[i] >>= 1;
if (bcd[i-1] & 1) bcd[i] |= 8;
}
bcd[scanstart] >>= 1;
while (scanstart < len && !bcd[scanstart]) ++scanstart;
for (size_t i = scanstart; i < len; ++i)
{
if (bcd[i] > 7) bcd[i] -= 3;
}
}
return 1;
}
int main(void)
{
unsigned int a;
if (parseuint(&a, "4258"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 4258");
}
if (parseuint(&a, "13.7"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 13.7");
}
if (parseuint(&a, "12345678901234567890"))
{
printf("parsed: %u\n", a);
}
else
{
puts("error parsing 12345678901234567890");
}
}

Related

Decimal to octal converter in c [duplicate]

I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}

Convert long integer(decimal) to base 36 string (strtol inverted function in C)

I can use the strtol function for turning a base36 based value (saved as a string) into a long int:
long int val = strtol("ABCZX123", 0, 36);
Is there a standard function that allows the inversion of this? That is, to convert a long int val variable into a base36 string, to obtain "ABCZX123" again?
There's no standard function for this. You'll need to write your own one.
Usage example: https://godbolt.org/z/MhRcNA
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *reverse(char *str)
{
char *end = str;
char *start = str;
if(!str || !*str) return str;
while(*(end + 1)) end++;
while(end > start)
{
int ch = *end;
*end-- = *start;
*start++ = ch;
}
return str;
}
char *tostring(char *buff, long long num, int base)
{
int sign = num < 0;
char *savedbuff = buff;
if(base < 2 || base >= sizeof(digits)) return NULL;
if(buff)
{
do
{
*buff++ = digits[abs(num % base)];
num /= base;
}while(num);
if(sign)
{
*buff++ = '-';
}
*buff = 0;
reverse(savedbuff);
}
return savedbuff;
}
One of the missing attributes of this "Convert long integer to base 36 string" is string management.
The below suffers from a potential buffer overflow when destination is too small.
char *long_to_string(char *destination, long num, int base);
(Assuming 32-bit long) Consider the overflow of below as the resultant string should be "-10000000000000000000000000000000", which needs 34 bytes to encode the string.
char buffer[33]; // Too small
long_to_string(buffer, LONG_MIN, 2); // Oops!
An alternative would pass in the buffer size and then provide some sort of error signaling when the buffer is too small.
char* longtostr(char *dest, size_t size, long a, int base)
Since C99, code instead could use a compound literal to provide the needed space - without calling code trying to compute the needed size nor explicitly allocate the buffer.
The returned string pointer from TO_BASE(long x, int base) is valid until the end of the block.
#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(long)*CHAR_BIT + 2)
// v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))
char *my_to_base(char *buf, long a, int base) {
assert(base >= 2 && base <= 36);
long i = a < 0 ? a : -a; // use the negative side - this handle _MIN, _MAX nicely
char *s = &buf[TO_BASE_N - 1];
*s = '\0';
do {
s--;
*s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[-(i % base)];
i /= base;
} while (i);
if (a < 0) {
s--;
*s = '-';
}
// Could add memmove here to move the used buffer to the beginning
return s;
}
#include <limits.h>
#include <stdio.h>
int main(void) {
long ip1 = 0x01020304;
long ip2 = 0x05060708;
long ip3 = LONG_MIN;
printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16), TO_BASE(ip3, 16));
printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2), TO_BASE(ip3, 2));
puts(TO_BASE(ip1, 8));
puts(TO_BASE(ip1, 36));
puts(TO_BASE(ip3, 10));
}
Here is another option with no need for source array of charaters, but less portable since not all character encodings have contiguous alphabetic characters, for example EBCDIC. Test HERE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
char get_chars(long long value)
{
if (value >= 0 && value <= 9)
return value + '0';
else
return value - 10 + 'A';
}
void reverse_string(char *str)
{
int len = strlen(str);
for (int i = 0; i < len/2; i++)
{
char temp = str[i];
str[i] = str[len - i - 1];
str[len - i - 1] = temp;
}
}
char* convert_to_base(char *res, int base, long long input)
{
bool flag = 0;
int index = 0;
if(input < 0){
input = llabs(input);
flag = 1;
}
else if(input == 0){
res[index++] = '0';
res[index] = '\0';
return res;
}
while(input > 0)
{
res[index++] = get_chars(input % base);
input /= base;
}
if(flag){
res[index++] = '-';
}
res[index] = '\0';
reverse_string(res);
return res;
}
int main() {
long long input = 0;
printf("** Integer to Base-36 **\n ");
printf("Enter a valid number: ");
scanf("%lld", &input);
if(input >= LLONG_MAX && input <= LLONG_MIN){
printf("Invalid number");
return 0;
}
int base = 36;
char res[100];
printf("%lld -> %s\n", input, convert_to_base(res, base, input));
return 0;
}

How to convert ascii string to binary?

I'm trying to convert an ascii string to a binary string in C. I found this example Converting Ascii to binary in C but I rather not use a recursive function. I tried to write an iterative function as opposed to a recursive function, but the binary string is missing the leading digit. I'm using itoa to convert the string, however itoa is a non standard function so I used the implementation from What is the proper way of implementing a good "itoa()" function? , the one provided by Minh Nguyen.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int32_t ascii_to_binary(char *input, char **out, uint64_t len)
{
uint32_t i;
uint32_t str_len = len * 8;
if(len == 0)
{
printf("Length argument is zero\n");
return (-1);
}
(*out) = malloc(str_len + 1);
if((*out) == NULL)
{
printf("Can't allocate binary string: %s\n", strerror(errno));
return (-1);
}
if(memset((*out), 0, (str_len)) == NULL)
{
printf("Can't initialize memory to zero: %s\n", strerror(errno));
return (-1);
}
for(i = 0; i < len; i++)
itoa((int32_t)input[i], &(*out)[(i * 8)], 2);
(*out)[str_len] = '\0';
return (str_len);
}
int main(void)
{
int32_t rtrn = 0;
char *buffer = NULL;
rtrn = ascii_to_binary("a", &buffer, 1);
if(rtrn < 0)
{
printf("Can't convert string\n");
return (-1);
}
printf("str: %s\n", buffer);
return (0);
}
I get 1100001 for ascii character a, but I should get 01100001, so how do I convert the ascii string to the whole binary string?
You could change the for loop to something like this:
for(i = 0; i < len; i++) {
unsigned char ch = input[i];
char *o = *out + 8 * i;
int b;
for (b = 7; b >= 0; b--)
*o++ = (ch & (1 << b)) ? '1' : '0';
}
or similar:
for(i = 0; i < len; i++) {
unsigned char ch = input[i];
char *o = &(*out)[8 * i];
unsigned char b;
for (b = 0x80; b; b >>= 1)
*o++ = ch & b ? '1' : '0';
}
This program gets and integer ( which contains 32 bits ) and converts it to binary, Work on it to get it work for ascii strings :
#include <stdio.h>
int main()
{
int n, c, k;
printf("Enter an integer in decimal number system\n");
scanf("%d", &n);
printf("%d in binary number system is:\n", n);
for (c = 31; c >= 0; c--)
{
k = n >> c;
if (k & 1)
printf("1");
else
printf("0");
}
printf("\n");
return 0;
}
Best just write a simple function to do this using bitwise operators...
#define ON_BIT = 0x01
char *strToBin(char c) {
static char strOutput[10];
int bit;
/*Shifting bits to the right, but don't want the output to be in reverse
* so indexing bytes with this...
*/
int byte;
/* Add a nul at byte 9 to terminate. */
strOutput[8] = '\0';
for (bit = 0, byte = 7; bit < 8; bit++, byte--) {
/* Shifting the bits in c to the right, each time and'ing it with
* 0x01 (00000001).
*/
if ((c >> bit) & BIT_ON)
/* We know this is a 1. */
strOutput[byte] = '1';
else
strOutput[byte] = '0';
}
return strOutput;
}
Something like that should work, there's loads of ways you can do it. Hope this helps.

How do I change an array of characters into an array of integers?

More specifically, how do I change'
char tempList[256] = "1 -2 -8 4 5";
into something like this:
int tempListNum[256] = {1, -2, -8, 4, 5};
?
I tried this, but I don't know how to append the array.
for (int j = 0; j < 256; j++)
{
if(TEMPS[j] == 45 && (TEMPS[j+1] >= 48 && TEMPS[j+2] >= 48))
{
numToAppend = ((TEMPS[j+1]-'0')*10 + (TEMPS[j+2]-'0')) * -1;
}
if(TEMPS[j] == 45 && TEMPS[j+1] >= 48)
{
numToAppend = (TEMPS[j+1]-'0') * -1;
}
if(TEMPS[j] >= 48)
{
numToAppend = TEMPS[j]-'0';
}
if(TEMPS[j] >= 48 && TEMPS[j+1] >= 48)
{
numToAppend = TEMPS[j]*10 + TEMPS[j+1];
}
}
you can use strtok with space as separator and then use atoi standard library function
Write a function that goes through tempList char by char:
While it encounters only numbers, it should turn them into an int. If there are more than 1 digit, it should multiply the first digit with 10 and add then add it to the int, etc.
When it encounters a space, it should add the newly created int to tempListNum and skip the space.
When it encounters a minus sign, it should multiply the currently created int with -1.
Repeat these steps until end of list.
You can try this
unsigned char index1 = 0,index2 =0;
int PrevValue = 0;
for(;index1 <= 255;index1 ++)
{
if(tempList[index1] != ' ') //space
{
tempListNum[index2] = PrevValue*10 + (tempList[index1]-0x30);
PrevValue = tempListNum[index2] ;
}
else
{
PrevValue = 0;
index2++;
}
}
You can add further optimizations and other validations.
This isn't terribly difficult. I'd recommend a custom strtoi function instead of atoi since atoi allows for little error handling. For example, atoi("1.3") would return 1 with no other way to get other information like the fact that ".3" makes it not an integer. Moreover, the value 1 is obviously within the range of the int type, so even errno may not be of help.
That is why I write and use strtoi below, which uses the C library's strtol function and has the same behaviors. If you need help understanding what strtoi does, look up documentation for strtol since they're pretty much the same except for the range of valid values (between INT_MIN and INT_MAX, both inclusive, instead of between LONG_MIN and LONG_MAX, both inclusive).
#include <stdio.h>
#include <stdlib.h> //strtol
#include <string.h> //strtok
#include <limits.h> //INT_MIN, INT_MAX
#include <errno.h> //errno, ERANGE
int
strtoi (const char *s, char **rem, int base)
{
long n;
int esave = errno;
errno = 0;
n = strtol (s, rem, base);
if (n < INT_MIN || n > INT_MAX)
errno = ERANGE;
if (errno)
{
if (n == LONG_MAX)
return INT_MAX;
return INT_MIN;
}
errno = esave;
return (int) n;
}
int
main (void)
{
char tempList[256] = "1 -2 -8 4 5";
int tempListNum[128] = {0};
int i, n;
char *listPtr;
char *listPtr2;
listPtr = strtok (tempList, " ");
for (i = 0;
listPtr != NULL && (size_t) i < sizeof tempListNum / sizeof tempListNum[0];
++i)
{
errno = 0;
n = strtoi (listPtr, &listPtr2, 10);
if (*listPtr2)
{
fprintf (stderr, "error: value `%s' is not an integer ... ignoring value\n", listPtr);
--i;
}
// value out of range or some other implementation-defined error
else if (errno)
{
perror (listPtr);
}
listPtr = strtok (NULL, " ");
}
// n is now the number of items in the array
n = i;
for (i = 0; i < n; ++i)
printf ("%d\n", tempListNum[i]);
}
You could obviously avoid strtok and just use strtoi by itself. That might actually be a cleaner solution!
Is this a homework assignment, or maybe a interview question?
I haven't tested this, but you could do something like this:
#define enum _error {
success = 0,
parse_error,
out_of_memory,
invalid_arg,
insuficient_buffer
} error;
error parse_int(
char **pp,
int *val)
{
error e = success;
char neg = 0;
if (!pp || !*pp || !val) {
e = invalid_arg;
goto exit;
}
*val = 0;
while (**pp) {
if (**pp == '-') {
if (val) {
e = parse_error;
goto exit;
}
neg = 1;
}
else if (**pp >= '0' **pp <= '9') {
*val *= 10;
*val += **pp - '0';
}
else {
break;
}
++*pp;
}
if (neg) {
*val *= -1;
}
exit:
return e;
}
error parse_array_of_ints(
char *p,
unsigned int parsed_ints_size,
int **parsed_ints)
{
error e = success;
unsigned int cur = 0;
if (!p || !parsed_ints) {
e = invalid_arg;
goto exit;
}
for (;;) {
while (*p && *p != '-' && *p < '0' && *p > '9') {
p++;
}
if (!*p) {
break;
}
if (cur = parsed_ints_size) {
e = insuficient_buffer;
goto exit;
}
e = parse_int(&p, parsed_ints+cur);
if (e != success) {
goto exit;
}
cur++;
}
exit:
return e;
}
For example, with while loop and functions sscanf and strtok from strings.h.
#include <stdio.h>
#include <string.h>
int main (void)
{
char tempList[256] = "1 -2 -8 4 5";
int tempListNum[256] = {0};
int cnt = 0;
int tmp = 0;
char * str = strtok (tempList," ");
while(str != NULL)
{
if(sscanf(str, "%d", &tmp))
{
tempListNum[cnt] = tmp;
cnt++;
}
// read next number
str = strtok (NULL," ");
}
// test output
for(tmp = 0; tmp < cnt; tmp++)
{
printf("%d ", tempListNum[tmp]);
}
return 0;
}
Tested in Visual Studio 2012.
Consider this short example:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char tempList[256] = "1 -2 -8 4 5";
int tempListNum[256] = {0};
int numCnt = 0;
char * pEnd = tempList;
int number = 0;
while( strlen(pEnd) > 0)
{
tempListNum[numCnt] = strtol (pEnd,&pEnd,0);
numCnt++;
}
for(number = 0; number < numCnt; number++)
{
printf("%d ", tempListNum[number]);
}
return 0;
}
You can try this :
char tempList[256] = "1 -2 -8 4 5";
int tempListNum[256]
int i=0,k=0;
while(i<256)
{
int num=0;
for(int j=0;tempList[j]!=' ';j++)
{
int neg=0,counter=0; //Not worked in C for a long time and I am not sure if it supports Bools
if(a[j]=='-')
neg=1;
else
num=num*10+int(tempList[j])-int('0');
counter++;
}
if(neg==1)
num=-num;
tempListNum[k]=num;
k++; i+=counter;
}
use this: it works on me.
#include <stdio.h>
#include <ctype.h>
#include <math.h>
int main() {
char tempList[256] = "1 -2 -82 43 5";
char tempNumber[10];
int tempNumberCounter = 0;
int i, j,counter=0, isNegative = 1;
int numTempList[256] = {0};
for(i=0; tempList[i] != '\0'; i++) {
if(tempList[i-1] == '-') {
isNegative = -1;
}
if(isdigit(tempList[i])) {
tempNumber[tempNumberCounter] = tempList[i];
tempNumberCounter++;
}
if(tempList[i] == ' ' || tempList[i+1] == '\0') {
tempNumber[tempNumberCounter] = '\0';
for(j=0; j<strlen(tempNumber); j++) {
numTempList[counter] += (tempNumber[j] - '0') * pow(10, strlen(tempNumber)-j-1);
}
numTempList[counter] *= isNegative;
counter++;
tempNumberCounter = 0;
*tempNumber = 0;
isNegative = 1;
}
}
for(i=0; numTempList[i] != 0; i++) {
printf("%d ", numTempList[i]);
}
return 0;
}
numTempList is the converted array from tempList. this is just a sample implementation of char to int array, you can refactor this into functions so that you can reuse this functionality..
Modified:
Now it can also read multiple digits

C code to convert hex to int

I am writing this code to convert a hex entry into its integer equivalent. So A would be 10 and B would be 11 etc. This code acts weirdly, in that it seg. faults at random locations and including an extra newline character at times will get it to work. I am trying to debug it, just so I can understand what I am doing wrong here. Can anyone take a look and help me here ? Thanks a lot for your time.
/* Fixed working code for anyone interested */
#include <stdio.h>
#include <stdlib.h>
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
int dec;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
if ( temp[i] == '\0')
{
return ;
}
if (temp[i] == '0' || temp[i] == 'x' || temp[i] == 'X' )
{
printf("0");
answer = temp[i];
}
// compare each temp[i] with all contents in hexchar[]
int j;
int a = temp[i];
for ( j=0; hexchar[j] != '\0'; j++)
{
if ( temp[i] == hexchar[j] )
{
answer *= 16;
answer = answer + 10 + (j/2);
// printf("%d\n",answer );
break;
}
}
}
return answer;
}
main()
{
char *test[] =
{ "bad",
"aabbdd"
"0100",
"0x1",
"0XA",
"0X0C0BE",
"abcdef",
"123456",
"0x123456",
"deadbeef",
"zog_c"
};
int answer=0;
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
printf("main():Number of chars = %d\n",numberOfChars);
int i;
// Go through each character and convert Hex to Integers.
for ( i = 0; i<numberOfChars;i++)
{
// Need to take the first char and then go through it and convert
it.
answer = hextoint(test[i]);
printf("%d\n",answer );
}
}
Let's take a look.
unsigned int hextoint(const char temp[])
{
int i;
int answer = 0;
char hexchar[] = "aAbBcCdDeEfF" ;
for ( i=0; temp[i] != '\0'; i++ )
{
printf("In here");
printf("%c\t",temp[i] );
}
return answer;
}
This doesn't seem to even try to do any conversion. It should always return 0, since answer is never assigned any other value. Normally, you'd do something like:
for (i=0; input[i] != '\0'; i++) {
answer *= 16;
answer += digit_value(input[i]);
}
return answer;
Where digit_value (obviously enough) returns the value of an individual digit. One way to do this is:
int digit_value(char input) {
input = tolower(input);
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
return -1; // signal error.
}
Then, looking at main:
main()
{
Depending on the "implicit int" rule is generally poor practice, at least IMO. It's much better to specify the return type.
// Calculate the number of char's.
int numberOfChars;
numberOfChars = sizeof test /sizeof test[0];
This actually calculates the number of strings, not the number of chars.
for ( i = 0; i<=numberOfChars;i++)
Valid subscripts run from 0 through the number of items - 1, so this attempts to read past the end of the array (giving undefined behavior).
This'll work for any number within the unsigned int range, the nice thing is it does not use any other library functions so it is great for micro-controllers where space is tight.
unsigned int hexToInt(const char *hex)
{
unsigned int result = 0;
while (*hex)
{
if (*hex > 47 && *hex < 58)
result += (*hex - 48);
else if (*hex > 64 && *hex < 71)
result += (*hex - 55);
else if (*hex > 96 && *hex < 103)
result += (*hex - 87);
if (*++hex)
result <<= 4;
}
return result;
}
The problem is with calculating numberOfChars part. sizeof test is actually the size of the pointer, not the total length of all characters in your array, so the number returned in your code would be 1, which makes the for loop go to the second index of test (test[1]) which does not have a \0 at the end. Try using strlen for calculating numberOfChars.
This may not me the most optimal method, but it should work without problem.
unsigned int hex_to_int(const char* hex) {
unsigned int result = 0;
size_t len = strlen(hex);
for (size_t i = 0; i < len; ++i) {
char cur_char = tolower(hex[len - i - 1]);
// direct return if encounter any non-hex character.
if (!(isdigit(cur_char) && (cur_char >= 'a' && cur_char <= 'f'));)
return result;
unsigned int char_val = (isdigit(cur_char) ? cur_char - '0' : 10 + cur_char - 'a');
result += round(pow(16, i)) * char_val;
}
return result;
}

Resources