Exercise 5-2. Write
getfloat, the floating-point analog ofgetint. What type doesgetfloatreturn 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