Pointers to Functions --- the C programming lan...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINES 5000 /* max #lines to be sorted */
char *lineptr[MAXLINES]; /*pointers to text lines */


int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);


void qsort(void *lineptr[], int left, int right, int(*comp)(void *, void *));


int numcmp(char *, char *);


/* sort input lines */
main(int argc, char *argv[])
{
  int nlines; /*number of input lines read */
  int numeric = 0; /* 1 if numeric sort */


  if(argc > 1 && strcmp(argv[1], "-n") == 0)
    numberic = 1;
  if ((nlines = readlines(lineptr, MAXLINES)) >= 0)
    {
      qsort((void **) lineptr, 0, nlines-1,
            (int (*)(void *, void *))(numberic ? numcmp : strcmp));
      writelines(lineptr, nlines);
      return 0;
    }
  else
    {
      printf("input too big to sort\n");
      return 1;
    }
}

/* qsort: sort v[left] ... v[right] into increasing order */
void qsort(void *v[], int left, int right, int (*comp)(void *, void *))
{
  int i, last;
  void swap(void *v[], int, int);

  if (left >= right) /* do nothing if array contains */
    return;          /* fewer than two elements */

  swap(v, left, (left + right)/2);
  last = left;
  for(i = left +1; i <= right; i++)
    if ((*comp)(v[i],v[left]) < 0)
      swap(v, ++last, i);
  swap(v, left, last);
  qsort(v, left, last-1, comp);
  qsort(v, last+1, right, comp);
}

/* numcmp: compare s1 and s2 numerically */
int numcmp(char *s1, char *s2)
{
  double v1, v2;

  v1 = atof(s1);
  v2 = atof(s2);
  if (v1 < v2)
    return -1;
  else if (v1 > v2)
    return 1;
  else
    return 0;
}

void swap(void *v[], int i, int j)
{
  void *temp;

  temp = v[i];
  v[i] = v[j];
  v[j] = temp;
}


In C, a function itself is not a variable, but it is possible to define pointers to functions, which can be assigned, placed in arrays, passed to functions, returned by functions, and so on. 

In the call to qsort, strcmp and numcmp are addresses of functions. Since they are known to be functions, the & operator is not necessary, in the same way that it is not needed before an array name.

We have written qsort so it can process any data type, not just character strings. As indicated by the function prototype, qsort expects an array of pointers, two integers, and a function with two pointer arguments. The generic pointer type void * is used for the pointer arguments. Any pointer can be cast to void * and back again without loss of information, so we can call qsort by casting arguments to void *. The elaborate cast of the function argument casts the arguments of the comparison function. These will generally have no effect on actual representation, but assure the compiler that all is well.

The declarations should be studied with some care. The fourth parameter of qsort is 

int (*comp)(void *, void *)

which says that comp is a pointer to a function that has two void * arguments and returns an int.

The use of comp in the line

if ((*comp)(v[i], v[left]) < 0)

is consistent with the declaration: comp is a pointer to a function, *comp is the function, and 

(*comp)(v[i],v[left])

is the call to it. The parentheses are needed so the components are correctly associated; without them,

int *comp(void *, void *) /* WRONG */

says that comp is a function returning a pointer to an int, which is very different.

We have already shown strcmp, which compares two strings. Here is numcmp, which compares two strings on a leading numeric value, computed by calling atof.

你可能感兴趣的:(c,读书笔记)