ANSI C Challenge on readint

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);
}
 
K

Keith Thompson

RoSsIaCrIiLoIA said:
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

What is the purpose of these macros? If it's to save you a few
keystrokes, you're doing so by imposing a significant cost in time and
effort on your readers. That's not a good tradeoff.
#define is_digit(x) ('0'<=(x) && (x)<='9')

Why not use the standard isdigit() function?
#define mult10(x) ( ((x)<<3) + ((x)<<1) )

Sorry, but this is just dumb. If shifting and adding is more
efficient than multiplying by 10, your compiler can probably figure
that out. If it isn't, you're probably interfering with the
compiler's ability to optimize. And this is an input routine; it's
vanishingly unlikely that the few cycles you *might* save with your
mult10() macro will be significant compared to the time it's going to
take to read characters from an external device.

[snip]

I decline your challenge.
 
J

Jack Klein

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

[snip]

Sorry, I stopped reading right here. I have little tolerance for
deliberate (pick one):

1. stupidity

2. obfuscation

3. trolling
 
A

August Derleth

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

A laudable goal for a beginning C programmer.
#define P printf
#define R return
#define W while
#define F for

What. The. ****. Nobody in their right mind defines macros for stuff like
this. If you can't type out 'for', you'll never make it as a programmer.
#define is_digit(x) ('0'<=(x) && (x)<='9')

Don't define a macro to do a standard subroutine's job. (Hint: isdigit()).
#define mult10(x) ( ((x)<<3) + ((x)<<1) )

Trust the compiler to optimize this for you, if it needs to be optimized
at all. Doing things like this makes you look stupid. It does not impress
experienced coders and it does not make you an uber-leet h4x0r.

[snip]

Ye gods, what did I do to deserve this pile of garbage in my newsreader?
/* 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).

You've thought through the intent well enough to make a pretty good
comment block, but what if you actually happen to read the textual
representation of INT_MAX? How do we differentiate the error codes from a
possibly valid output?
*
* 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"
*/

