osmium said:
Well, you have lets the abstruse crowd lead you up the creek and abandon
you. I have given them all day to come and rescue you and figure that is
long enough to wait. . AFAICT you used to have a working program. Now you
let the user toss a die with a negative number of sides. Also, the number
of sides could be greater than the range of rand. And the number of sides
should be a constant. The last item may have been mentioned, I'm not really
sure.
None of those were a problem in your initial post. 6 *is* a constant. It
*is* positive. It is less than any RAND_MAX that is allowed by the
standard.
The OP established first thing that the program worked fine -- this
thread has been about coding practices from the beginning, not program
correctness. Obviously, someone having a bunch of new, sometimes
conflicting ideas about coding practices heaped on all at once is going
to take a couple of iterations to sort them all out in a reasonable
fashion.
You're right about range checking. There are a number of strategies
that can be adopted. Certainly, an unsigned data type should be used.
Beyond that, you must first answer the question of whether you want to
do bounds checking at compile-time, or run-time. If the number of
sides is not going to be a compile-time constant (which could be
checked by static assertion, e.g. BOOST_STATIC_ASSERT), then of course
the value will have to be bounds-checked against RAND_MAX (and probably
0) at runtime. How errors are handled (exception, return value,
assertion failure, etc.) is an issue with multiple acceptable answers,
depending on context.
All that said, here's a sketch of what I might do to incorporate the
advice received thus far:
#include <iostream>
#include <cstdlib>
typedef unsigned int DieSides;
typedef unsigned int DieRoll;
const DieSides defaultSides(6);
DieRoll roll(DieSides sides = defaultSides) {
static bool rngSeeded(false);
if (!rngSeeded) {
srand(time(NULL)); // Seed the RNG, once only.
rngSeeded = true;
}
return 1 + rand() % sides;
}
int main() {
const unsigned int numRolls(10);
for(int i = 0; i < numRolls; ++i) {
using namespace std;
cout << "Die rolled: " << roll() << "\n";
}
return EXIT_SUCCESS;
}
Note that I didn't do bounds checking against 0 and RAND_MAX in the
above. If I wanted to be as careful as that, I'd probably define
DieSides as a more robust type, convertible from an unsigned int, which
performs bounds checking on construction. That way, an invalid value
can never even exist, and you find out about the error as early as
possible.
Luke