K&R C Programs Exercise 5-2

Exercise 5-2. Write getfloat, the floating-point analog of getint. What type does getfloat return as its function value?

getfloat returns int — the same as getint. This might seem surprising since it reads a double. The return value is used as a status indicator: it returns the terminating non-numeric character (so the caller can check for EOF or detect input errors), not the value itself. The actual floating-point value is stored through the pointer parameter double *pn. This is the same convention as scanf: return value = status, output via pointer.

Solution

/* K&R Exercise 5-2 — getfloat: floating-point analog of getint
 * Compile: gcc -ansi -Wall ex5-2.c -o ex5-2 */
#include <stdio.h>
#include <ctype.h>

#define BUFSIZE 100
static char buf[BUFSIZE];
static int  bufp = 0;

int  getch(void)    { return (bufp > 0) ? buf[--bufp] : getchar(); }
void ungetch(int c) { if (bufp < BUFSIZE) buf[bufp++] = c; }

/* Returns: terminating non-digit char (or EOF); value via *pn.
 * Returns 0 (not EOF, not digit) if non-numeric input. */
int getfloat(double *pn)
{
    int    c, sign, next;
    double power;

    while (isspace(c = getch()))
        ;

    if (!isdigit(c) && c != '.' && c != EOF && c != '+' && c != '-') {
        ungetch(c);
        return 0;
    }

    sign = (c == '-') ? -1 : 1;

    if (c == '+' || c == '-') {
        next = getch();
        if (!isdigit(next) && next != '.') {
            ungetch(next);
            ungetch(c);
            return c;
        }
        c = next;
    }

    /* integer part */
    for (*pn = 0.0; isdigit(c); c = getch())
        *pn = 10.0 * *pn + (c - '0');

    /* fractional part */
    if (c == '.') {
        c = getch();
        for (power = 1.0; isdigit(c); c = getch()) {
            *pn = 10.0 * *pn + (c - '0');
            power *= 10.0;
        }
        *pn /= power;
    }

    *pn *= sign;
    if (c != EOF) ungetch(c);
    return c;
}

#define SIZE 10

int main(void)
{
    double a[SIZE];
    int n, ret;

    printf("Enter floats (Ctrl-D to end):\n");
    for (n = 0; n < SIZE && (ret = getfloat(&a[n])) != EOF; n++)
        ;
    printf("Read %d values:\n", n);
    for (int i = 0; i < n; i++)
        printf("  a[%d] = %g\n", i, a[i]);
    return 0;
}

The Return Type Question

What it returns Why
int Status: the terminating character or EOF; not the float itself
NOT double The value is written through double *pn; the return value is status, not data

Compile and Test

echo "3.14 -2.718 0.5 99" | ./ex5-2

Sample Output

Read 4 values:
  a[0] = 3.14
  a[1] = -2.718
  a[2] = 0.5
  a[3] = 99

What This Exercise Teaches

  • Status vs value via pointer — the pattern of returning status as the function value and delivering data through a pointer parameter is fundamental C idiom (used by scanf, fgets, etc.)
  • Fractional part parsing — accumulate the fractional digits as if they were integers, then divide by the accumulated power of 10
  • Sign and pushback — the fix from Exercise 5-1 (push back sign if not followed by digit) applies here too

Set Up Your C Environment

← Exercise 5-1  | 
Chapter 5 Solutions  | 
Exercise 5-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>