Solution for Exercise 09_09-qsortptrs.c

09_09-qsortptrs.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int compare(const void *a, const void *b)
{
	char **alpha = (char **)a;
	char **beta = (char **)b;
	
	return( strcmp( *alpha, *beta ) );
}

int main()
{
	char *weekdays[7] = {
		"Sunday", "Monday", "Tuesday",
		"Wednesday", "Thursday",
		"Friday", "Saturday"
	};
	int x,size;

	/* obtain array size */
	size = sizeof(weekdays)/sizeof(weekdays[0]);

	/* output original array */
	puts("Unsorted:");
	for( x=0; x<size; x++ )
		printf(" %s\n",weekdays[x]);

	/* quick sort the array */
	qsort( weekdays, size, sizeof(char *), compare );

	/* output the sorted result */
	puts("Sorted:");
	for( x=0; x<size; x++ )
		printf(" %s\n",weekdays[x]);

	return 0;
}

Output

Unsorted:
 Sunday
 Monday
 Tuesday
 Wednesday
 Thursday
 Friday
 Saturday
Sorted:
 Friday
 Monday
 Saturday
 Sunday
 Thursday
 Tuesday
 Wednesday

Notes

* In the main() function, the nested loop is no longer needed, but the size of the array is. So I added int variable size, which obtains the pointer array's size: size = sizeof(weekdays)/sizeof(weekdays[0]);

* The other update to the main() function is including the qsort() call. This function and its fourth argument are covered in the book.

* The truly bizarre things in this code happen in the compare() function. The key to understanding this function, and its horrid use of double-pointers, is that the data it deals with are addresses of addresses (an array of strings).

* Before screaming at the solution's compare() function, consider the qsort() function's call: qsort( weekdays, size, sizeof(char *), compare ); The first argument is the weekdays array, which is the address of a series of pointers (addresses).

* As it's a *v[] type of data being passed, recognize that *v[] can also be written as **v. This relationship explains the typecasting required in the compare() function.

* The compare() function is required to use void data types for its two pointer arguments.

* To make the strcmp() function readable, I use two double-pointer char variables to hold the values (strings) passed: char **alpha and char **beta. Each is assigned to the void pointers passed, a and b.

* To assign the double-pointer variables alpha and beta to the void pointers a and b, typecasting is required: char **alpha = (char **)a; and char **beta = (char **)b;

* After the void pointers are assigned to their proper data types, the strcmp() function is used to compare the strings and return the result of the comparison. At this point, alpha and beta hold addresses. Therefore, to compare their string values each variable must be dereferenced in the strcmp() function: strcmp( *alpha, *beta )