dice generator problems

  • Thread starter Bill Cunningham
  • Start date
B

Bill Cunningham

I had one error in this code until I tried to use error checking with
strtol. Now I've really goofed it. This is the compilation I used.

gcc -g di.c -o a -ansi -pedantic -Wall

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
if (argc > 4 || argc == 0) {
fputs("Dice generator usage error\n", stderr);
exit(EXIT_FAILURE);
}
int x, y;
if (argv[1][0] == '-' && argv[1][1] == 'a') {
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {
fputs("strtol error\n", stderr);
return 1;
}
if ((y = strtol(argv[2], NULL, 10)) == LONG_MIN || LONG_MAX) {
fputs("strtol error\n", stderr);
return 1;
}
printf("%i\n", x + y);
exit(1);
}
srand(time(NULL));
printf("%i\n", rand(void) %argv[1]);
return 0;
}

di.c: In function `main':
di.c:11: warning: ISO C90 forbids mixed declarations and code
di.c:13: error: `LONG_MIN' undeclared (first use in this function)
di.c:13: error: (Each undeclared identifier is reported only once
di.c:13: error: for each function it appears in.)
di.c:13: error: `LONG_MAX' undeclared (first use in this function)
di.c:25: error: syntax error before "void"

Are those return values for strtol right? That must be my biggest
problem. I checked the man page for strtol.

Bill
 
B

Bill Cunningham

Bill Cunningham said:
I had one error in this code until I tried to use error checking with
strtol. Now I've really goofed it. This is the compilation I used.

gcc -g di.c -o a -ansi -pedantic -Wall

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
if (argc > 4 || argc == 0) {
fputs("Dice generator usage error\n", stderr);
exit(EXIT_FAILURE);
}
int x, y;
if (argv[1][0] == '-' && argv[1][1] == 'a') {
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {
fputs("strtol error\n", stderr);
return 1;
}
if ((y = strtol(argv[2], NULL, 10)) == LONG_MIN || LONG_MAX) {
fputs("strtol error\n", stderr);
return 1;
}
printf("%i\n", x + y);
exit(1);
}
srand(time(NULL));
printf("%i\n", rand(void) %argv[1]);
return 0;
}

di.c: In function `main':
di.c:11: warning: ISO C90 forbids mixed declarations and code
di.c:13: error: `LONG_MIN' undeclared (first use in this function)
di.c:13: error: (Each undeclared identifier is reported only once
di.c:13: error: for each function it appears in.)
di.c:13: error: `LONG_MAX' undeclared (first use in this function)
di.c:25: error: syntax error before "void"

Are those return values for strtol right? That must be my biggest
problem. I checked the man page for strtol.
Wait a minute I didn't balance those parenthesis. Well I think this code
has alot more wrong with it than that.

Bill
 
S

Seebs

if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

Uh.

x == 1 || 2