The examples aren't needed. Everyone knows how atoi() should behave.
int readint(FILE* fp)
{int c, sign = +1;

+1? Just say 1. Give some credit to the programmer's intelligence.
unsigned n;

You wouldn't need to make n an unsigned if you'd stop trying to
out-optimize your own compiler. Just a hint.

[snip rest of atoi()]

Ugly, ugly code, made worse by massive macro abuse.
 
R

Richard Bos

RoSsIaCrIiLoIA said:
I a poor beginner defy this NG to write an ANSI-C portable

I, a regular, would like to ask the other regulars to finally ignore
this obvious, insistent troll, just like last time. Please?

Richard
 
K

Keith Thompson

August Derleth said:
+1? Just say 1. Give some credit to the programmer's intelligence.

Actually, assuming that "sign" is intended to represent a sign, +1 is
clearer than just 1, IMHO. (Given the rest of the code, though, I'm
not entirely sure I'd assume that "sign" represents a sign.)
 
C

Christopher Benson-Manica

Richard Bos said:
I, a regular, would like to ask the other regulars to finally ignore
this obvious, insistent troll, just like last time. Please?

Long since done here :)
 
D

Default User

What. The. ****. Nobody in their right mind defines macros for stuff like
this. If you can't type out 'for', you'll never make it as a programmer.


This clown is a troll that masquerades as a newbie asking questions.
Just plop it in the old killfile and move on. I did that quite some time
back.




Brian Rodenborn
 
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>
#include <errno.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 read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 for end]>\n");
errno = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(errno == ERANGE)
puts( "Out of range for int." );
if( !feof(stdin) && (c=fgetc(stdin))!='\n' )
{ungetc(c, stdin);
scanf("%80[^\n]", a);
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
}
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = [' \t\n']
* Return -1 if it meet eof of fp
* Return 1 on error in the preserve the stream
* otherwise return 0
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
R -1;
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? -1:
ungetc(c, fp)==EOF ? 1: 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* {'+'} or {'-'} ['0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big ;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE if a range error
*
* 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, cp, sign = +1, u;
unsigned n;

assert(fp != NULL);
if( feof(fp) ) R INT_MAX;

if((c = fgetc(fp))=='+') u = '+';
else if(c=='-') {u = '-'; sign = -1;}
else if(!is_digit(c))
{
if( c!=EOF && ungetc(c, fp)==EOF )
R INT_MIN;
R INT_MAX;
}
if(!is_digit(c) && (c = fgetc(fp), !is_digit(c)) )
{
if(c == EOF) clearerr(fp);
else if( ungetc(c, fp) == EOF )
R INT_MIN; /*## A waste stream ## */
if( ungetc(u, fp) == EOF ) /*## u=='+'||u=='-' ##*/
R INT_MIN; /*## A waste stream ##*/
R INT_MAX;
}
n = 0; /*## here c would be digit ##*/
W(1)
{
if( n >= (INT_MAX - ( c - '0' ))/10.0 )
{ n = INT_MAX; errno = ERANGE; 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 read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* [' \t\n'] {'+'} or {'-'} ['0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE for range errors
*/
int read_int(FILE* fp)
{int c = skip_spaces(fp);
if(c == 1) /* stream problem */
R INT_MIN;
R readint(fp);
}
 
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

And if in the stream there is fp="68768.7979kdkdk" ?


#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')

int read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 or EOF for end]>\n");
errno = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(errno == ERANGE)
puts( "Out of range for int." );
if( !feof(stdin) )
{P("Scan...");
if(scanf("%80[^\n]", a)>0)
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
else P("NO out from scanf\n");
}
else P("Press eof\n");
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = ' ' and '\t' and '\n'
* Return -1 if it meet eof of fp
* Return 1 on error in the preserve the stream
* otherwise return 0
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
R -1;
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? -1:
ungetc(c, fp)==EOF ? 1: 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* {'+'} or {'-'} or {'.'} ['.0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big ;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE if a range error
*
* 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"
* fp=".1231M" -> readint(fp)=0, fp="M"
* fp="-.8989s" -> readint(fp)=0 , fp="s"
* fp="23.1231M" -> readint(fp)=23, fp="M"
* fp="-23.8989s" -> readint(fp)=-23,fp="s"
*/

int readint(FILE* fp)
{int c, cp, sign = +1, u;
unsigned n;

assert(fp != NULL);
if( feof(fp) ) R INT_MAX;

if((c = fgetc(fp))=='+') u = '+';
else if(c=='-') {u = '-'; sign = -1;}
else if(!is_digit(c) && c!='.')
{
if( c!=EOF && ungetc(c, fp)==EOF )
R INT_MIN;
R INT_MAX;
}

if( !is_digit(c) && c!='.' && (c = fgetc(fp), !is_digit(c)) )
{
if(c=='.')
{
if(sign = fgetc(fp), is_digit(sign) )
{ /*## cancell .number ##*/
W( sign = fgetc(fp), is_digit(sign));
if(ungetc(sign, fp) == EOF)
R INT_MIN;
R 0;
}
else if(ungetc(sign, fp)==EOF ||
ungetc('.' , fp)==EOF || ungetc(u, fp)==EOF)
R INT_MIN;
R INT_MAX;
}
if(c == EOF) clearerr(fp);
else if( ungetc(c, fp) == EOF )
R INT_MIN; /*## A waste stream ## */
if( ungetc(u, fp) == EOF ) /*## u=='+'||u=='-' ##*/
R INT_MIN; /*## A waste stream ##*/
R INT_MAX;
}
if(c=='.')
{
if(u = fgetc(fp), is_digit(u) )
{ /*## cancell .number ##*/
W( u = fgetc(fp), is_digit(u));
if(ungetc(u, fp) == EOF)
R INT_MIN;
R 0;
}
else if(ungetc(u, fp)==EOF || ungetc('.', fp)==EOF)
R INT_MIN;
R INT_MAX;
}
n = 0; /*## here c would be digit ##*/
W(1)
{
if( n >= (INT_MAX - ( c - '0' ))/10.0 )
{ n = INT_MAX; errno = ERANGE; break; }
n = 10*n + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(c=='.')
{
if( u = fgetc(fp), !is_digit(u) )
{
if( u!=EOF && ungetc( u, fp)==EOF)
R INT_MIN;
R sign * ((int) n);
}
c = u;
}
if(is_digit(c)) /*## it jumps big numbers or .numbers ##*/
W( c = fgetc(fp), is_digit(c));

if( c!=EOF && ungetc(c, fp)==EOF )
R INT_MIN;
R sign * ((int) n);
}


/* #### int read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* [' \t\n'] {'+'} or {'-'} ['0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE
*/
int read_int(FILE* fp)
{int c = skip_spaces(fp);
if(c == 1) /* stream problem */
R INT_MIN;
R readint(fp);
}
 
R

RoSsIaCrIiLoIA

#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')

int read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 or EOF for end]>\n");
errno = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(errno == ERANGE)
puts( "Out of range for int." );
if( !feof(stdin) )
{P("Scan...");
if(scanf("%80[^\n]", a)>0)
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
else P("NO out from scanf\n");
}
else P("Press eof\n");
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = ' ' and '\t' and '\n'
* Return -1 if it meet eof of fp
* Return 1 on error in the preserve the stream
* otherwise return 0
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
R -1;
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? -1:
ungetc(c, fp)==EOF ? 1: 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* {'+'} or {'-'} or {'.'} ['.0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big ;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE if a range error
*
* 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"
* fp=".1231M" -> readint(fp)=0, fp="M"
* fp="-.8989s" -> readint(fp)=0 , fp="s"
* fp="23.1231M" -> readint(fp)=23, fp="M"
* fp="-23.8989s" -> readint(fp)=-23,fp="s"
*/

int readint(FILE* fp)
{int c, cp, sign = +1, u;
unsigned n;

assert(fp != NULL);
if( feof(fp) ) R INT_MAX;

if((c = fgetc(fp))=='+') u = '+';
else if(c=='-') {u = '-'; sign = -1;}
else if(!is_digit(c) && c!='.')
{
if( c!=EOF && ungetc(c, fp)==EOF )
R INT_MIN;
R INT_MAX;
}

if( !is_digit(c) && c!='.' && (c = fgetc(fp), !is_digit(c)) )
{
if(c == '.')
{
if(sign = fgetc(fp), is_digit(sign) )
{ /*## cancell .number ##*/
W( sign = fgetc(fp), is_digit(sign));
if( sign!=EOF && ungetc(sign, fp)==EOF )
R INT_MIN;
R 0;
}
else {
if(sign == EOF) clearerr(fp);
else if(ungetc(sign, fp)==EOF)
R INT_MIN;
if(ungetc('.' , fp)==EOF || ungetc(u, fp)==EOF)
R INT_MIN;
}
R INT_MAX;
}
if(c == EOF) clearerr(fp);
else if( ungetc(c, fp) == EOF )
R INT_MIN; /*## A waste stream ## */
if( ungetc(u, fp) == EOF ) /*## u=='+'||u=='-' ##*/
R INT_MIN; /*## A waste stream ##*/
R INT_MAX;
}
if(c == '.')
{
if( u = fgetc(fp), is_digit(u) )
{ /*## cancell .number ##*/
W( u = fgetc(fp), is_digit(u));
if(u!=EOF && ungetc(u, fp)==EOF)
R INT_MIN;
R 0;
}
else {
if(u == EOF) clearerr(fp);
else if(ungetc(u, fp) == EOF) R INT_MIN;
if(ungetc('.', fp) == EOF) R INT_MIN;
}
R INT_MAX;
}
n = 0; /*## here c would be digit ##*/
W( 1 )
{
if( n >= (INT_MAX - ( c - '0' ))/10.0 )
{ W( c = fgetc(fp), is_digit(c) );
n = INT_MAX; errno = ERANGE;
break;
}
n = 10*n + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(c == '.')
{
if( u = fgetc(fp), !is_digit(u) )
{
if(u == EOF) clearerr(fp);
else if(ungetc( u, fp) == EOF)
R INT_MIN;
if(ungetc('.', fp) == EOF)
R INT_MIN;
R sign * ((int) n);
}
c = u;
}
if(is_digit(c)) /*## it jumps .numbers ##*/
W( c = fgetc(fp), is_digit(c));

if( c!=EOF && ungetc(c, fp)==EOF )
R INT_MIN;
R sign * ((int) n);
}


/* #### int read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* [' \t\n'] {'+'} or {'-'} ['0123456789']
* range=[ -INT_MAX + 1, INT_MAX - 1 ]
* on error it returns
* INT_MAX (number too big;
* or not good input but it is preserved the stream)
* or -INT_MAX (a negative number too big)
* or INT_MIN (a wasted stream);
* errno = ERANGE
*/
int read_int(FILE* fp)
{int c = skip_spaces(fp);
if(c == 1) /* stream problem */
R INT_MIN;
R readint(fp);
}
 
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

Fear ... don't you :)))
__________
Lato A
Gli americani vanno contro il diritto internazionale
occupando paesi di altri popoli e uccidendo una popolazione
inerme nascosti nei loro carrammati.
__________
Lato B
I terroristi uccidono persone che non c'entrano completamente
i civili qui, sono tutti contro la guerra.
GLi unici che ci guadagnano sono i costruttori di armi ...
 
R

RoSsIaCrIiLoIA

in comp.lang.c:
#define P printf
#define R return
#define W while
#define F for

[snip]

Sorry, I stopped reading right here. I have little tolerance for
deliberate (pick one):

1. stupidity

2. obfuscation

3. trolling

I pick 3, trolling just for fun myself.
 
R

RoSsIaCrIiLoIA

#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')

#define EERR_EOF 8
#define EERR_UNGET 4
#define EERR_RANGE 2
#define EERR_NONUM 1

unsigned errno1=0;

int read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 or EOF for end]>\n");
errno1 = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(errno1 & EERR_RANGE)
puts( "Out of range for int." );
if(errno1 & EERR_EOF)
puts( "Find EOF." );
if(errno1 & EERR_NONUM)
puts( "Nonum" );
if(errno1 & EERR_UNGET)
puts( "Unget" );
if( !feof(stdin) )
{P("Scan...");
if(scanf("%80[^\n]", a)>0)
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
else P("NO out from scanf\n");
}
else P("Press eof\n");
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = ' ' and '\t' and '\n'
* Return EERR_EOF if it meet eof of fp
* Return EERR_UNGET on error in the preserve the stream
* otherwise return 0
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
(errno1 |= EERR_EOF );
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? (errno1 |= EERR_EOF ):
ungetc(c, fp)==EOF ? (errno1 |= EERR_UNGET): 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* ({'+'} || {'-'}) && ({'.'} || {''}) && ['0123456789']
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big ;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (errno1 & EERR_RANGE) !=0 if a range error
* (errno1 & EERR_NONUM) !=0 if number is not gets
* (errno1 & EERR_EOF ) !=0 if EOF is meet
* (errno1 & EERR_UNGET) !=0 if stream error in ungetc
* Examples:
* fp="+a+bbb" -> readint(fp)=INT_MAX, fp="+a+bbb"
* fp="++aabbb" -> readint(fp)=INT_MAX, fp="++aabbb"
* fp="+9999999999999999999999999+9" -> readint(fp)= INT_MAX, fp="+9"
* fp="-9999999999999999999999999+9" -> readint(fp)= INT_MIN, 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"
* fp=".1231M" -> readint(fp)=0, fp="M"
* fp="-.8989s" -> readint(fp)=0 , fp="s"
* fp="23.1231M" -> readint(fp)=23, fp="M"
* fp="-23.8989s" -> readint(fp)=-23,fp="s"
*/


int readint(FILE* fp)
{int c, cp, sign = +1, u;
unsigned n, max;

assert(fp != NULL);
if( feof(fp) )
{errno1 |= (EERR_EOF|EERR_NONUM) ; R INT_MAX;}

if((c = fgetc(fp))=='+') u = '+';
else if(c == '-') {u = '-'; sign = -1;}
else if(!is_digit(c) && c!='.')
{
if(c !=EOF)
{
if( ungetc(c, fp)==EOF )
{ errno1 |= (EERR_UNGET|EERR_NONUM); R INT_MAX;}
}
else errno1 |= EERR_EOF;
errno1 |= EERR_NONUM;
R INT_MAX;
}

if( !is_digit(c) && c!='.' && (c = fgetc(fp), !is_digit(c)) )
{
if(c == '.')
{
if(sign = fgetc(fp), is_digit(sign) )
{ /*## cancell .number ##*/
W( sign = fgetc(fp), is_digit(sign));
if(sign != EOF)
{
if( ungetc(sign, fp)==EOF )
{
errno1 |= EERR_UNGET|EERR_NONUM;;
R INT_MAX;
}
}
else errno1 |= EERR_EOF;
R 0;
}
else {
if(sign == EOF) clearerr(fp);
else if(ungetc(sign, fp)==EOF)
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
if(ungetc('.' , fp)==EOF || ungetc(u, fp)==EOF)
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
if(c == EOF) clearerr(fp);
else if( ungetc(c, fp) == EOF ) /* c=='\n' */
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
} /*## A waste stream ## */
if( ungetc(u, fp) == EOF ) /*## u=='+'||u=='-' ##*/
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
if(c == '.')
{
if( u = fgetc(fp), is_digit(u) )
{ /*## cancell .number ##*/
W( u = fgetc(fp), is_digit(u));
if(u != EOF)
{if(ungetc(u, fp) == EOF)
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
}
else errno1 |= EERR_EOF;
R 0;
}
else {
if(u == EOF) clearerr(fp);
else if(ungetc(u, fp) == EOF ||
ungetc('.', fp) == EOF )
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
n = 0; /*## here c would be digit ##*/
if(sign>0) max = INT_MAX;
else max = - INT_MIN; /*##???##*/

W( 1 )
{
if( n > ( max - ( c - '0' ))/10 )
{ W( c = fgetc(fp), is_digit(c) );
n = max; errno1 |= EERR_RANGE;
break;
}
n = 10*n + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(c == '.')
{
if( u = fgetc(fp), !is_digit(u) )
{
if(u == EOF) clearerr(fp);
else if(ungetc( u, fp) == EOF)
errno1 |= EERR_UNGET;
if(ungetc('.', fp) == EOF)
errno1 |= EERR_UNGET;
R sign * ((int) n);
}
c = u;
}
if(is_digit(c)) /*## it jumps .numbers ##*/
W( c = fgetc(fp), is_digit(c));

if(c != EOF)
{
if(ungetc(c, fp) == EOF)
errno1 |= EERR_UNGET;
}
else errno1 |= EERR_EOF;
R (int) (sign * n);
}


/* #### int read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* [' \t\n']&&({'+'} || {'-'})&&({'.'} || {''})&&['0123456789']
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (errno1 & EERR_RANGE) !=0 if a range error
* (errno1 & EERR_NONUM) !=0 if number is not gets
* (errno1 & EERR_EOF ) !=0 if EOF is meet
* (errno1 & EERR_UNGET) !=0 if stream error in ungetc
*/
int read_int(FILE* fp)
{int c = skip_spaces(fp);
if(c == EERR_UNGET) /* stream problem */
{errno1 |= EERR_NONUM; R INT_MAX;}
R readint(fp);
}
 
R

RoSsIaCrIiLoIA

#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')

#define EERR_EOF 8
#define EERR_UNGET 4
#define EERR_RANGE 2
#define EERR_NONUM 1

unsigned errno1=0;

int read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 or EOF for end]>\n");
errno1 = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(errno1 & EERR_RANGE)
puts( "Out of range for int." );
if(errno1 & EERR_EOF)
puts( "Find EOF." );
if(errno1 & EERR_NONUM)
puts( "Nonum" );
if(errno1 & EERR_UNGET)
puts( "Unget" );
if( !feof(stdin) )
{P("Scan..."); fflush(stdout);
if(scanf("%80[^\n]", a)>0)
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
else P("NO out from scanf\n");
}
else P("Press eof\n");
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = ' ' and '\t' and '\n'
* Return EERR_EOF if it meet eof of fp
* Return EERR_UNGET on error in the preserve the stream
* otherwise return 0
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
(errno1 |= EERR_EOF );
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? (errno1 |= EERR_EOF ):
ungetc(c, fp)==EOF ? (errno1 |= EERR_UNGET): 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* ({'+'}||{'-'}||{''}) && ({'.'}||{''}) && ['0123456789']
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big ;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (errno1 & EERR_RANGE) !=0 if a range error
* (errno1 & EERR_NONUM) !=0 if number is not gets
* (errno1 & EERR_EOF ) !=0 if EOF is meet
* (errno1 & EERR_UNGET) !=0 if stream error in ungetc
* 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"
* fp=".1231M" -> readint(fp)=0, fp="M"
* fp="-.8989s" -> readint(fp)=0 , fp="s"
* fp="23.1231M" -> readint(fp)=23, fp="M"
* fp="-23.8989s" -> readint(fp)=-23,fp="s"
*/


int readint(FILE* fp)
{int c, cp, sign = +1, u;
unsigned n, max;

assert(fp != NULL);
if( feof(fp) )
{errno1 |= (EERR_EOF|EERR_NONUM) ; R INT_MAX;}

if((c = fgetc(fp))=='+') u = '+';
else if(c == '-') {u = '-'; sign = -1;}
else if(!is_digit(c) && c!='.')
{
if(c !=EOF)
{
if( ungetc(c, fp)==EOF )
{ errno1 |= (EERR_UNGET|EERR_NONUM); R INT_MAX;}
}
else errno1 |= EERR_EOF;
errno1 |= EERR_NONUM;
R INT_MAX;
}

if( !is_digit(c) && c!='.' && (c = fgetc(fp), !is_digit(c)) )
{ /* case fp="+else" or fp="-else" */
if(c == '.')
{ /*case fp="+.else" or fp="-.else" */
if(sign = fgetc(fp), is_digit(sign) )
{ /*## cancell .number ##*/
W( sign = fgetc(fp), is_digit(sign));
if(sign != EOF)
{
if( ungetc(sign, fp)==EOF )
{
errno1 |= EERR_UNGET|EERR_NONUM;;
R INT_MAX;
}
}
else errno1 |= EERR_EOF;
R 0;
}
else {
if(sign == EOF) clearerr(fp);
else if(ungetc(sign, fp)==EOF)
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
if(ungetc('.' , fp)==EOF || ungetc(u, fp)==EOF)
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
/* here fp="+no_num" */
if(c == EOF) clearerr(fp);
else if( ungetc(c, fp) == EOF )
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
} /*## A waste stream ## */
if( ungetc(u, fp) == EOF ) /*## u=='+'||u=='-' ##*/
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
if(c == '.')
{ /* case of ".else" */
if( u = fgetc(fp), is_digit(u) )
{ /*## cancell .number ##*/
W( u = fgetc(fp), is_digit(u));
if(u != EOF)
{if(ungetc(u, fp) == EOF)
{
errno1 |= EERR_UNGET;
R 0;
}
}
else errno1 |= EERR_EOF;
R 0;
}
else { /* case ".no_num" */
if(u == EOF) clearerr(fp);
else if(ungetc(u, fp) == EOF ||
ungetc('.', fp) == EOF )
{
errno1 |= EERR_UNGET|EERR_NONUM;
R INT_MAX;
}
}
errno1 |= EERR_NONUM;
R INT_MAX;
}
n = 0; /*## here c would be digit ##*/
if(sign>0) max = INT_MAX;
else max = - INT_MIN; /*##???##*/

W( 1 )
{
if( n > ( max - ( c - '0' ))/10 )
{ W( c = fgetc(fp), is_digit(c) );
n = max; errno1 |= EERR_RANGE;
break;
}
n = 10*n + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(c == '.') /* number.else */
{ /*I'm here ^ */
if( u = fgetc(fp), !is_digit(u) )
{
if(u == EOF) clearerr(fp);
else if(ungetc( u, fp) == EOF)
errno1 |= EERR_UNGET;
if(ungetc('.', fp) == EOF)
errno1 |= EERR_UNGET;
R sign * ((int) n);
}
c = u;
}
if(is_digit(c)) /*## it jumps .numbers ##*/
W( c = fgetc(fp), is_digit(c));

if(c != EOF)
{
if(ungetc(c, fp) == EOF)
errno1 |= EERR_UNGET;
}
else errno1 |= EERR_EOF;
R (int) (sign * n);
}


/* #### int read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* [' \t\n'] && ({'+'}||{'-'}||{''}) && ({'.'} || {''}) &&
['0123456789']
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (errno1 & EERR_RANGE) !=0 if a range error
* (errno1 & EERR_NONUM) !=0 if number is not gets
* (errno1 & EERR_EOF ) !=0 if EOF is meet
* (errno1 & EERR_UNGET) !=0 if stream error in ungetc
*/
int read_int(FILE* fp)
{int c = skip_spaces(fp);
if(c == EERR_UNGET) /* stream problem */
{errno1 |= EERR_NONUM; R INT_MAX;}
R readint(fp);
}
 
R

RoSsIaCrIiLoIA

#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#define P printf
#define R return
#define W while
#define F for
#define is_digit(x) ('0'<=(x) && (x)<='9')

#define IERR_EOF 8u
#define IERR_UNGET 4u
#define IERR_RANGE 2u
#define IERR_NONUM 1u

unsigned ierrno = 0;

int read_int(FILE* fp);


int main( void )
{
int i, c;
char a[81]={0};

do {
P("Enter an int[1919 or EOF for end]>\n");
ierrno = 0;
i = read_int( stdin );
P( "%d==NUMBER\n", i );
if(ierrno & IERR_RANGE)
puts( "Out of range for int." );
if(ierrno & IERR_EOF)
puts( "Find EOF." );
if(ierrno & IERR_NONUM)
puts( "Nonum" );
if(ierrno & IERR_UNGET)
puts( "Unget" );
if( !feof(stdin) )
{P("Scan..."); fflush(stdout);
if(scanf("%80[^\n]", a)>0)
/*## in stdin there is '\n' ##*/
P("\"%s\"\n", a);
else P("NO out from scanf\n");
}
else P("Press eof\n");
}while(i!=1919 && !feof(stdin));
R 0;
}


/* #### int skip_spaces(FILE* fp) ####
* skip the spaces = ' ' and '\t' and '\n'
* Return EERR_EOF if it meets the eof of fp
* Return EERR_UNGET on error in the preserve the stream
* otherwise return 0.
* (ierrno & IERR_EOF ) !=0 if EOF is meet
* (ierrno & IERR_UNGET) !=0 if stream error (no ungetc)
*/
int skip_spaces(FILE* fp)
{int c;
if( feof(fp) )
R ( ierrno |= IERR_EOF );
W( (c = fgetc(fp))==' ' || c=='\t' || c=='\n') ;
R (c == EOF ? (ierrno |= IERR_EOF ):
ungetc(c, fp)==EOF ? (ierrno |= IERR_UNGET): 0
);
}


/* #### int readint(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* ({+}||{-}||{}) && ({.}||{}) && [0123456789] &&
* ( ({.}&&[0123456789])||{} )
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big ;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (ierrno & IERR_RANGE) !=0 if a range error
* (ierrno & IERR_NONUM) !=0 if number is not gets
* (ierrno & IERR_EOF ) !=0 if EOF is meet
* (ierrno & IERR_UNGET) !=0 if stream error in ungetc
* Examples:
* fp="+a+bbb" -> readint(fp)=INT_MAX, fp="+a+bbb"
* fp="++aabbb" -> readint(fp)=INT_MAX, fp="++aabbb"
* fp="+999999999999999999999+9" -> readint(fp)= INT_MAX, fp="+9"
* fp="-999999999999999999999+9" -> readint(fp)= INT_MIN, 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"
* fp=".1231M" -> readint(fp)=0, fp="M"
* fp="-.8989s" -> readint(fp)=0 , fp="s"
* fp="23.1231M" -> readint(fp)=23, fp="M"
* fp="-23.8989s" -> readint(fp)=-23,fp="s"
*/


int readint(FILE* fp)
{int c, sign = +1;
unsigned n, u = 'a';

assert(fp != NULL);
if( feof(fp) )
{ierrno |= (IERR_EOF|IERR_NONUM) ; R INT_MAX;}

if((c = fgetc(fp))=='+') u = '+';
else if(c == '-') {u = '-'; sign = -1;}
else if(c == '.')
{
thePoint: /*### case of ".else" ###*/
if( sign = fgetc(fp), is_digit(sign) )
{ /*## case .number return 0 ##*/
W( sign = fgetc(fp), is_digit(sign));
if(sign != EOF)
{if(ungetc(sign, fp) == EOF)
{ ierrno |= IERR_UNGET; R 0; }
}
else ierrno |= IERR_EOF;
R 0;
}
else { /*## case ".no_num" exit ##*/
if(sign == EOF) clearerr(fp);
else if(ungetc( sign, fp) == EOF)
goto label1;
if( ungetc('.', fp) == EOF )
{ /*## A waste stream ##*/
label1:
ierrno |= IERR_UNGET|IERR_NONUM;
R INT_MAX;
}
if( u!='a' && ungetc(u, fp)==EOF )
goto label1;
ierrno |= IERR_NONUM;
R INT_MAX;
}
}
else if(!is_digit(c) )
{ /* "no_num" --> exit */
if(c !=EOF)
{ if( ungetc(c, fp)==EOF ) goto label1; }
else ierrno |= IERR_EOF;
ierrno |= IERR_NONUM;
R INT_MAX;
}

if( !is_digit(c) && (c = fgetc(fp), !is_digit(c)) )
{ /*## case fp="+else" or fp="-else" ##*/
if(c == '.')
goto thePoint;
/*## fp="+no_num"||"-no_num" ##*/
if(c == EOF) clearerr( fp );
else if( ungetc(c, fp) == EOF )
goto label1;
if( ungetc(u, fp) == EOF ) /*## u=='+' || u=='-'##*/
goto label1;
ierrno |= IERR_NONUM;
R INT_MAX;
}

n = 0; /*## here c would be digit ##*/
if(sign>0) u = INT_MAX;
else u = - INT_MIN; /*##???##*/

W( 1 )
{
if( n > ( u - ( c - '0' ))/10 )
{ W( c = fgetc(fp), is_digit(c) );
n = u; ierrno |= IERR_RANGE;
break;
}
n = 10*n + (c - '0');
if(c = fgetc(fp), !is_digit(c))
break;
}
if(c == '.') /*# number.else#*/
{ /*#I'm here ^ #*/
if( c = fgetc(fp), !is_digit(c) )
{
if(c == EOF) clearerr(fp);
else if(ungetc( c, fp) == EOF)
ierrno |= IERR_UNGET;
if(ungetc('.', fp) == EOF)
ierrno |= IERR_UNGET;
R (int) (sign * n);
}
}
if(is_digit(c)) /*## it jumps .numbers ##*/
W( c = fgetc(fp), is_digit(c));

if(c != EOF)
{
if(ungetc(c, fp) == EOF)
ierrno |= IERR_UNGET;
}
else ierrno |= IERR_EOF;
R (int) (sign * n);
}


/* #### int read_int(FILE* fp) #####
* It gets an integer from fp; it is allowed this input
* ([' \t\n']||{}) && ({+}||{-}||{}) && ({.}||{}) && [0123456789] &&
* ( ({.}&&[0123456789])||{} )
* range=[ INT_MIN, INT_MAX ]
* on error it returns
* INT_MAX (number too big;
* or not good input)
* or INT_MIN (a negative number too big)
*
* (ierrno & IERR_RANGE) !=0 if a range error
* (ierrno & IERR_NONUM) !=0 if number is not gets
* (ierrno & IERR_EOF ) !=0 if EOF is meet
* (ierrno & IERR_UNGET) !=0 if stream error in ungetc
*/
int read_int(FILE* fp)
{
skip_spaces(fp);
if(ierrno & IERR_UNGET) /* stream problem */
{ierrno |= IERR_NONUM; R INT_MAX;}
R readint(fp);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top