|
Page 3 of 5 Note that, in doing this, in compare() we had to introduce the casting of the void pointer types passed to the actual type being sorted. But, as we' see later that' okay. And since what is being passed to bubble() is still a pointer to an array of integers, we had to cast these pointers to void pointers when we passed them as parameters in our call to compare(). We now address the problem of what we pass to bubble(). We want to make the first parameter of that function a void pointer also. But, that means that within bubble() we need to do something about the variable t, which is currently an integer. Also, where we use t = p[j-1]; the type of p[j-1] needs to be known in order to know how many bytes to copy to the variable t (or whatever we replace t with). Currently, in bubble_4.c, knowledge within bubble() as to the type of the data being sorted (and hence the size of each individual element) is obtained from the fact that the first parameter is a pointer to type integer. If we are going to be able to use bubble() to sort any type of data, we need to make that pointer a pointer to type void. But, in doing so we are going to lose information concerning the size of individual elements within the array. So, in bubble_5.c we will add a separate parameter to handle this size information. These changes, from bubble4.c to bubble5.c are, perhaps, a bit more extensive than those we have made in the past. So, compare the two modules carefully for differences. /*---------------------- bubble5.c ---------------------------*/ /* Program bubble_5.c from PTRTUT10.HTM 6/13/97 */ #include <stdio.h> #include <string.h> long arr[10] = { 3,6,1,2,3,8,4,1,7,2}; void bubble(void *p, size_t width, int N); int compare(void *m, void *n); int main(void) { int i; putchar('\n'); for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } bubble(arr, sizeof(long), 10); putchar('\n'); for (i = 0; i < 10; i++) { printf("%ld ", arr[i]); } return 0; } void bubble(void *p, size_t width, int N) { int i, j; unsigned char buf[4]; unsigned char *bp = p; for (i = N-1; i >= 0; i--) { for (j = 1; j <= i; j++) { if (compare((void *)(bp + width*(j-1)), (void *)(bp + j*width))) /* 1 */ { /* t = p[j-1]; */ memcpy(buf, bp + width*(j-1), width); /* p[j-1] = p[j]; */ memcpy(bp + width*(j-1), bp + j*width , width); /* p[j] = t; */ memcpy(bp + j*width, buf, width); } } } } int compare(void *m, void *n) { long *m1, *n1; m1 = (long *)m; n1 = (long *)n; return (*m1 > *n1); } /*--------------------- end of bubble5.c ---------------------*/
Note that I have changed the data type of the array from int to long to illustrate the changes needed in the compare() function. Within bubble() I' done away with the ariable t (which we would have had to change from type int to type long). I have added buffer of size 4 unsigned characters, which is the size needed to hold a long (this will hange again in future modifications to this code). The unsigned character pointer *bp is sed to point to the base of the array to be sorted, i.e. to the first element of that array. We also had to modify what we passed to compare(), and how we do the swapping of lements that the comparison indicates need swapping. Use of memcpy() and pointer otation instead of array notation work towards this reduction in type sensitivity. Again, making a careful comparison of bubble5.c with bubble4.c can result in improved understanding of what is happening and why.
|