is not a test for whether x is equal to either 1 or 2.
di.c:13: error: `LONG_MIN' undeclared (first use in this function)

Maybe LONG_MIN is declared in a specific header?

-s
 
S

Seebs

Seebs said:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {
Uh.
x == 1 || 2
is not a test for whether x is equal to either 1 or 2.
I don't quite understand here what you are trying to say.

I'm saying something really, really, simple. In English.

You have written:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

Let's simplify this a bit:
x = strtol(argv[1], NULL, 10);
if (x == LONG_MIN || LONG_MAX) { ...

Now, there are two possibilities.

One is that you think this will tell you whether x is either of LONG_MIN
or LONG_MAX.

The other is that you want to test whether x is 1.

The thing is: You have written something that might be read out loud
as "if x is equal to long_min or long_max". And that suggests, given
your general history, that you have somehow decided that this is a
good way to test whether x has either of these two values.

However, in C, the expression "LONG_MIN || LONG_MAX" turns out to have
the value 1, because at least one of them has a non-zero value. So what
you've actually done is "if x is equal to the boolean value of the
expression long_min or long_max, which is one". So it's equivalent to
"if (x == 1)".

#include <stdlib.h>
int main(void) {
int x = LONG_MIN;
}

gcc says:
t.c: In function "main":
t.c:3: error: "LONG_MIN" undeclared (first use in this function)
t.c:3: error: (Each undeclared identifier is reported only once
t.c:3: error: for each function it appears in.)

So I guess no, it must be some other header. Man, sure is a shame it's
impossible to open the documentation and look, or we'd have this one nailed.

-s
 
B

Bill Cunningham

Seebs said:
Seebs said:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {
Uh.
x == 1 || 2
is not a test for whether x is equal to either 1 or 2.
I don't quite understand here what you are trying to say.

I'm saying something really, really, simple. In English.

You have written:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

Let's simplify this a bit:
x = strtol(argv[1], NULL, 10);
if (x == LONG_MIN || LONG_MAX) { ...

Now, there are two possibilities.

One is that you think this will tell you whether x is either of LONG_MIN
or LONG_MAX.

The other is that you want to test whether x is 1.

The thing is: You have written something that might be read out loud
as "if x is equal to long_min or long_max". And that suggests, given
your general history, that you have somehow decided that this is a
good way to test whether x has either of these two values.

However, in C, the expression "LONG_MIN || LONG_MAX" turns out to have
the value 1, because at least one of them has a non-zero value. So what
you've actually done is "if x is equal to the boolean value of the
expression long_min or long_max, which is one". So it's equivalent to
"if (x == 1)".

OK. It's been awhile since I tried error checking What I want if if
(x=y) I need the comparison equals and not the assignment operator.
#include <stdlib.h>
int main(void) {
int x = LONG_MIN;
}

gcc says:
t.c: In function "main":
t.c:3: error: "LONG_MIN" undeclared (first use in this function)
t.c:3: error: (Each undeclared identifier is reported only once
t.c:3: error: for each function it appears in.)

So I guess no, it must be some other header. Man, sure is a shame it's
impossible to open the documentation and look, or we'd have this one
nailed.

I got that from man 3 strtol. It said that strtol was defined in
stdlib.h. It didn't say that LONG_MAX and LONG_MIN were declared else where
but as you have pointed out the compiler says they are somewhere else.

Bill
 
B

Bill Cunningham

Keith Thompson said:
Bill Cunningham said:
Seebs said:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

Uh.

x == 1 || 2

is not a test for whether x is equal to either 1 or 2.

I don't quite understand here what you are trying to say.

Read it again until you do.

I should have used = instead of ==
Don't guess.

man 3 strtol said strtol was declared in stdlib.h. But the compiler says
otherwise.

Bill
 
B

Ben Bacarisse

Bill Cunningham said:
I had one error in this code until I tried to use error checking with
strtol. Now I've really goofed it. This is the compilation I used.

gcc -g di.c -o a -ansi -pedantic -Wall

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
if (argc > 4 || argc == 0) {
fputs("Dice generator usage error\n", stderr);
exit(EXIT_FAILURE);
}
int x, y;

Why int when you set the using strtol? Surely you mean long here, no?
if (argv[1][0] == '-' && argv[1][1] == 'a') {
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

This is wrong but it not (currently) a problem because errors prevent
compilation. You want x == LONG MAX at the end, not just LONG_MAX.
LONG_MAX on its own will be taken as true so the whole || will always
be true.
fputs("strtol error\n", stderr);
return 1;
}
if ((y = strtol(argv[2], NULL, 10)) == LONG_MIN || LONG_MAX) {
fputs("strtol error\n", stderr);
return 1;
}
printf("%i\n", x + y);
exit(1);
}
srand(time(NULL));
printf("%i\n", rand(void) %argv[1]);

One error message is telling you that rand(void) is wrong. That is
not ho you call a function that takes no arguments. Once you fix
that, there will be a complaint about % argv[1] as well. argv[1] is
of type char * but % requires integer operands.
return 0;
}

di.c: In function `main':
di.c:11: warning: ISO C90 forbids mixed declarations and code
di.c:13: error: `LONG_MIN' undeclared (first use in this function)
di.c:13: error: (Each undeclared identifier is reported only once
di.c:13: error: for each function it appears in.)
di.c:13: error: `LONG_MAX' undeclared (first use in this function)
di.c:25: error: syntax error before "void"

