Objects First |
Following the step-by-step approach:
|
In this case,
the obvious one is
It's not too long and is the same term used in the specification. |
Other possibilities are:
|
Click here to load
the software specification.
I suggest that you re-size the windows to make two long ones
side-by-side so that you can scroll through the code in one and
these notes in the other.
Add a destructor which frees the memory allocated by a constructor.
If it matches precisely ..
In order to make the class as flexible as possible, we've allowed
the user to specify the number of bins at construction time.
So, rather than have a fixed array for the bins,
eg
struct histogram {
...
int bins[MAX_BINS];
}
we just have a pointer to a block of memory
which we're going to allocate
when we find out how many bins this particular object needs.
ConsHistogram
|
There are 2 malloc calls:
* the first allocates space for the dictionary structure, * the other allocate sufficient space for bin_count integers. |
![]() |
DeleteHistogram
Not unsurprisingly, DeleteHistogram has 2 free calls - one to free each block of space malloc'd in the constructor.
ClearHistogram
The pre-condition for this method (and all subsequent ones), states that h must be a valid histogram. The test, h != NULL, is a necessary condition, but certainly not a sufficient one. Here, we have attempted to "tighten up" the test a little bit more by checking that both h and h->bins are not NULL.
In the loop which resets all the bin counts to zero,
we've used the array index form for addressing the elements
of the bins array.
We could equally well have written:
int *ip;
...
ip = h->bins;
for(i=0;i<h->bin_count;i++) *ip++ = 0;
Since this style of array addressing is commonly used by C
programmers, you must be able to recognise it - even if
you never use it yourself!
Aside: There is an ANSI library function:
#include <string.h>
void *memset( void *s, int c, size_t n );
which sets the n bytes of memory from address,
s,
to the value in c, which can also be used efficiently here.
In this case, we would write:
memset( h->bins, 0, h->bin_count*sizeof(int) );
Calling memset
would generally be the most efficient way to
clear memory: it can make use of any special instructions which the
target machine may have and, being part of the ANSI standard
library, should have an efficient implementation on every machine.
AddDatum
We have used the floor function (found in <math.h>) to truncate the result of multiplying x by the reduction factor which converts x to a bin index.
Note the position of the assert after the calculation of the bin index. assert's - just like any function call - can go anywhere in the body of a C function. This one is actually checking the pre-condition that x must be in range - it turns out to be more convenient here to simply check the bin index after it's been calculated than, for example, to calculate the limits of the range of x and check against them.
SampleMedian, SampleMean and MaxFrequency
For SampleMedian, we have chosen to calculate the median from the data gathered already, whereas for SampleMean and MaxFrequency we have updated some variables stored in the object every time AddDatum was called.
This illustrates a number of points in our OO design strategy:
|
Continue on to Verifying the Class Back to the Table of Contents |