102 lines
2.3 KiB
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;
|
||
|
}
|