Are those return values for strtol right? That must be my biggest
problem. I checked the man page for strtol.

There are problems with the return values you use (not least trying to
put a long int into and int) but the basic problem is exactly what the
error messages say: you are using names that are not declared.
LONG_MIN and LONG_MAX are defined in limits.h.
 
K

Keith Thompson

Seebs said:
Let's simplify this a bit:
x = strtol(argv[1], NULL, 10);
if (x == LONG_MIN || LONG_MAX) { ... [...]
However, in C, the expression "LONG_MIN || LONG_MAX" turns out to have
the value 1, because at least one of them has a non-zero value. So what
you've actually done is "if x is equal to the boolean value of the
expression long_min or long_max, which is one". So it's equivalent to
"if (x == 1)".
[...]

Not quite. Remember that "==" binds more tightly than "||".
(x == (LONG_MIN || LONG_MAX))
has the meaning you describe, but
(x == LONG_MIN || LONG_MAX)
is equivalent to
((x == LONG_MIN) || LONG_MAX)
which evaluates to 1, regardless of the value of x (assuming, of
course, that LONG_MIN and LONG_MAX are declared by #including the
proper header).

Of course this doesn't change the basic point, which is that
if (x == LONG_MIN || LONG_MAX)
is the wrong way to test whether x is equal either to LONG_MIN or to
LONG_MAX.
 
K

Keith Thompson

The above isn't quite correct, but for reasons that aren't relevant to
what you're trying to do.
OK. It's been awhile since I tried error checking What I want if if
(x=y) I need the comparison equals and not the assignment operator.

You have completely missed the point. You were already using the "=="
comparison operator; there wasn't an assignment operator in the
condition.

If you want to know whether x is either equal to LONG_MIN or equal to
LONG_MAX, you need to write

if (x == LONG_MIN || x == LONG_MAX)

Got it?

[...]
I got that from man 3 strtol. It said that strtol was defined in
stdlib.h. It didn't say that LONG_MAX and LONG_MIN were declared else where
but as you have pointed out the compiler says they are somewhere else.

So find out where they're declared and add a #include directive for
that header. (Yes, I know which header it is. No, I'm not going to
tell you.)

RTFM.
 
K

Keith Thompson

Bill Cunningham said:
Keith Thompson said:
Bill Cunningham said:
if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN || LONG_MAX) {

Uh.

x == 1 || 2

is not a test for whether x is equal to either 1 or 2.

I don't quite understand here what you are trying to say.

Read it again until you do.

I should have used = instead of ==

Wrong. Don't guess.
man 3 strtol said strtol was declared in stdlib.h. But the compiler says
otherwise.

Wrong again. strtol is declared in stdlib.h. We're talking about
where LONG_MIN is declared.

Look. It. Up.
 
P

Peter Nilsson

You have written:
         if ((x = strtol(argv[1], NULL, 10)) == LONG_MIN ||
LONG_MAX) {

Let's simplify this a bit:
        x = strtol(argv[1], NULL, 10);
        if (x == LONG_MIN || LONG_MAX) { ...

The thing is:  You have written something that might be
read out loud as "if x is equal to long_min or long_max".
...
However, in C, the expression "LONG_MIN || LONG_MAX" turns
out to have the value 1

Quite so, but the condition is parsed as...

(x == LONG_MIN) || LONG_MAX

....not...

x == (LONG_MIN || LONG_MAX)
 
B

Bill Cunningham

The manual page for strtol() probably does not mention the header
where LONG_MIN and LONG_MAX are declared.

It sounds like that's not my major problem here I thought strtol was
equal to atoi if the 3rd parameter was passed a base 10 number. Hence 10 in
the 3rd parameter. Maybe I'm wrong. The man page I read said the return
value on failure would be offerflow or underflow hence LONG_MAX and
LONG_MIN.

Bill
 
K

Kenny McCormack

Keith Thompson said:
Of course this doesn't change the basic point, which is that
if (x == LONG_MIN || LONG_MAX)
is the wrong way to test whether x is equal either to LONG_MIN or to
LONG_MAX.

Of course. Everyone knows that the right way is:

if ((x-LONG_MIN)*(x-LONG_MAX) == 0)
 
S

Seebs

OK. It's been awhile since I tried error checking What I want if if
(x=y) I need the comparison equals and not the assignment operator.

You need to slow down, and possibly stop drinking while posting.

None of this has anything to do with the distinction between comparison
and assignment.

I really don't understand why you're still doing this. If you can't
understand the explanation you were just given, there is no *point*.
Do you have alexia or something?
I got that from man 3 strtol. It said that strtol was defined in
stdlib.h.

But that's not the question.
It didn't say that LONG_MAX and LONG_MIN were declared else where
but as you have pointed out the compiler says they are somewhere else.

Right. Which is documented, too, if you would read the standard, or a C
book, or pretty much anything else.

-s
 
S

Seebs

I should have used = instead of ==

No.

And while I can't say whether you are genuinely incapable of reading
simple English, or simply not bothered to try, I give up.

*plonk*

-s
 
B

Bill Cunningham

Gordon Burditt said:
Try reading the manual and find out.


If you're going to use LONG_MIN and LONG_MAX, you need to include
the standard header which declares them. Fix it.

Well from what I make of this
http://www.manpagez.com/man/3/strtol/

That header limits.h declares strtol. My man page on linux said it was
dclared in stdlib.h. The two return values on failure are LONG_MAX and
LONG_MIN.

"The strtol(), strtoll(), strtoimax(), and strtoq() functions return the
result of the conversion, unless the value would underflow or overflow.
If no conversion could be performed, 0 is returned and the global vari-
able errno is set to EINVAL (the last feature is not portable across
all
platforms). If an overflow or underflow occurs, errno is set to ERANGE
and the function return value is clamped according to the following ta-
ble."

Bill
 
K

Keith Thompson

Bill Cunningham said:
It sounds like that's not my major problem here I thought strtol was
equal to atoi if the 3rd parameter was passed a base 10 number. Hence 10 in
the 3rd parameter. Maybe I'm wrong. The man page I read said the return
value on failure would be offerflow or underflow hence LONG_MAX and
LONG_MIN.

Your major problem at the moment is that your code doesn't compile.

Your code will not compile until you add a #include directive for the
header that declares LONG_MIN and LONG_MAX.

Note that your code still won't compile even after you've fixed that
problem, because it has other problems as well. You can try to fix
those later.

But the LONG_MIN and LONG_MAX problem is a very simple one. If you're
not able to fix that given the hints we've already given you, there's
just no point in continuing.

Find out which header declares LONG_MIN and LONG_MAX. (Do not guess.
Look it up.) Add a #include directive for that header. Recompile
your program. You'll still have error messages, but fewer than you
have now; in particular, these error messages:

di.c:13: error: `LONG_MIN' undeclared (first use in this function)
di.c:13: error: (Each undeclared identifier is reported only once
di.c:13: error: for each function it appears in.)
di.c:13: error: `LONG_MAX' undeclared (first use in this function)

will go away.

After you've done that, you can worry about fixing the other errors.

Focus on one thing at a time.
 
S

Seebs

Not quite. Remember that "==" binds more tightly than "||".

D'oh!

I even wrote a test program, which did not test what I thought it did.

This is what comes of spending a bunch of time in languages in which "x || y"
is idiomatic for roughly "x ? x : y".
Of course this doesn't change the basic point, which is that
if (x == LONG_MIN || LONG_MAX)
is the wrong way to test whether x is equal either to LONG_MIN or to
LONG_MAX.

Right.

Interesting trivia point: I have written substantial code in a language
where

if (x == 1 or 2 && y == 3 or 4)

actually checks whether it is the case both that:
1. x has either the value 1 or the value 2
2. y has either the value 3 or the value 4

It's actually pretty handy as syntactic sugar goes.

-s
 

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
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top