For comparison, here's a simple, straightforward version of atoi()
, that accepts an arbitrary base to use (i.e. not necessarily 10):
#include <ctype.h>
int myatoi(const char *str, int b)
{
const char *p;
int ret = 0;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
ret = b * ret + (*p - '0');
return ret;
}
(Note that I have left out negative number handling.)
Once you've got that, it's straightforward to detect a decimal point and handle digits to the right of it as well:
double myatof(const char *str, int b)
{
const char *p;
double ret = 0;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
ret = b * ret + (*p - '0');
if(*p == '.')
{
double fac = b;
for(p++; *p != '\0' && isdigit(*p); p++)
{
ret += (*p - '0') / fac;
fac *= b;
}
}
return ret;
}
A slightly less obvious approach, which might be numerically better behaved, is:
double myatof2(const char *str, int b)
{
const char *p;
long int n = 0;
double denom = 1;
for(p = str; *p != '\0' && isspace(*p); p++)
;
for(; *p != '\0' && isdigit(*p); p++)
n = b * n + (*p - '0');
if(*p == '.')
{
for(p++; *p != '\0' && isdigit(*p); p++)
{
n = b * n + (*p - '0');
denom *= b;
}
}
return n / denom;
}
I tested these with
#include <stdio.h>
int main()
{
printf("%d\n", myatoi("123", 10));
printf("%d\n", myatoi("10101", 2));
printf("%f\n", myatof("123.123", 10));
printf("%f\n", myatof("101.101", 2));
printf("%f\n", myatof2("123.123", 10));
printf("%f\n", myatof2("101.101", 2));
return 0;
}
which prints
123
21
123.123000
5.625000
123.123000
5.625000
as expected.
One more note: these functions don't handle bases greater than 10.