Marlene Stebbins wrote:
CBFalconer wrote:
Marlene Stebbins wrote:
... snip ...
I hate to come this far and then fail in the very last phase of the
project. I'm wondering if there might be an experienced C programmer
out there who would be willing to take a look at the code (its on my
web site). I know it's asking a lot and I have nothing to offer in
return except my gratitude.
Which URL is conspicuously missing from your post.
Here 'tis:
http://members.shaw.ca/bystander/bignum.html
Um, it would have been nicer to get either links to the four
source files or a .zip archive containing all of them.
Apart from that: On which inputs does your routine fail?
I just looked over your code and found some problems but I
will not go through it without knowing the right inputs:
Your low-level functions are visible everywhere; writing, say
"static void abs_add (....)" effectively prevents users from
using routines which are only yours.
bignum.h:
You need not restrict yourself to ASCII or whatever, instead
of ZERO you can always write '0', instead of NINE you always
can write '9'. If you like your defines better, then at least
#define ZERO '0' and #define NINE '9'.
Your sign control can cause problems down the road, I would
rather use
enum {NEG=-1,POS=1};
or
enum {NEG=-1,NONE,POS};
This will also simplify sign calculation for your bigints
to a.sign*b.sign
bignum.c:
bigAlloc(): You can also use realloc()
int2big(): You multiply n with -1 without checking whether
n<-INT_MAX; for 2s complement machines, INT_MIN= -INT_MAX-1,
so you will run into undefined behaviour.
BTW: If you just malloc() a large enough string, you can
sprintf() n there and just call your ordinary str2big() (or
however it is called). After return, you free() the string
buffer.
big2int(): You do not check whether the return value of strtol()
makes sense but just cast it which can invoke UB.
I'd rather do the conversion by hand (checking against
INT_MAX (or INT_MAX/10)) or use strtof() and check against
INT_MAX.
bigCmp(): I would first evaluate the signs. As far as I have
understood, .size contains strlen(.num), so you do not need
the strlen() round here.
The test could also be (for sign in NEG, NONE, POS)
switch (a.sign*b.sign) {
case NEG:
return a.sign;
case NONE:
if (a.sign) return a.sign;
else return -b.sign;
case POS:
if (a.size > b.size) return a.sign;
else if (b.size > a.size) return -b.sign;
else return strcmp(a.number , b.number);
default:
assert(0);
return 0;
}
Note the default. You have no "default" in your tests.
mul_sign(), div_sign(): with (NEG,NONE,POS), this becomes
return dvd.sign*div.si gn;
or the equivalent for multiplication.
slice(): Are you sure about the first test?
You fail to check lo<=hi.
ascii2str(): You are just duplicating the string; the name
is misleading.
Further down: The
zero:;
label needs no semicolon as it is no statement.
I would mark the label by writing it at the same indentation
level as the surrounding block or at the very beginning of
the line:
zero:
pprod.sign....
After that I stopped.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.