exc/k&r/05-pointers-and-arrays/05-01-02.c

102 lines
2.3 KiB
C

#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
int getint(int *p);
int getfloat(float *p);
/* ungetchar: push char c back to input stream */
#define ungetchar(c) ungetc(c, stdin)
/* tests getfloat, prints input to output, puts valid numbers
* in brackets : n -> [n] */
int main()
{
float x;
int r;
while ((r = getfloat(&x)) != EOF)
if (!r) {
int c;
putchar(getchar());
while (!isdigit(c = getchar()) && c != EOF && c != '-' && c != '+')
putchar(c);
ungetchar(c);
} else
printf("[%g]", x);
return 0;
}
/* we assert that EOF is negative */
static_assert(EOF < 0, "EOF is not a negative number");
/* ugetint: gets unsigned int from input to n
* n must be intialized by caller
* takes optional arguments for loop increment
* last char read is stored in varvar_c */
#define ugetint(var_c, n, ...) \
do { \
for (; isdigit(var_c = getchar()); __VA_ARGS__) \
n = 10 * (n) + var_c - '0'; \
} while (0)
/* getint : gets int from input and overwrites it to p
* returns 1 on valid integer, 0 if no integer is found
* and EOF on EOF. */
int getint(int *p)
{
int c;
if ((c = getchar()) == EOF)
return EOF;
/* handle sign */
int sign = (c == '-') ? -1 : ((c == '+') ? 1 : 0);
if (sign)
c = getchar();
if (!isdigit(c)) { /* not a number */
ungetchar(c);
if (sign)
ungetchar((sign > 0) ? '+' : '-');
return 0;
}
*p = c - '0';
ugetint(c, *p);
ungetchar(c);
*p *= (sign) ? sign : 1;
return 1;
}
#define DEC_SEP X('.') X(',')
#define EXP_SEP X('e') X('E')
/* getfloat : gets float from input and overwrites it to p
* returns 1 on valid integer, 0 if no integer is found
* and EOF on EOF. */
int getfloat(float *p)
{
char flag;
int n;
if ((flag = getint(&n)) < 1) /* not a number */
return flag;
*p = n;
int exp, c = getchar();
/* fractional part */
#define X(C) c == C ||
if (DEC_SEP 0) {
n = exp = 0;
ugetint(c, n, exp--);
*p += n * pow(10, exp);
}
#undef X
/* exponent part */
#define X(C) c == C ||
if ((EXP_SEP 0) && getint(&exp)) {
*p *= pow(10, exp);
} else
ungetchar(c);
return 1;
}