A puzzle

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))

The problem seems not there but
) : (
(i < INT_MIN + VAL( c )) ? (
^^^^^^^^^^^^^^^^^^^^^^^^^
Here (don't know why)
i = INT_MIN,
errno = ERANGE
) : (
i -= VAL( c )
in the borland compiler
E.g.
C:\Documents and Settings\giu\
77
77
-77
Out of range for int.
-2147483648
^Z
0
^Z
This seems better

#include <stdio.h>
#include <limits.h>
#include <errno.h>
#define P printf
#define R return
#define W while
#define F for

/* 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 DIVC00( x, y ) ( (x) / (y) )

#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, j;
int c;

/* IF=&&; ELSE IF=||; */
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)
) ,
/*--------------------------------------------------*/
(j = VAL(c), sign > 0)
? ( (i > INT_MAX - j )
? (i = INT_MAX, errno = ERANGE )
: (i += j)
)
: ( (i < INT_MIN + j )
? (i = INT_MIN, errno = ERANGE)
: (i -= j)
) ,
/*--------------------------------------------------*/
readINT( fp )
)
: ( c!=EOF && ungetc( c, fp ), base = 0, i );
}


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

do {
P("Enter an int[1919 or EOF for end]>\n");
errno = 0;
i = readINT( stdin );
P( "%d==NUMBER\n", i );
if(errno == ERANGE)
puts( "Out of range for int." );
if( !feof(stdin) && ((c = fgetc(stdin))!='\n' && c!=EOF) )
{ ungetc(c, 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");
}
}while(i!=1919 && !feof(stdin));
R 0;
}
 
P

Peter Nilsson

Sam Dennis said:
/* 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))

This isn't guaranteed C99 behaviour. Theoretically, on a C89 machine...

-5 / -2 == 3 && -5 % -2 = 1

....may be true, in which case DIVC99(-5/-2) would return 3.

#include <stdlib.h>

int divc99(int a, int b)
{
div_t d = div(a, b);
return d.quot;
}

int modc99(int a, int b)
{
div_t d = div(a, b);
return d.rem;
}
 
S

Sam Dennis

Peter said:
This isn't guaranteed C99 behaviour. Theoretically, on a C89 machine...

-5 / -2 == 3 && -5 % -2 = 1

Okay, I suspected that I'd missed something, although it didn't affect
the behaviour as I only had positive divisors; I'll try again:

#define DIVC99( x, y ) ((x) / (y) + \
((((x) > 0) != ((y) > 0)) * 2 - 1) \
* ((x) % (y) * (((x) > 0) * 2 - 1) < 0))

It's probably still slightly wrong.
 
S

Sam Dennis

Sam said:
#define DIVC99( x, y ) ((x) / (y) + \
((((x) > 0) != ((y) > 0)) * 2 - 1) \
* ((x) % (y) * (((x) > 0) * 2 - 1) < 0))

Once more, but comprehensible:

#define DIVC99( x, y ) ((x) / (y) \
+ ((x) % (y) * (x) < 0) * ((x) < 0 == (y) > 0 ? 1 : -1))
#define MODC99( x, y ) ((x) % (y) \
+ ((x) % (y) * (x) < 0) * ((x) > 0 == (y) > 0 ? (y) : -(y)))

....I think.
 
R

RoSsIaCrIiLoIA

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

This readIntNext would gets only 2 ints for call
(return address and the result)

FILE *fp=0;
int prev=0;

int readIntNext(void)
{static cont=0, c=0;

c = fgetc(fp);
return (++cont > 100000) ?
(prev=cont=0, INT_MAX):
(c<'0' || c>'9') ?
(c==EOF || ungetc(c, fp), c=prev, prev=cont=0, c ):
(prev = 10*prev + (c-'0'), readIntNext());
}

int readINT(FILE* fpp)
{ int c;

c = (fp=fpp, feof(fp)) ? EOF: fgetc(fp);
return c==EOF ? INT_MAX :
c=='-' ? -1 * readIntNext() :
c=='+' ? +1 * readIntNext() :
'0'<=c && c<='9' ? (prev = c-'0', readIntNext()):
(c==EOF||ungetc(c, fp), INT_MAX) ;
}
 
C

CBFalconer

Thomas said:
RoSsIaCrIiLoIA wrote:
[snip]

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

Please try harder.

S/he/it posts this stuff only to annoy. He has been plonked here
for a year or more.
 
R

RoSsIaCrIiLoIA

This readIntNext would gets only 2 ints for call
(return address and the result)

This take only one int [return address] for call

FILE *fp=0;
int prev=0;

void readIntNext(void)
{static cont=0, c=0;
c = fgetc(fp);

(++cont> 10000000) ? (cont=0, prev=INT_MAX ):
(c<'0'||c>'9') ?
(c==EOF || ungetc(c, fp), cont=0):
(prev = 10*prev + (c-'0'), readIntNext(), 1);
}


int readINT(FILE* fpp)
{ int c;

c = (fp=fpp, feof(fp)) ? EOF: fgetc(fp);
return c==EOF ? INT_MAX :
c=='-' ? (readIntNext(), c=-1*prev, prev=0, c) :
c=='+' ? (readIntNext(), c=+1*prev, prev=0, c) :
'0'<=c && c<='9' ?
(prev = c-'0', readIntNext(), c=prev, prev=0, c):
(c==EOF||ungetc(c, fp), INT_MAX) ;
}
 
S

Sam Dennis

RoSsIaCrIiLoIA said:
[Silly readINT thing]
in the borland compiler

Which Borland compiler?
-77
Out of range for int.
-2147483648

Well, I can't imagine why; not only does it work here, but I even dug
out a Borland compiler (BC++ 5.02) and verified that it worked there,
too.

Actually, I can imagine: a non-conforming implementation.
This seems better

I beg to differ.
#define DIVC00( x, y ) ( (x) / (y) )
Eh?

: ( c!=EOF && ungetc( c, fp ), base = 0, i );

I don't have a copy or draft of the 1990 standard, but ungetc(EOF) is
fine in C99, at least. (It doesn't do anything.)
if(scanf("%80[^\n]", a)>0)
(From a strange method to swallow the rest of a line)

Very funny; how about replacing these 8, or so, lines with this:

scanf( "%*[^\n]" );
scanf( "%*1[\n]" );
 
J

Joona I Palaste

R

RoSsIaCrIiLoIA

RoSsIaCrIiLoIA said:
[Silly readINT thing]
in the borland compiler

Which Borland compiler?
-77
Out of range for int.
-2147483648

Well, I can't imagine why; not only does it work here, but I even dug
out a Borland compiler (BC++ 5.02) and verified that it worked there,
too.
bcc32
it says
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
Try `bcc32 -h' for more information, or `bcc32 -h <OPT>' for specific
help.
Error E2266: No file names given
_________________
Copy your post in a file.c
bcc32 file.c
file
77
77
-77
Out of range for int.
-2147483648
-8989
Out of range for int.
-2147483648
^Z
0
^Z
Actually, I can imagine: a non-conforming implementation.

I beg to differ.


Eh?

It is a try
: ( c!=EOF && ungetc( c, fp ), base = 0, i );

I don't have a copy or draft of the 1990 standard, but ungetc(EOF) is
fine in C99, at least. (It doesn't do anything.)
if(scanf("%80[^\n]", a)>0)
(From a strange method to swallow the rest of a line)

Very funny; how about replacing these 8, or so, lines with this:

scanf( "%*[^\n]" );
scanf( "%*1[\n]" );

dont' know, but I want to see the rest of line
 

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