A puzzle

R

RoSsIaCrIiLoIA

write the function
int readINT(FILE* fp);
that read an int from fp and return it.
given the following conditions
a. Do not use arrays
b. Do not use any comparison function like if/then
or switch-case
c. you can use pointers only
d. you cannot use any of the loops either.
e. you cannot use in it any library function
except fgetc() and ungetch().
 
C

Chris McDonald

RoSsIaCrIiLoIA said:
write the function
int readINT(FILE* fp);
that read an int from fp and return it.
given the following conditions
a. Do not use arrays
b. Do not use any comparison function like if/then
or switch-case
c. you can use pointers only
d. you cannot use any of the loops either.
e. you cannot use in it any library function
except fgetc() and ungetch().


More homework?

_______________________________________________________________________________
Dr Chris McDonald EMAIL: (e-mail address removed)
School of Computer Science & Software Engineering
The University of Western Australia WWW: http://www.csse.uwa.edu.au/~chris
Crawley, Western Australia, 6009 PH: +61 8 6488 2533, FAX: +61 8 6488 1089
 
R

RoSsIaCrIiLoIA

write the function
int readINT(FILE* fp);
that read an int from fp and return it.
given the following conditions
a. Do not use arrays
b. Do not use any comparison function like if/then
or switch-case
c. you can use pointers only
d. you cannot use any of the loops either.
e. you cannot use in it any library function
except fgetc() and ungetch().

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

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R ((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
(sign = -1, readINT(fp)):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 > r ?
( (r = 10*r + (c-'0')), led = 1, readINT(fp) ):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 <= r ?
((max = 1), (r = INT_MAX), readINT(fp)):
c==EOF ?
( (c = sign*r), (max = led = r = 0), (sign = +1), c):
( ungetc(c, fp), (c = sign*r), (max = led = r = 0), (sign = +1), c);
}


int main(void)
{int x;
P("A int>"); fflush(stdout);
x = readINT(stdin);
printf("x=%d\n", x);
R 0;
}
 
R

RoSsIaCrIiLoIA

R ((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
(sign = -1, readINT(fp)):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 > r ?
( (r = 10*r + (c-'0')), led = 1, readINT(fp) ):
^^^^^^^^^
Is it better (led = 1) here?
 
R

RoSsIaCrIiLoIA

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

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R ((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
(sign = -1, (led = 1), readINT(fp)):
c=='+' && !led ?
((led = 1), readINT(fp)):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 > r ?
( (r = 10*r + (c-'0')), (led = 1), readINT(fp) ):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 <= r ?
((max = 1), (r = INT_MAX), readINT(fp)):
c==EOF ?
( (c = sign*r), (max = led = r = 0), (sign = +1), c):
(ungetc(c, fp), (c = sign*r), (max = led = r = 0), (sign = +1), c);
}



int main(void)
{int x;
P("A int>"); fflush(stdout);
x = readINT(stdin);
printf("x=%d\n", x);
R 0;
}
 
R

RoSsIaCrIiLoIA

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

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R ((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
(sign = -1, (led = 1), readINT(fp)):
c=='+' && !led ?
((led = 1), readINT(fp)):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 > r ?
( (r = 10*r + (c-'0')), (led = 1), readINT(fp) ):
'0'<=c && c<='9' && (INT_MAX - (c - '0'))/10 <= r ?
((max = 1), (r = INT_MAX), readINT(fp)):
c==EOF ?
( (c = sign*r), (max = led = r = 0), (sign = +1), c):
(ungetc(c, fp), (c = sign*r), (max = led = r = 0), (sign = +1), c);
}



int main(void)
{int x, y;
P("Two ints>"); fflush(stdout);
x = readINT(stdin);
y = readINT(stdin);
printf("x=%d y=%d\n", x, y);
R 0;
}
 
R

RoSsIaCrIiLoIA

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

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R ((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
(sign = -1, (led = 1), readINT(fp)):
c=='+' && !led ?
((led = 1), readINT(fp)):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0')) > r*10 ?
( (r = 10*r + (c-'0')), (led = 1), readINT(fp) ):
'0'<=c && c<='9' && (INT_MAX - (c - '0')) <= r*10 ?
((max = 1), (r = INT_MAX), readINT(fp)):
c==EOF ?
( (c = sign*r), (max = led = r = 0), (sign = +1), c):
(ungetc(c, fp), (c = sign*r), (max = led = r = 0), (sign = +1), c);
}



int main(void)
{int x, y;
P("Two int>"); fflush(stdout);
x = readINT(stdin);
y = readINT(stdin);
P("x=%d y=%d\n", x, y);
R 0;
}
 
R

RoSsIaCrIiLoIA

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

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R feof(fp) && led==0 ?
INT_MAX :
((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
( sign = -1, led = 1, readINT(fp) ):
c=='+' && !led ?
( led = 1, readINT(fp) ):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0')) > r*10 ?
( r = 10*r + (c-'0'), led = 2, readINT(fp) ):
'0'<=c && c<='9' && (INT_MAX - (c - '0')) <= r*10 ?
( max = 1, r = INT_MAX, readINT(fp)):
led!=2 && c!=EOF ? (ungetc(c, fp) , INT_MAX) :
led!=2 && c==EOF ? INT_MAX :
c==EOF ?
( c = sign*r, (max = led = r = 0), sign = +1, c):
(ungetc(c, fp),
c = sign*r, (max = led = r = 0), sign = +1, c);
}



int main(void)
{int x, y;
P("Two ints>"); fflush(stdout);
x = readINT(stdin);
y = readINT(stdin);
P("x=%d y=%d\n", x, y);
R 0;
}
 
A

Allan Bruce

RoSsIaCrIiLoIA said:
#include <stdio.h>
#include <assert.h>
#include <limits.h>

#define P printf
#define R return

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0;
int c;

assert(fp!=0);
R feof(fp) && led==0 ?
INT_MAX :
((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
( sign = -1, led = 1, readINT(fp) ):
c=='+' && !led ?
( led = 1, readINT(fp) ):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0')) > r*10 ?
( r = 10*r + (c-'0'), led = 2, readINT(fp) ):
'0'<=c && c<='9' && (INT_MAX - (c - '0')) <= r*10 ?
( max = 1, r = INT_MAX, readINT(fp)):
led!=2 && c!=EOF ? (ungetc(c, fp) , INT_MAX) :
led!=2 && c==EOF ? INT_MAX :
c==EOF ?
( c = sign*r, (max = led = r = 0), sign = +1, c):
(ungetc(c, fp),
c = sign*r, (max = led = r = 0), sign = +1, c);
}



int main(void)
{int x, y;
P("Two ints>"); fflush(stdout);
x = readINT(stdin);
y = readINT(stdin);
P("x=%d y=%d\n", x, y);
R 0;
}

why do you keep posting code to this? do you expect help?
 
R

RoSsIaCrIiLoIA

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

#define P printf
#define R return


/* it takes an int from fp; allow this input
[' \t'] one_of_['+'/'-'] ['0123456789']
on error it returns INT_MAX (number too long or not good input)
or -INT_MAX (a negative number too long) */

int readINT(FILE* fp)
{static int sign = +1, r = 0, led = 0, max = 0, u = 0;
int c;

assert(fp!=0);
R feof(fp) && led==0 ?
INT_MAX :
((c = fgetc(fp))==' ' || c=='\t') && !led ?
readINT(fp) :
c=='-' && !led ?
( u = c, sign = -1, led = 1, readINT(fp) ):
c=='+' && !led ?
( u = c, led = 1, readINT(fp) ):
!max && '0'<=c && c<='9' && (INT_MAX - (c - '0'))/10.0 > r ?
( r = 10*r + (c-'0'), led = 2, readINT(fp) ):
'0'<=c && c<='9' && (INT_MAX - (c - '0'))/10.0 <= r ?
( max = 1, r = INT_MAX, readINT(fp)):
led==1 && c!=EOF ?
(ungetc(c, fp) , ungetc(u, fp), (led = u = 0), sign = +1, INT_MAX) :
led==1 && c==EOF ?
(clearerr(fp) , ungetc(u, fp), (led = u = 0), sign = +1, INT_MAX) :
led==0 && c!=EOF ? (ungetc(c, fp), INT_MAX) :
led==0 && c==EOF ? INT_MAX :
c==EOF ?
( c = sign*r, (u = max = led = r = 0), sign = +1, c):
(ungetc(c, fp),
c = sign*r, (u = max = led = r = 0), sign = +1, c);
}



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;
}
 
T

Thomas Stegen

RoSsIaCrIiLoIA wrote:
[snip]

Your code really, really sucks. And it is just getting worse.

Please try harder.
 
C

Case

Thomas said:
RoSsIaCrIiLoIA wrote:
[snip]

Your code really, really sucks. And it is just getting worse.

Maybe something was missing from the (homework) assignment:

f. you cannot use assignments

That might help :)

Kees


But to be honest, rules a - e don't make this a fun programming
assignment. So, wishing RoSslaCrliLolA all the best!
 
C

Chris McDonald

Thomas said:
RoSsIaCrIiLoIA wrote:
[snip]

Your code really, really sucks. And it is just getting worse.


I'm glad that someone else noticed this, too.
I thought that my terminal's stty values were incorrect.

_______________________________________________________________________________
Dr Chris McDonald EMAIL: (e-mail address removed)
School of Computer Science & Software Engineering
The University of Western Australia WWW: http://www.csse.uwa.edu.au/~chris
Crawley, Western Australia, 6009 PH: +61 8 6488 2533, FAX: +61 8 6488 1089
 
M

Mark McIntyre

"RoSsIaCrIiLoIA" <[email protected]> wrote:
why do you keep posting code to this? do you expect help?

yes I would know consequences of two ungetc [ungetc(c, fp); ungetc(u,
fp);] in an unbuffered system. [feof(fp) will be zero?]

Then say so, you idiot, instead of posting 40 lines of mindlessly
obfuscated code.
I would like to see what are the solutions of others too

Terrific. The best way to achieve that is NOT to annoy the heck out of
people by posting reams of drivel.
 
S

Sam Dennis

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.
[unquotable code]

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.
 
I

Ivan Vecerina

RoSsIaCrIiLoIA said:
int readINT(FILE* fp);
that read an int from fp and return it.
given the following conditions
a. Do not use arrays
b. Do not use any comparison function like if/then
or switch-case
c. you can use pointers only
d. you cannot use any of the loops either.
e. you cannot use in it any library function
except fgetc() and ungetch().

What about the following approach? (not tested)


int readIntNext(int prev, FILE* fp)
{
int c = fgetc(fp);
return (c<'0'||c>'9')
? ( ungetch(), prev )
: readIntNext(10*prev+(c-'0'));
}

int readINT(FILE* fp)
{
int c = fgetc(fp);
c = (c=='-') ? -1 : ((c=='+'||ungetch(c)),+1);
return c * readIntNext(0,fp);
}


Regards,
Ivan
 
R

RoSsIaCrIiLoIA

#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)
[...]
Thanks. I have to think on it. It is not true that I understand other
code view, for example here I had to rewrite it in my code-mode.
 

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

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top