R
RoSsIaCrIiLoIA
I a poor beginner defy this NG to write an ANSI-C portable
int readint(FILE* fp);
better of my in the treatment of a stream
______________
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')
#define mult10(x) ( ((x)<<3) + ((x)<<1) )
int readint(FILE* fp);
int main(void)
{int x, y, z, h;
P("Two ints>"); fflush(stdout);
x = readint(stdin);
printf("c1=%c\n", (char) (z=fgetc(stdin)));
if(z!=EOF) ungetc(z, stdin);
y = readint(stdin);
printf("c2=%c\n", (char) (z=fgetc(stdin)));
if(z!=EOF)
{if(z!='\n') printf("c3=%c\n", (char) (h=fgetc(stdin)));
if(h!=EOF && z!='\n') ungetc(h, stdin);
ungetc(z, stdin);
}
P("x=%d y=%d\n", x, y);
R 0;
}
/* it gets an integer from fp; it is allowed this input
* [' \t'] {'+'} or {'-'} ['0123456789']
* range=( -INT_MAX, INT_MAX )
* on error it returns INT_MAX (number too big or not good input)
* or -INT_MAX (a negative number too big).
*
* Bug: When it is met a not-number preceded from '+' or '-'
* => '+' or '-' is popped from stream (if I use 2 times ungetc =>
* Standard say i can use safety it one time only *or* it not could
* be possible preserve the state of stream for the use of scanf,
* getc, fgetc ...)
* Examples:
* fp="+a+bbb" -> readint(fp)=INT_MAX, fp="a+bbb"
* fp="++aabbb" -> readint(fp)=INT_MAX, fp="+aabbb"
*fp="+999999999999999999999999999+9" -> readint(fp)=INT_MAX, fp="+9"
*fp="-999999999999999999999999999+9" -> readint(fp)=-INT_MAX, fp="+9"
* fp="+EOF" -> readint(fp)=INT_MAX, fp="EOF"
* fp="add" -> readint(fp)=INT_MAX, fp="add"
* fp="+8989s"-> readint(fp)=8989 , fp="s"
*/
int readint(FILE* fp)
{int c, sign = +1;
unsigned n;
assert(fp != NULL);
if( feof(fp) ) R INT_MAX;
/* jumps spaces [' ', '\t' *not* '\n']*/
W( (c = fgetc(fp))==' ' || c=='\t' ) ;
if(c=='+') ;
else if(c=='-') sign = -1;
else if(!is_digit(c))
{label:
if(c != EOF) ungetc(c, fp);
R INT_MAX;
}
if(!is_digit(c) && (c = fgetc(fp), !is_digit(c)) )
goto label;
n = 0; /* here c would be digit */
W(1)
{
if( n > (INT_MAX - ( c - '0' ))/10 )
{ n = INT_MAX; break; }
n = mult10(n) + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(is_digit(c)) /* it jumps big numbers */
W( c = fgetc(fp), is_digit(c));
if(c != EOF) ungetc(c, fp);
R sign * ((int) n);
}
int readint(FILE* fp);
better of my in the treatment of a stream
______________
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')
#define mult10(x) ( ((x)<<3) + ((x)<<1) )
int readint(FILE* fp);
int main(void)
{int x, y, z, h;
P("Two ints>"); fflush(stdout);
x = readint(stdin);
printf("c1=%c\n", (char) (z=fgetc(stdin)));
if(z!=EOF) ungetc(z, stdin);
y = readint(stdin);
printf("c2=%c\n", (char) (z=fgetc(stdin)));
if(z!=EOF)
{if(z!='\n') printf("c3=%c\n", (char) (h=fgetc(stdin)));
if(h!=EOF && z!='\n') ungetc(h, stdin);
ungetc(z, stdin);
}
P("x=%d y=%d\n", x, y);
R 0;
}
/* it gets an integer from fp; it is allowed this input
* [' \t'] {'+'} or {'-'} ['0123456789']
* range=( -INT_MAX, INT_MAX )
* on error it returns INT_MAX (number too big or not good input)
* or -INT_MAX (a negative number too big).
*
* Bug: When it is met a not-number preceded from '+' or '-'
* => '+' or '-' is popped from stream (if I use 2 times ungetc =>
* Standard say i can use safety it one time only *or* it not could
* be possible preserve the state of stream for the use of scanf,
* getc, fgetc ...)
* Examples:
* fp="+a+bbb" -> readint(fp)=INT_MAX, fp="a+bbb"
* fp="++aabbb" -> readint(fp)=INT_MAX, fp="+aabbb"
*fp="+999999999999999999999999999+9" -> readint(fp)=INT_MAX, fp="+9"
*fp="-999999999999999999999999999+9" -> readint(fp)=-INT_MAX, fp="+9"
* fp="+EOF" -> readint(fp)=INT_MAX, fp="EOF"
* fp="add" -> readint(fp)=INT_MAX, fp="add"
* fp="+8989s"-> readint(fp)=8989 , fp="s"
*/
int readint(FILE* fp)
{int c, sign = +1;
unsigned n;
assert(fp != NULL);
if( feof(fp) ) R INT_MAX;
/* jumps spaces [' ', '\t' *not* '\n']*/
W( (c = fgetc(fp))==' ' || c=='\t' ) ;
if(c=='+') ;
else if(c=='-') sign = -1;
else if(!is_digit(c))
{label:
if(c != EOF) ungetc(c, fp);
R INT_MAX;
}
if(!is_digit(c) && (c = fgetc(fp), !is_digit(c)) )
goto label;
n = 0; /* here c would be digit */
W(1)
{
if( n > (INT_MAX - ( c - '0' ))/10 )
{ n = INT_MAX; break; }
n = mult10(n) + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(is_digit(c)) /* it jumps big numbers */
W( c = fgetc(fp), is_digit(c));
if(c != EOF) ungetc(c, fp);
R sign * ((int) n);
}