Exercise 4-2. Extend
atofto handle scientific notation of the form123.45e-6where a floating-point number may be followed byeorEand an optionally signed exponent.
The K&R atof in Section 4.2 handles sign, integer part, and fractional part. Scientific notation adds a third stage: after the mantissa, look for e or E, then read an optional sign and the exponent digits. The exponent is applied as a power of 10. A negative exponent divides; a positive exponent multiplies. The cleanest implementation accumulates the exponent as a positive integer and applies sign at the end, rather than adjusting val one digit at a time.
Solution
/* K&R Exercise 4-2 — atof with scientific notation
* Compile: gcc -ansi -Wall ex4-2.c -o ex4-2 */
#include <stdio.h>
#include <ctype.h>
double atof(const char s[])
{
double val, power;
int i, sign, esign, exp;
/* skip whitespace */
for (i = 0; isspace(s[i]); i++)
;
/* optional sign */
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
/* integer part */
for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');
/* fractional part */
if (s[i] == '.')
i++;
for (power = 1.0; isdigit(s[i]); i++) {
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
val = sign * val / power;
/* scientific notation: e or E */
if (s[i] == 'e' || s[i] == 'E') {
i++;
esign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (exp = 0; isdigit(s[i]); i++)
exp = 10 * exp + (s[i] - '0');
if (esign == 1)
while (exp-- > 0) val *= 10.0;
else
while (exp-- > 0) val /= 10.0;
}
return val;
}
int main(void)
{
printf("%g\n", atof("123.45e-6")); /* 0.00012345 */
printf("%g\n", atof("1.0e+3")); /* 1000 */
printf("%g\n", atof("-2.5E2")); /* -250 */
printf("%g\n", atof("3.14159")); /* 3.14159 */
printf("%g\n", atof("42")); /* 42 */
return 0;
}
The exponent loop uses repeated multiplication/division instead of pow() to avoid requiring -lm and to match the self-contained spirit of K&R’s original.
Compile and Run
gcc -ansi -Wall ex4-2.c -o ex4-2
./ex4-2
Sample Output
0.00012345 1000 -250 3.14159 42
What This Exercise Teaches
- Multi-stage parsing — sign → integer → fraction → exponent; each stage is independent and the same index
iadvances through all four - Exponent sign —
esignis determined before consuming the exponent digits; accumulate exponent as a positive integer and apply direction afterward - Avoiding
pow()— repeated multiply/divide works for integer exponents and keeps the function self-contained; for large exponents a lookup table orpow()is better
Set Up Your C Environment
← Exercise 4-1 |
Chapter 4 Solutions |
Exercise 4-3 →
Book: The C Programming Language, 2nd Ed — Kernighan & Ritchie