#include <stdio.h>
double atof(char s[]);
int main(int argc, char *argv[])
{
int i;
char *strings[] = {
"123.45e-6",
"123.45E-6",
"123.45E6",
"-1.2e03",
NULL
};
for (i=0; *strings[i]; i++)
printf("atof(%s) = %25.15f\n", strings[i], atof(strings[i]) );
return 0;
}
/*
* Convert a string to a double.
*
* atof can convert strings of the form 123.45e-6 to a double. The exponent
* marker e, can be lower case or upper case. The exponent is optinally
* signed.
*
* @param s the string to convert to double.
*
* @return the double representation of the string s.
*/
double atof(char s[])
{
double val, power;
int i, sign, exponent, esign;
/* Skip whitespace */
for (i=0; isspace(s[i]); i++) {}
/* Convert the sign if present. */
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-') {i++;}
/* Convert the whole number portion. */
for (val = 0.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - '0');
}
if (s[i] == '.') {i++;}
/* Convert the fractional portion. power keeps track of the number of
* place values after the decimal. */
for (power = 1.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
/* Check for exponent marker. */
exponent = 0.0;
if (s[i] == 'e' || s[i] == 'E')
{
i++;
/* Convert sign on the exponent. */
esign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-') {i++;}
/* Convert the exponent. */
for (exponent = 0.0; isdigit(s[i]); i++)
{
exponent = 10.0 * exponent + (s[i] - '0');
}
}
/* Return the converted value. The position for the decimal point must be
* calculated before returning. Floats of the form 123.45e-6 will need
* to be calculated slightly differently. */
if (exponent)
{
val = val * sign / power;
while (exponent)
{
if (esign == 1)
{
val *= 10.0;
}
else
{
val /= 10.0;
}
exponent--;
}
return val;
}
else
{
return sign * val / power;
}
}