RoSsIaCrIiLoIA said:
I would [like to] know [the] consequences of two ungetc [calls]
You are guaranteed that it'll work the first time, but it's allowed to
fail after that until you either read back the character(s) or discard
them by changing the file position directly; check the return value or
don't do it.
By any chance, did you learn C by reading IOCCC entries? Despite quite
insane (and poorly stated) requirements, there's no need for code that
is as thoroughly obfuscated that which you appear to emit by default.
The third requirement (only pointers), is obviously impossible for any
function that returns an integer by any reasonable interpretation; so,
ignoring that, here's a quick implementation: (further testing needed)
#include <stdio.h>
#include <limits.h>
#include <errno.h>
/* C99 behaviour for negative operands even in C89, probably broken; I
* should've replaced it with something that I know to work. */
#define DIVC99( x, y ) ((x) / (y) \
+ ((x) / (y) < 0 && (x) % (y) > 0))
#define VAL( c ) (((c) >= '0' && (c) <= '9') ? c - '0' \
: ((c) == 'a' || (c) == 'A') ? 0xa \
: ((c) == 'b' || (c) == 'B') ? 0xb \
: ((c) == 'c' || (c) == 'C') ? 0xc \
: ((c) == 'd' || (c) == 'D') ? 0xd \
: ((c) == 'e' || (c) == 'E') ? 0xe \
: ((c) == 'f' || (c) == 'F') ? 0xf \
: -1)
/* Acts mostly like a hypothetical strtoi( instr, NULL, 0 ) */
int readINT( FILE *fp )
{
static int i, base, sign;
int c = fgetc( fp );
(base == 0) && (
i = 0,
sign = 1,
(c == '-') && (
sign = -1,
c = fgetc( fp ), 1
) || (c == '+') && (
c = fgetc( fp )
),
(c == '0') && (
base = 8,
c = fgetc( fp ),
(c == 'x' || c == 'X') && (
base = 16,
c = fgetc( fp )
), 1
) || (
base = 10
)
);
return
(c >= '0' && c <= '9' && c - '0' < base
|| base == 16
&& (c == 'a' || c == 'A' || c == 'b' || c == 'B'
|| c == 'c' || c == 'C' || c == 'd' || c == 'D'
|| c == 'e' || c == 'E' || c == 'f' || c == 'F')) ? (
(sign > 0) ? (
(i > INT_MAX / base) ? (
i = INT_MAX,
errno = ERANGE
) : (
i *= base
)
) : (
(i < DIVC99( INT_MIN, base )) ? (
i = INT_MIN,
errno = ERANGE
) : (
i *= base
)
),
(sign > 0) ? (
(i > INT_MAX - VAL( c )) ? (
i = INT_MAX,
errno = ERANGE
) : (
i += VAL( c )
)
) : (
(i < INT_MIN + VAL( c )) ? (
i = INT_MIN,
errno = ERANGE
) : (
i -= VAL( c )
)
),
readINT( fp )
) : (
ungetc( c, fp ),
base = 0,
i
);
}
int main( void )
{
int i;
do {
errno = 0;
i = readINT( stdin );
if (errno == ERANGE)
puts( "Out of range for int." );
printf( "%d\n", i );
while (i = fgetc( stdin ), i != '\n' && i != EOF)
;
} while (i != EOF);
return 0;
}
This style could be rendered more legible by selective application of
macros, such as IF, THEN, etc. It mightn't look much like C with all
that, but... actually, this whole exercise is pointless, so that also
would be.