K&R C Programs Exercise 4-2

Exercise 4-2. Extend atof to handle scientific notation of the form 123.45e-6 where a floating-point number may be followed by e or E and 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 i advances through all four
  • Exponent signesign is 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 or pow() 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

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>