Pointers are super important when writing low-level programs! GET COMFORTABLE WITH EM!
In this lab, you’ll be writing a generic array-filtering function. This will make use of pointer arithmetic, function pointers, and pointer casting. This is an actually useful function! Filtering values out of an array is a very common operation.
Get the starting file here.
Open it and read the comments.
“Predicate” is a common programming term which means “something that gives a yes-or-no answer.”
filter function’s predicate must be a function which:
- takes a
const void*which points to a value from the array
- returns a
- false to ignore the item, and
- true to put the item in the output array
Writing the predicate functions
less_than_50 function should interpret its parameter as a pointer to a
float, and as the name implies, return
true if it is less than 50.
Since the parameter is a
const void*, you’ll have to cast the parameter to a different pointer type.
Have a look at how I wrote the
compare_ints function in the
qsort.c example to get an idea of how to write this.
Then implement the others:
even_whole_numbershould interpret its parameter as a pointer to a
float, and return
trueif the whole number part of the float is even.
- you can cast a
intto get the whole number part.
- you can cast a
less_than_50_bshould interpret its parameter as a pointer to a
char, and return
trueif the value is less than 50.
Hint: comparison operators give you a
bool. You can write e.g.
return x == 10;. This is valid in C and Java.
Have a look at the first piece of code in
float filtered[NUM_VALUES]; int filtered_len = filter(filtered, float_values, NUM_VALUES, sizeof(float), &less_than_50); printf("there are %d numbers less than 50:\n", filtered_len); for(int i = 0; i < filtered_len; i++) printf("\t%.2f\n", filtered[i]);
Look at the
float_values array and think about what the output should look like. (There are 6 numbers less than 50, right?)
filter function should work like this:
- for each item in the
- call the
predfunction with a pointer to that element
- it’s a function pointer but you just call it like a function
- if it returned “true”:
memcpyto copy that item from the input array to the output array (see below)
- call the
In addition it should:
- keep a count of how many items “passed the test” (predicate returned “true”)
- return that count
memcpy is used to copy blobs of bytes from one place to another. It’s a very common function.
memcpy(dest, src, length);
This will copy
length bytes from the memory pointed to by
src into the memory pointed to by
You’re used to using
 to access values from arrays. But you can’t use
 on a
void*. Instead, an easier technique is to use a “walking pointer.”
Instead of keeping a pointer to the beginning of an arrays, we move the pointer along, item by item, to access the array. Like this.
When you do pointer arithmetic on a
void*, it will add or subtract a number of bytes to its address. So, you can move the pointer(s) along by adding the size of one item to them.
The correct output
Done right, the output should be:
there are 6 floats less than 50: 31.94 36.10 1.00 6.35 20.76 19.60 there are 3 floats that have an even whole part: 36.10 6.35 20.76 there are 6 bytes less than 50: 31 36 1 6 20 19
Some likely mistakes:
If you don’t move the pointer along the
input array, you’ll get something like:
there are 10 floats less than 50: 31.94 31.94 31.94 ...etc...
If you don’t move the pointers by the right number of bytes, you might get something like:
there are 6 floats less than 50: 127.76 36.10 0.00 ...etc...
If you moved the
input pointer right, but forgot to move the
output pointer along:
there are 6 floats less than 50: 19.60 0.00 0.00 ...etc...
If you moved BOTH pointers every iteration:
there are 6 floats less than 50: 31.94 0.00 36.10 ...etc...
If you didn’t count properly, or maybe you didn’t respond to the predicate properly:
there are 0 floats less than 50:
Please make sure the driver (the
main function) is the default one I gave you before you submit.
Then submit as usual.